@@ -152,26 +152,23 @@ fn symbols_by_section(
152
152
arch : & dyn ObjArch ,
153
153
obj_file : & File < ' _ > ,
154
154
section : & ObjSection ,
155
+ section_symbols : & [ Symbol < ' _ , ' _ > ] ,
155
156
split_meta : Option < & SplitMeta > ,
156
157
name_counts : & mut HashMap < String , u32 > ,
157
158
) -> Result < Vec < ObjSymbol > > {
158
159
let mut result = Vec :: < ObjSymbol > :: new ( ) ;
159
- for symbol in obj_file . symbols ( ) {
160
+ for symbol in section_symbols {
160
161
if symbol. kind ( ) == SymbolKind :: Section {
161
162
continue ;
162
163
}
163
- if let Some ( index) = symbol. section ( ) . index ( ) {
164
- if index. 0 == section. orig_index {
165
- if symbol. is_local ( ) && section. kind == ObjSectionKind :: Code {
166
- // TODO strip local syms in diff?
167
- let name = symbol. name ( ) . context ( "Failed to process symbol name" ) ?;
168
- if symbol. size ( ) == 0 || name. starts_with ( "lbl_" ) {
169
- continue ;
170
- }
171
- }
172
- result. push ( to_obj_symbol ( arch, obj_file, & symbol, 0 , split_meta) ?) ;
164
+ if symbol. is_local ( ) && section. kind == ObjSectionKind :: Code {
165
+ // TODO strip local syms in diff?
166
+ let name = symbol. name ( ) . context ( "Failed to process symbol name" ) ?;
167
+ if symbol. size ( ) == 0 || name. starts_with ( "lbl_" ) {
168
+ continue ;
173
169
}
174
170
}
171
+ result. push ( to_obj_symbol ( arch, obj_file, symbol, 0 , split_meta) ?) ;
175
172
}
176
173
result. sort_by ( |a, b| a. address . cmp ( & b. address ) . then ( a. size . cmp ( & b. size ) ) ) ;
177
174
let mut iter = result. iter_mut ( ) . peekable ( ) ;
@@ -221,47 +218,71 @@ fn common_symbols(
221
218
. collect :: < Result < Vec < ObjSymbol > > > ( )
222
219
}
223
220
221
+ const LOW_PRIORITY_SYMBOLS : & [ & str ] =
222
+ & [ "__gnu_compiled_c" , "__gnu_compiled_cplusplus" , "gcc2_compiled." ] ;
223
+
224
+ fn best_symbol < ' r , ' data , ' file > (
225
+ symbols : & ' r [ Symbol < ' data , ' file > ] ,
226
+ address : u64 ,
227
+ ) -> Option < & ' r Symbol < ' data , ' file > > {
228
+ let closest_symbol_index = match symbols. binary_search_by_key ( & address, |s| s. address ( ) ) {
229
+ Ok ( index) => Some ( index) ,
230
+ Err ( index) => index. checked_sub ( 1 ) ,
231
+ } ?;
232
+ let mut best_symbol: Option < & ' r Symbol < ' data , ' file > > = None ;
233
+ for symbol in symbols. iter ( ) . skip ( closest_symbol_index) {
234
+ if symbol. address ( ) > address {
235
+ break ;
236
+ }
237
+ if symbol. kind ( ) == SymbolKind :: Section
238
+ || ( symbol. size ( ) > 0 && ( symbol. address ( ) + symbol. size ( ) ) <= address)
239
+ {
240
+ continue ;
241
+ }
242
+ // TODO priority ranking with visibility, etc
243
+ if let Some ( best) = best_symbol {
244
+ if LOW_PRIORITY_SYMBOLS . contains ( & best. name ( ) . unwrap_or_default ( ) )
245
+ && !LOW_PRIORITY_SYMBOLS . contains ( & symbol. name ( ) . unwrap_or_default ( ) )
246
+ {
247
+ best_symbol = Some ( symbol) ;
248
+ }
249
+ } else {
250
+ best_symbol = Some ( symbol) ;
251
+ }
252
+ }
253
+ best_symbol
254
+ }
255
+
224
256
fn find_section_symbol (
225
257
arch : & dyn ObjArch ,
226
258
obj_file : & File < ' _ > ,
259
+ section_symbols : & [ Symbol < ' _ , ' _ > ] ,
227
260
target : & Symbol < ' _ , ' _ > ,
228
261
address : u64 ,
229
262
split_meta : Option < & SplitMeta > ,
230
263
) -> Result < ObjSymbol > {
264
+ if let Some ( symbol) = best_symbol ( section_symbols, address) {
265
+ return to_obj_symbol (
266
+ arch,
267
+ obj_file,
268
+ symbol,
269
+ address as i64 - symbol. address ( ) as i64 ,
270
+ split_meta,
271
+ ) ;
272
+ }
273
+ // Fallback to section symbol
231
274
let section_index =
232
275
target. section_index ( ) . ok_or_else ( || anyhow:: Error :: msg ( "Unknown section index" ) ) ?;
233
276
let section = obj_file. section_by_index ( section_index) ?;
234
- let mut closest_symbol: Option < Symbol < ' _ , ' _ > > = None ;
235
- for symbol in obj_file. symbols ( ) {
236
- if !matches ! ( symbol. section_index( ) , Some ( idx) if idx == section_index) {
237
- continue ;
238
- }
239
- if symbol. kind ( ) == SymbolKind :: Section || symbol. address ( ) != address {
240
- if symbol. address ( ) < address
241
- && symbol. size ( ) != 0
242
- && ( closest_symbol. is_none ( )
243
- || matches ! ( & closest_symbol, Some ( s) if s. address( ) <= symbol. address( ) ) )
244
- {
245
- closest_symbol = Some ( symbol) ;
246
- }
247
- continue ;
248
- }
249
- return to_obj_symbol ( arch, obj_file, & symbol, 0 , split_meta) ;
250
- }
251
- let ( name, offset) = closest_symbol
252
- . and_then ( |s| s. name ( ) . map ( |n| ( n, s. address ( ) ) ) . ok ( ) )
253
- . or_else ( || section. name ( ) . map ( |n| ( n, section. address ( ) ) ) . ok ( ) )
254
- . unwrap_or ( ( "<unknown>" , 0 ) ) ;
255
- let offset_addr = address - offset;
256
277
Ok ( ObjSymbol {
257
- name : name. to_string ( ) ,
278
+ name : section . name ( ) ? . to_string ( ) ,
258
279
demangled_name : None ,
259
- address : offset ,
260
- section_address : address - section . address ( ) ,
280
+ address : section . address ( ) ,
281
+ section_address : 0 ,
261
282
size : 0 ,
262
283
size_known : false ,
263
284
flags : Default :: default ( ) ,
264
- addend : offset_addr as i64 ,
285
+ addend : address as i64 - section . address ( ) as i64 ,
265
286
virtual_address : None ,
266
287
original_index : None ,
267
288
bytes : Vec :: new ( ) ,
@@ -272,6 +293,7 @@ fn relocations_by_section(
272
293
arch : & dyn ObjArch ,
273
294
obj_file : & File < ' _ > ,
274
295
section : & ObjSection ,
296
+ section_symbols : & [ Symbol < ' _ , ' _ > ] ,
275
297
split_meta : Option < & SplitMeta > ,
276
298
) -> Result < Vec < ObjReloc > > {
277
299
let obj_section = obj_file. section_by_index ( SectionIndex ( section. orig_index ) ) ?;
@@ -315,7 +337,14 @@ fn relocations_by_section(
315
337
}
316
338
SymbolKind :: Section => {
317
339
ensure ! ( addend >= 0 , "Negative addend in reloc: {addend}" ) ;
318
- find_section_symbol ( arch, obj_file, & symbol, addend as u64 , split_meta)
340
+ find_section_symbol (
341
+ arch,
342
+ obj_file,
343
+ section_symbols,
344
+ & symbol,
345
+ addend as u64 ,
346
+ split_meta,
347
+ )
319
348
}
320
349
kind => Err ( anyhow ! ( "Unhandled relocation symbol type {kind:?}" ) ) ,
321
350
} ?;
@@ -650,15 +679,26 @@ pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<ObjInfo> {
650
679
let mut sections = filter_sections ( & obj_file, split_meta. as_ref ( ) ) ?;
651
680
let mut name_counts: HashMap < String , u32 > = HashMap :: new ( ) ;
652
681
for section in & mut sections {
682
+ let mut symbols = obj_file
683
+ . symbols ( )
684
+ . filter ( |s| s. section_index ( ) == Some ( SectionIndex ( section. orig_index ) ) )
685
+ . collect :: < Vec < _ > > ( ) ;
686
+ symbols. sort_by_key ( |s| s. address ( ) ) ;
653
687
section. symbols = symbols_by_section (
654
688
arch. as_ref ( ) ,
655
689
& obj_file,
656
690
section,
691
+ & symbols,
657
692
split_meta. as_ref ( ) ,
658
693
& mut name_counts,
659
694
) ?;
660
- section. relocations =
661
- relocations_by_section ( arch. as_ref ( ) , & obj_file, section, split_meta. as_ref ( ) ) ?;
695
+ section. relocations = relocations_by_section (
696
+ arch. as_ref ( ) ,
697
+ & obj_file,
698
+ section,
699
+ & symbols,
700
+ split_meta. as_ref ( ) ,
701
+ ) ?;
662
702
}
663
703
if config. combine_data_sections {
664
704
combine_data_sections ( & mut sections) ?;
0 commit comments