1
1
use std:: error:: Error ;
2
2
3
3
use addr2line:: {
4
- gimli:: { EndianRcSlice , RunTimeEndian } ,
5
- object:: { read:: File , Object , ObjectSegment , ObjectSymbol } ,
4
+ gimli:: { self , Dwarf , EndianSlice , LittleEndian , SectionId } ,
6
5
Context ,
7
6
LookupResult ,
8
7
} ;
8
+ use object:: { read:: File , Object , ObjectSection , ObjectSegment , ObjectSymbol } ;
9
9
10
10
// Wrapper around addr2line that allows to look up function names and
11
11
// locations from a given address.
12
12
pub ( 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 > > ,
15
15
}
16
16
17
17
impl < ' sym > Symbols < ' sym > {
18
18
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
+ ) ?;
21
29
22
- Ok ( Self { file, ctx } )
30
+ let ctx = Context :: from_dwarf ( dwarf) ?;
31
+
32
+ Ok ( Self { object, ctx } )
23
33
}
24
34
25
35
/// Returns the name of the function at the given address, if one can be
26
36
/// found.
27
37
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| {
30
40
( segment. address ( ) ..( segment. address ( ) + segment. size ( ) ) ) . contains ( & addr)
31
41
} ) {
32
42
return None ;
33
43
}
34
44
35
45
// 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
39
49
// directly
40
- // 4. return a demangled function name, if one was found
50
+ // 4. Return a demangled function name, if one was found
41
51
let mut frames = match self . ctx . find_frames ( addr) {
42
52
LookupResult :: Output ( result) => result. unwrap ( ) ,
43
53
LookupResult :: Load { .. } => unimplemented ! ( ) ,
@@ -55,7 +65,7 @@ impl<'sym> Symbols<'sym> {
55
65
. or_else ( || {
56
66
// Don't use `symbol_map().get(addr)` - it's documentation says "Get the symbol
57
67
// 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| {
59
69
( symbol. address ( ) ..=( symbol. address ( ) + symbol. size ( ) ) ) . contains ( & addr)
60
70
} ) ;
61
71
0 commit comments