2
2
//!
3
3
//! This is adapted from `gimli/crates/examples/src/bin/simple.rs`.
4
4
5
- use gimli:: Reader as _;
6
5
use object:: { Object , ObjectSection } ;
7
6
use std:: collections:: HashSet ;
8
7
use std:: { borrow, error, fs} ;
@@ -29,6 +28,22 @@ impl BkeyTypes {
29
28
}
30
29
}
31
30
31
+ impl std:: fmt:: Display for BkeyTypes {
32
+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
33
+ for bkey in self . 0 . iter ( ) {
34
+ for memb in bkey. members . iter ( ) {
35
+ writeln ! (
36
+ f,
37
+ "{} {} {} {}" ,
38
+ bkey. name, memb. name, memb. size, memb. offset
39
+ ) ?;
40
+ }
41
+ writeln ! ( f) ?;
42
+ }
43
+ Ok ( ( ) )
44
+ }
45
+ }
46
+
32
47
#[ derive( Debug ) ]
33
48
pub struct BchStruct {
34
49
name : String ,
@@ -53,33 +68,13 @@ pub struct BchMember {
53
68
offset : u64 ,
54
69
}
55
70
56
- // This is a simple wrapper around `object::read::RelocationMap` that implements
57
- // `gimli::read::Relocate` for use with `gimli::RelocateReader`.
58
- // You only need this if you are parsing relocatable object files.
59
- #[ derive( Debug , Default ) ]
60
- struct RelocationMap ( object:: read:: RelocationMap ) ;
61
-
62
- impl < ' a > gimli:: read:: Relocate for & ' a RelocationMap {
63
- fn relocate_address ( & self , offset : usize , value : u64 ) -> gimli:: Result < u64 > {
64
- Ok ( self . 0 . relocate ( offset as u64 , value) )
65
- }
66
-
67
- fn relocate_offset ( & self , offset : usize , value : usize ) -> gimli:: Result < usize > {
68
- <usize as gimli:: ReaderOffset >:: from_u64 ( self . 0 . relocate ( offset as u64 , value as u64 ) )
69
- }
70
- }
71
-
72
71
// The section data that will be stored in `DwarfSections` and `DwarfPackageSections`.
73
72
#[ derive( Default ) ]
74
73
struct Section < ' data > {
75
74
data : borrow:: Cow < ' data , [ u8 ] > ,
76
- relocations : RelocationMap ,
77
75
}
78
76
79
- // The reader type that will be stored in `Dwarf` and `DwarfPackage`.
80
- // If you don't need relocations, you can use `gimli::EndianSlice` directly.
81
- type Reader < ' data > =
82
- gimli:: RelocateReader < gimli:: EndianSlice < ' data , gimli:: RunTimeEndian > , & ' data RelocationMap > ;
77
+ type Reader < ' data > = gimli:: EndianSlice < ' data , gimli:: RunTimeEndian > ;
83
78
84
79
fn process_file (
85
80
object : & object:: File ,
@@ -99,27 +94,17 @@ fn process_file(
99
94
Ok ( match object. section_by_name ( name) {
100
95
Some ( section) => Section {
101
96
data : section. uncompressed_data ( ) ?,
102
- relocations : section. relocation_map ( ) . map ( RelocationMap ) ?,
103
97
} ,
104
98
None => Default :: default ( ) ,
105
99
} )
106
100
}
107
101
108
- // Borrow a `Section` to create a `Reader`.
109
- fn borrow_section < ' data > (
110
- section : & ' data Section < ' data > ,
111
- endian : gimli:: RunTimeEndian ,
112
- ) -> Reader < ' data > {
113
- let slice = gimli:: EndianSlice :: new ( borrow:: Cow :: as_ref ( & section. data ) , endian) ;
114
- gimli:: RelocateReader :: new ( slice, & section. relocations )
115
- }
116
-
117
- // Load all of the sections.
118
102
let dwarf_sections = gimli:: DwarfSections :: load ( |id| load_section ( object, id. name ( ) ) ) ?;
119
103
120
104
// Create `Reader`s for all of the sections and do preliminary parsing.
121
105
// Alternatively, we could have used `Dwarf::load` with an owned type such as `EndianRcSlice`.
122
- let dwarf = dwarf_sections. borrow ( |section| borrow_section ( section, endian) ) ;
106
+ let dwarf = dwarf_sections
107
+ . borrow ( |section| gimli:: EndianSlice :: new ( borrow:: Cow :: as_ref ( & section. data ) , endian) ) ;
123
108
124
109
let mut bkey_types = HashSet :: new ( ) ;
125
110
load_bkey_types ( & mut bkey_types) ;
@@ -167,6 +152,30 @@ enum CompType {
167
152
Struct ,
168
153
}
169
154
155
+ /// Used to keep track of info needed for structs that contain
156
+ /// other compound types.
157
+ struct ParentInfo < ' a > {
158
+ ty : CompType ,
159
+ starting_offset : u64 ,
160
+ member_prefix : & ' a str ,
161
+ }
162
+
163
+ fn entry_name (
164
+ dwarf : & gimli:: Dwarf < Reader > ,
165
+ unit : & gimli:: Unit < Reader > ,
166
+ entry : & gimli:: DebuggingInformationEntry < Reader > ,
167
+ ) -> Option < String > {
168
+ entry. attr ( gimli:: DW_AT_name ) . ok ( ) ?. and_then ( |name| {
169
+ Some (
170
+ dwarf
171
+ . attr_string ( unit, name. value ( ) )
172
+ . ok ( ) ?
173
+ . to_string_lossy ( )
174
+ . into_owned ( ) ,
175
+ )
176
+ } )
177
+ }
178
+
170
179
fn process_tree (
171
180
dwarf : & gimli:: Dwarf < Reader > ,
172
181
unit : & gimli:: Unit < Reader > ,
@@ -176,15 +185,18 @@ fn process_tree(
176
185
) -> gimli:: Result < ( ) > {
177
186
let entry = node. entry ( ) ;
178
187
if entry. tag ( ) == gimli:: DW_TAG_structure_type {
179
- if let Some ( name) = entry. attr ( gimli:: DW_AT_name ) ? {
180
- if let Ok ( name) = dwarf. attr_string ( unit, name. value ( ) ) {
181
- let name = name. to_string_lossy ( ) ?. into_owned ( ) ;
182
- if bkey_types. remove ( & name. clone ( ) ) {
183
- let mut members: Vec < BchMember > = Vec :: new ( ) ;
184
- process_compound_type ( dwarf, unit, node, & mut members, 0 , CompType :: Struct ) ?;
185
- struct_list. 0 . push ( BchStruct { name, members } ) ;
186
- }
187
- }
188
+ let name = entry_name ( dwarf, unit, entry) ;
189
+ let Some ( name) = name else { return Ok ( ( ) ) ; } ;
190
+
191
+ if bkey_types. remove ( & name) {
192
+ let mut members: Vec < BchMember > = Vec :: new ( ) ;
193
+ let parent_info = ParentInfo {
194
+ ty : CompType :: Struct ,
195
+ starting_offset : 0 ,
196
+ member_prefix : "" ,
197
+ } ;
198
+ process_compound_type ( dwarf, unit, node, & mut members, & parent_info) ?;
199
+ struct_list. 0 . push ( BchStruct { name, members } ) ;
188
200
}
189
201
} else {
190
202
let mut children = node. children ( ) ;
@@ -200,12 +212,11 @@ fn process_compound_type(
200
212
unit : & gimli:: Unit < Reader > ,
201
213
node : gimli:: EntriesTreeNode < Reader > ,
202
214
members : & mut Vec < BchMember > ,
203
- starting_offset : u64 ,
204
- comp : CompType ,
215
+ parent : & ParentInfo ,
205
216
) -> gimli:: Result < ( ) > {
206
217
let mut children = node. children ( ) ;
207
218
while let Some ( child) = children. next ( ) ? {
208
- process_comp_member ( dwarf, unit, child, members, starting_offset , comp ) ?;
219
+ process_comp_member ( dwarf, unit, child, members, parent ) ?;
209
220
}
210
221
211
222
Ok ( ( ) )
@@ -239,38 +250,51 @@ fn process_comp_member(
239
250
unit : & gimli:: Unit < Reader > ,
240
251
node : gimli:: EntriesTreeNode < Reader > ,
241
252
members : & mut Vec < BchMember > ,
242
- starting_offset : u64 ,
243
- comp : CompType ,
253
+ parent : & ParentInfo ,
244
254
) -> gimli:: Result < ( ) > {
245
255
let entry = node. entry ( ) . clone ( ) ;
246
256
247
- let offset = match comp {
257
+ let Some ( offset) = ( match parent . ty {
248
258
CompType :: Union => Some ( 0 ) ,
249
259
CompType :: Struct => entry
250
260
. attr ( gimli:: DW_AT_data_member_location ) ?
251
261
. and_then ( |offset| offset. value ( ) . udata_value ( ) ) ,
252
- } ;
253
- let Some ( offset) = offset else {
262
+ } ) else {
254
263
return Ok ( ( ) ) ;
255
264
} ;
256
265
266
+ let name = entry_name ( dwarf, unit, & entry) ;
267
+
257
268
if let Some ( ( ref_type, comp) ) = get_comp_ref ( unit, & entry) {
269
+ let prefix = if let Some ( ref name) = name {
270
+ let mut prefix = name. clone ( ) ;
271
+ prefix. push ( '.' ) ;
272
+ prefix
273
+ } else {
274
+ String :: from ( "" )
275
+ } ;
276
+ let parent = ParentInfo {
277
+ ty : comp,
278
+ starting_offset : offset,
279
+ member_prefix : & prefix,
280
+ } ;
258
281
let mut tree = unit. entries_tree ( Some ( ref_type) ) ?;
259
- process_compound_type ( dwarf, unit, tree. root ( ) ?, members, offset, comp) ?;
282
+ process_compound_type ( dwarf, unit, tree. root ( ) ?, members, & parent) ?;
283
+
284
+ return Ok ( ( ) ) ;
260
285
} ;
261
286
262
287
let Some ( size) = get_size ( unit, & entry) else {
263
288
return Ok ( ( ) ) ;
264
289
} ;
265
290
266
- let name = entry. attr ( gimli:: DW_AT_name ) ?;
267
291
let Some ( name) = name else { return Ok ( ( ) ) } ;
268
- let name = dwarf . attr_string ( unit , name . value ( ) ) ? ;
269
- let name = name . to_string_lossy ( ) ? . into_owned ( ) ;
292
+ let mut name_with_prefix = String :: from ( parent . member_prefix ) ;
293
+ name_with_prefix . push_str ( & name ) ;
270
294
271
295
members. push ( BchMember {
272
- name,
273
- offset : offset + starting_offset,
296
+ name : name_with_prefix ,
297
+ offset : offset + parent . starting_offset ,
274
298
size,
275
299
} ) ;
276
300
@@ -285,13 +309,12 @@ fn get_size(
285
309
return size. udata_value ( ) ;
286
310
}
287
311
288
- if let Some ( ref_type) = entry. attr ( gimli:: DW_AT_type ) . ok ( ) ? {
289
- if let gimli:: AttributeValue :: UnitRef ( offset) = ref_type. value ( ) {
290
- let mut type_entry = unit. entries_at_offset ( offset) . ok ( ) ?;
291
- type_entry. next_entry ( ) . ok ( ) ?;
292
- if let Some ( t) = type_entry. current ( ) {
293
- return get_size ( unit, t) ;
294
- }
312
+ let ref_type = entry. attr ( gimli:: DW_AT_type ) . ok ( ) ??;
313
+ if let gimli:: AttributeValue :: UnitRef ( offset) = ref_type. value ( ) {
314
+ let mut type_entry = unit. entries_at_offset ( offset) . ok ( ) ?;
315
+ type_entry. next_entry ( ) . ok ( ) ?;
316
+ if let Some ( t) = type_entry. current ( ) {
317
+ return get_size ( unit, t) ;
295
318
}
296
319
}
297
320
@@ -301,21 +324,12 @@ fn get_size(
301
324
/// Return a list of the known bkey types.
302
325
pub fn get_bkey_type_info ( ) -> BkeyTypes {
303
326
let path = fs:: read_link ( "/proc/self/exe" ) . unwrap ( ) ;
304
-
305
327
let file = fs:: File :: open ( path) . unwrap ( ) ;
306
328
let mmap = unsafe { memmap2:: Mmap :: map ( & file) . unwrap ( ) } ;
307
329
let object = object:: File :: parse ( & * mmap) . unwrap ( ) ;
330
+
308
331
let mut struct_list = BkeyTypes :: new ( ) ;
309
332
process_file ( & object, & mut struct_list) . unwrap ( ) ;
310
333
311
- /*
312
- for s in struct_list.0.iter() {
313
- for m in s.members.iter() {
314
- println!("{} {} {} {}", s.name, m.name, m.offset, m.size);
315
- }
316
- println!("");
317
- }
318
- */
319
-
320
334
struct_list
321
335
}
0 commit comments