Skip to content

Commit e51ad4a

Browse files
committed
Move relative_address_base to samply-object
1 parent 2d858c1 commit e51ad4a

File tree

6 files changed

+70
-73
lines changed

6 files changed

+70
-73
lines changed

samply-object/src/object_ext.rs

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use object::{Object, ObjectSection};
2-
use uuid::Uuid;
3-
41
use debugid::DebugId;
2+
use object::{FileFlags, Object, ObjectSection};
3+
use uuid::Uuid;
54

65
use samply_debugid::{CodeId, DebugIdExt, ElfBuildId};
76

@@ -15,6 +14,40 @@ pub trait ObjectExt<'data>: Object<'data> {
1514
/// and falls back to hashing the first page of the text section otherwise.
1615
/// Returns None on failure.
1716
fn debug_id(&self) -> Option<DebugId>;
17+
18+
/// The "relative address base" is the base address which [`LookupAddress::Relative`]
19+
/// addresses are relative to. You start with an SVMA (a stated virtual memory address),
20+
/// you subtract the relative address base, and out comes a relative address.
21+
///
22+
/// This function computes that base address. It is defined as follows:
23+
///
24+
/// - For Windows binaries, the base address is the "image base address".
25+
/// - For mach-O binaries, the base address is the vmaddr of the __TEXT segment.
26+
/// - For ELF binaries, the base address is the vmaddr of the *first* segment,
27+
/// i.e. the vmaddr of the first "LOAD" ELF command.
28+
///
29+
/// In many cases, this base address is simply zero:
30+
///
31+
/// - ELF images of dynamic libraries (i.e. not executables) usually have a
32+
/// base address of zero.
33+
/// - Stand-alone mach-O dylibs usually have a base address of zero because their
34+
/// __TEXT segment is at address zero.
35+
/// - In PDBs, "RVAs" are relative addresses which are already relative to the
36+
/// image base.
37+
///
38+
/// However, in the following cases, the base address is usually non-zero:
39+
///
40+
/// - The "image base address" of Windows binaries is usually non-zero.
41+
/// - mach-O executable files (not dylibs) usually have their __TEXT segment at
42+
/// address 0x100000000.
43+
/// - mach-O libraries in the dyld shared cache have a __TEXT segment at some
44+
/// non-zero address in the cache.
45+
/// - ELF executables can have non-zero base addresses, e.g. 0x200000 or 0x400000.
46+
/// - Kernel ELF binaries ("vmlinux") have a large base address such as
47+
/// 0xffffffff81000000. Moreover, the base address seems to coincide with the
48+
/// vmaddr of the .text section, which is readily-available in perf.data files
49+
/// (in a synthetic mapping called "[kernel.kallsyms]_text").
50+
fn samply_relative_address_base(&self) -> u64;
1851
}
1952

2053
// Blanket implementation
@@ -66,4 +99,24 @@ where
6699

67100
None
68101
}
102+
103+
fn samply_relative_address_base(&self) -> u64 {
104+
use object::read::ObjectSegment;
105+
if let Some(text_segment) = self.segments().find(|s| s.name() == Ok(Some("__TEXT"))) {
106+
// This is a mach-O image. "Relative addresses" are relative to the
107+
// vmaddr of the __TEXT segment.
108+
return text_segment.address();
109+
}
110+
111+
if let FileFlags::Elf { .. } = self.flags() {
112+
// This is an ELF image. "Relative addresses" are relative to the
113+
// vmaddr of the first segment (the first LOAD command).
114+
if let Some(first_segment) = self.segments().next() {
115+
return first_segment.address();
116+
}
117+
}
118+
119+
// For PE binaries, relative_address_base() returns the image base address.
120+
self.relative_address_base()
121+
}
69122
}

samply-symbols/src/binary_image.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,7 @@ use crate::error::Error;
1010
use crate::jitdump::{debug_id_and_code_id_for_jitdump, JitDumpIndex};
1111
use crate::macho::{DyldCacheFileData, MachOData, MachOFatArchiveMemberData};
1212
use crate::shared::{
13-
relative_address_base, FileAndPathHelperError, FileContents, FileContentsWrapper, LibraryInfo,
14-
RangeReadRef,
13+
FileAndPathHelperError, FileContents, FileContentsWrapper, LibraryInfo, RangeReadRef,
1514
};
1615

1716
#[derive(thiserror::Error, Debug)]
@@ -244,7 +243,7 @@ impl<F: FileContents> BinaryImageInner<F> {
244243

245244
// Translate start_address from a "relative address" into an
246245
// SVMA ("stated virtual memory address").
247-
let image_base = relative_address_base(&object);
246+
let image_base = object.samply_relative_address_base();
248247
let start_svma = image_base + u64::from(start_address);
249248

250249
// Find the section and segment which contains our start_svma.

samply-symbols/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -252,11 +252,11 @@ pub use crate::macho::FatArchiveMember;
252252
pub use crate::mapped_path::MappedPath;
253253
pub use crate::path_interner::PathInterner;
254254
pub use crate::shared::{
255-
relative_address_base, AddressInfo, CandidatePathInfo, ExternalFileAddressInFileRef,
256-
ExternalFileAddressRef, ExternalFileRef, FileAndPathHelper, FileAndPathHelperError,
257-
FileAndPathHelperResult, FileContents, FileContentsWrapper, FileLocation, FrameDebugInfo,
258-
FramesLookupResult, LibraryInfo, LookupAddress, MultiArchDisambiguator, OptionallySendFuture,
259-
SymbolInfo, SyncAddressInfo,
255+
AddressInfo, CandidatePathInfo, ExternalFileAddressInFileRef, ExternalFileAddressRef,
256+
ExternalFileRef, FileAndPathHelper, FileAndPathHelperError, FileAndPathHelperResult,
257+
FileContents, FileContentsWrapper, FileLocation, FrameDebugInfo, FramesLookupResult,
258+
LibraryInfo, LookupAddress, MultiArchDisambiguator, OptionallySendFuture, SymbolInfo,
259+
SyncAddressInfo,
260260
};
261261
pub use crate::source_file_path::{SourceFilePath, SourceFilePathHandle, SourceFilePathIndex};
262262
pub use crate::symbol_map::{AccessPatternHint, SymbolMap, SymbolMapTrait};

samply-symbols/src/shared.rs

Lines changed: 0 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ use std::sync::Arc;
1010
use bitvec::{bitvec, prelude::BitVec};
1111
use debugid::DebugId;
1212
use object::read::ReadRef;
13-
use object::FileFlags;
1413
use samply_debugid::{CodeId, ElfBuildId};
1514

1615
use crate::symbol_map::SymbolMapTrait;
@@ -364,61 +363,6 @@ pub trait FileLocation: Clone + Display {
364363
fn location_for_dwp(&self) -> Option<Self>;
365364
}
366365

367-
/// The "relative address base" is the base address which [`LookupAddress::Relative`]
368-
/// addresses are relative to. You start with an SVMA (a stated virtual memory address),
369-
/// you subtract the relative address base, and out comes a relative address.
370-
///
371-
/// This function computes that base address. It is defined as follows:
372-
///
373-
/// - For Windows binaries, the base address is the "image base address".
374-
/// - For mach-O binaries, the base address is the vmaddr of the __TEXT segment.
375-
/// - For ELF binaries, the base address is the vmaddr of the *first* segment,
376-
/// i.e. the vmaddr of the first "LOAD" ELF command.
377-
///
378-
/// In many cases, this base address is simply zero:
379-
///
380-
/// - ELF images of dynamic libraries (i.e. not executables) usually have a
381-
/// base address of zero.
382-
/// - Stand-alone mach-O dylibs usually have a base address of zero because their
383-
/// __TEXT segment is at address zero.
384-
/// - In PDBs, "RVAs" are relative addresses which are already relative to the
385-
/// image base.
386-
///
387-
/// However, in the following cases, the base address is usually non-zero:
388-
///
389-
/// - The "image base address" of Windows binaries is usually non-zero.
390-
/// - mach-O executable files (not dylibs) usually have their __TEXT segment at
391-
/// address 0x100000000.
392-
/// - mach-O libraries in the dyld shared cache have a __TEXT segment at some
393-
/// non-zero address in the cache.
394-
/// - ELF executables can have non-zero base addresses, e.g. 0x200000 or 0x400000.
395-
/// - Kernel ELF binaries ("vmlinux") have a large base address such as
396-
/// 0xffffffff81000000. Moreover, the base address seems to coincide with the
397-
/// vmaddr of the .text section, which is readily-available in perf.data files
398-
/// (in a synthetic mapping called "[kernel.kallsyms]_text").
399-
pub fn relative_address_base<'data>(object_file: &impl object::Object<'data>) -> u64 {
400-
use object::read::ObjectSegment;
401-
if let Some(text_segment) = object_file
402-
.segments()
403-
.find(|s| s.name() == Ok(Some("__TEXT")))
404-
{
405-
// This is a mach-O image. "Relative addresses" are relative to the
406-
// vmaddr of the __TEXT segment.
407-
return text_segment.address();
408-
}
409-
410-
if let FileFlags::Elf { .. } = object_file.flags() {
411-
// This is an ELF image. "Relative addresses" are relative to the
412-
// vmaddr of the first segment (the first LOAD command).
413-
if let Some(first_segment) = object_file.segments().next() {
414-
return first_segment.address();
415-
}
416-
}
417-
418-
// For PE binaries, relative_address_base() returns the image base address.
419-
object_file.relative_address_base()
420-
}
421-
422366
/// The symbol for a function.
423367
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
424368
pub struct SymbolInfo {

samply-symbols/src/symbol_map_object.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ use gimli::{EndianSlice, RunTimeEndian};
99
use object::{
1010
ObjectMap, ObjectSection, ObjectSegment, SectionFlags, SectionIndex, SectionKind, SymbolKind,
1111
};
12+
use samply_object::ObjectExt;
1213
use yoke::Yoke;
1314
use yoke_derive::Yokeable;
1415

1516
use crate::dwarf::convert_frames;
1617
use crate::generation::SymbolMapGeneration;
1718
use crate::shared::{
18-
relative_address_base, ExternalFileAddressInFileRef, ExternalFileAddressRef, ExternalFileRef,
19-
FramesLookupResult, LookupAddress, SymbolInfo,
19+
ExternalFileAddressInFileRef, ExternalFileAddressRef, ExternalFileRef, FramesLookupResult,
20+
LookupAddress, SymbolInfo,
2021
};
2122
use crate::symbol_map::{
2223
GetInnerSymbolMap, GetInnerSymbolMapWithLookupFramesExt, SymbolMapTrait,
@@ -675,7 +676,7 @@ impl<'a, FC: FileContents + 'static> ObjectSymbolMapInnerWrapper<'a, FC> {
675676
Symbol: object::ObjectSymbol<'a> + Send + Sync + 'a,
676677
DDM: DwoDwarfMaker<FC> + Sync,
677678
{
678-
let base_address = relative_address_base(object_file);
679+
let base_address = object_file.samply_relative_address_base();
679680
let list = SymbolList::new(
680681
object_file,
681682
base_address,

samply/src/linux_shared/converter.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use object::{CompressedFileRange, CompressionFormat, Object, ObjectSection};
2828
use samply_debugid::DebugIdExt;
2929
use samply_object::ObjectExt;
3030
use wholesym::samply_symbols::demangle_any;
31-
use wholesym::{samply_symbols, CodeId, ElfBuildId};
31+
use wholesym::{CodeId, ElfBuildId};
3232

3333
use super::avma_range::AvmaRange;
3434
use super::convert_regs::ConvertRegs;
@@ -1644,7 +1644,7 @@ where
16441644
}
16451645
}
16461646

1647-
let base_svma = samply_symbols::relative_address_base(file);
1647+
let base_svma = file.samply_relative_address_base();
16481648
let text = file.section_by_name(".text");
16491649
let eh_frame = file.section_by_name(".eh_frame");
16501650
let got = file.section_by_name(".got");
@@ -1922,7 +1922,7 @@ impl MappingInfo {
19221922
self.avma_range.start(),
19231923
self.avma_range.size(),
19241924
)?;
1925-
let base_svma = samply_symbols::relative_address_base(file);
1925+
let base_svma = file.samply_relative_address_base();
19261926
base_svma.wrapping_add(bias)
19271927
}
19281928
};

0 commit comments

Comments
 (0)