11use std:: error:: Error ;
22
33use addr2line:: {
4- gimli:: { EndianRcSlice , RunTimeEndian } ,
5- object:: { read:: File , Object , ObjectSegment , ObjectSymbol } ,
4+ gimli:: { self , Dwarf , EndianSlice , LittleEndian , SectionId } ,
65 Context ,
76 LookupResult ,
87} ;
8+ use object:: { read:: File , Object , ObjectSection , ObjectSegment , ObjectSymbol } ;
99
1010// Wrapper around addr2line that allows to look up function names and
1111// locations from a given address.
1212pub ( crate ) struct Symbols < ' sym > {
13- file : File < ' sym , & ' sym [ u8 ] > ,
14- ctx : Context < EndianRcSlice < RunTimeEndian > > ,
13+ object : File < ' sym , & ' sym [ u8 ] > ,
14+ ctx : Context < EndianSlice < ' sym , LittleEndian > > ,
1515}
1616
1717impl < ' sym > Symbols < ' sym > {
1818 pub fn try_from ( bytes : & ' sym [ u8 ] ) -> Result < Self , Box < dyn Error > > {
19- let file = File :: parse ( bytes) ?;
20- let ctx = Context :: new ( & file) ?;
19+ let object = File :: parse ( bytes) ?;
20+ let dwarf = Dwarf :: load (
21+ |id : SectionId | -> Result < EndianSlice < ' sym , LittleEndian > , gimli:: Error > {
22+ let data = object
23+ . section_by_name ( id. name ( ) )
24+ . and_then ( |section| section. data ( ) . ok ( ) )
25+ . unwrap_or ( & [ ] [ ..] ) ;
26+ Ok ( EndianSlice :: new ( data, LittleEndian ) )
27+ } ,
28+ ) ?;
2129
22- Ok ( Self { file, ctx } )
30+ let ctx = Context :: from_dwarf ( dwarf) ?;
31+
32+ Ok ( Self { object, ctx } )
2333 }
2434
2535 /// Returns the name of the function at the given address, if one can be
2636 /// found.
2737 pub fn get_name ( & self , addr : u64 ) -> Option < String > {
28- // no need to try an address not contained in any segment
29- if !self . file . segments ( ) . any ( |segment| {
38+ // No need to try an address not contained in any segment:
39+ if !self . object . segments ( ) . any ( |segment| {
3040 ( segment. address ( ) ..( segment. address ( ) + segment. size ( ) ) ) . contains ( & addr)
3141 } ) {
3242 return None ;
3343 }
3444
3545 // The basic steps here are:
36- // 1. find which frame `addr` is in
37- // 2. look up and demangle the function name
38- // 3. if no function name is found, try to look it up in the object file
46+ // 1. Find which frame `addr` is in
47+ // 2. Look up and demangle the function name
48+ // 3. If no function name is found, try to look it up in the object file
3949 // directly
40- // 4. return a demangled function name, if one was found
50+ // 4. Return a demangled function name, if one was found
4151 let mut frames = match self . ctx . find_frames ( addr) {
4252 LookupResult :: Output ( result) => result. unwrap ( ) ,
4353 LookupResult :: Load { .. } => unimplemented ! ( ) ,
@@ -55,7 +65,7 @@ impl<'sym> Symbols<'sym> {
5565 . or_else ( || {
5666 // Don't use `symbol_map().get(addr)` - it's documentation says "Get the symbol
5767 // before the given address." which might be totally wrong
58- let symbol = self . file . symbols ( ) . find ( |symbol| {
68+ let symbol = self . object . symbols ( ) . find ( |symbol| {
5969 ( symbol. address ( ) ..=( symbol. address ( ) + symbol. size ( ) ) ) . contains ( & addr)
6070 } ) ;
6171
0 commit comments