Skip to content

Commit

Permalink
Add a synthetic symbol for the entry point.
Browse files Browse the repository at this point in the history
Before: https://share.firefox.dev/3Iw19eq
After: https://share.firefox.dev/3wGBXPA

On my version of Ubuntu, the caller of dl_start in ld-linux-x86-64.so.2
didn't have a synthetic symbol - it was just a free-standing address.
The address is inside the "entry point" function. In the .eh_frame
unwind information, this part of this binary is not covered by an FDE, so
we didn't create a synthetic symbol based on unwind information in the past.

With this commit, we use the binary's entry point address to create another
synthetic symbol.

In the Firefox profiler, this allows the root function to be double-clicked
and its assembly code to be inspected. With just the address we weren't
able to do that because we didn't know where to start and stop disassembling.

To capture a profile like the one in the links above, use
`cargo run --release -- record --iteration-count 2 -r 10000 rustup check`
and then look at the thread for the second invocation.
The first invocation seems to be missing the very start of the process,
i.e. it looks the sample data is only captured after `dl_start` has
already finished running.
  • Loading branch information
mstange committed Mar 9, 2024
1 parent 2a1cf89 commit 339e463
Showing 1 changed file with 17 additions and 3 deletions.
20 changes: 17 additions & 3 deletions samply-symbols/src/symbol_map_object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@ impl<'data, R: ReadRef<'data> + Send + Sync, FAC: FunctionAddressesComputer<'dat
}

enum FullSymbolListEntry<'a, Symbol: object::ObjectSymbol<'a>> {
/// A synthesized symbol for a function start address that's known
/// from some other information (not from the symbol table).
Synthesized,
/// A synthesized symbol for the entry point of the object.
SynthesizedEntryPoint,
Symbol(Symbol),
Export(object::Export<'a>),
EndAddress,
Expand All @@ -100,6 +104,7 @@ impl<'a, Symbol: object::ObjectSymbol<'a>> std::fmt::Debug for FullSymbolListEnt
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Synthesized => write!(f, "Synthesized"),
Self::SynthesizedEntryPoint => write!(f, "SynthesizedEntryPoint"),
Self::Symbol(arg0) => f
.debug_tuple("Symbol")
.field(&arg0.name().unwrap())
Expand All @@ -117,6 +122,7 @@ impl<'a, Symbol: object::ObjectSymbol<'a>> FullSymbolListEntry<'a, Symbol> {
fn name(&self, addr: u32) -> Result<Cow<'a, str>, ()> {
match self {
FullSymbolListEntry::Synthesized => Ok(format!("fun_{addr:x}").into()),
FullSymbolListEntry::SynthesizedEntryPoint => Ok("EntryPoint".into()),
FullSymbolListEntry::Symbol(symbol) => match symbol.name_bytes() {
Ok(name) => Ok(String::from_utf8_lossy(name)),
Err(_) => Err(()),
Expand Down Expand Up @@ -304,7 +310,15 @@ where
);
}

// 5. End addresses from text section ends
// 5. A placeholder symbol for the entry point.
if let Some(entry_point) = object_file.entry().checked_sub(base_address) {
entries.push((
entry_point as u32,
FullSymbolListEntry::SynthesizedEntryPoint,
));
}

// 6. End addresses from text section ends
// These entries serve to "terminate" the last function of each section,
// so that addresses in the following section are not considered
// to be part of the last function of that previous section.
Expand All @@ -320,7 +334,7 @@ where
}),
);

// 6. End addresses for sized symbols
// 7. End addresses for sized symbols
// These addresses serve to "terminate" functions symbols.
entries.extend(
object_file
Expand All @@ -342,7 +356,7 @@ where
}),
);

// 7. End addresses for known functions ends
// 8. End addresses for known functions ends
// These addresses serve to "terminate" functions from function_start_addresses.
// They come from .eh_frame or .pdata info, which has the function size.
if let Some(function_end_addresses) = function_end_addresses {
Expand Down

0 comments on commit 339e463

Please sign in to comment.