@@ -152,26 +152,23 @@ fn symbols_by_section(
152152 arch : & dyn ObjArch ,
153153 obj_file : & File < ' _ > ,
154154 section : & ObjSection ,
155+ section_symbols : & [ Symbol < ' _ , ' _ > ] ,
155156 split_meta : Option < & SplitMeta > ,
156157 name_counts : & mut HashMap < String , u32 > ,
157158) -> Result < Vec < ObjSymbol > > {
158159 let mut result = Vec :: < ObjSymbol > :: new ( ) ;
159- for symbol in obj_file . symbols ( ) {
160+ for symbol in section_symbols {
160161 if symbol. kind ( ) == SymbolKind :: Section {
161162 continue ;
162163 }
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 ;
173169 }
174170 }
171+ result. push ( to_obj_symbol ( arch, obj_file, symbol, 0 , split_meta) ?) ;
175172 }
176173 result. sort_by ( |a, b| a. address . cmp ( & b. address ) . then ( a. size . cmp ( & b. size ) ) ) ;
177174 let mut iter = result. iter_mut ( ) . peekable ( ) ;
@@ -221,47 +218,71 @@ fn common_symbols(
221218 . collect :: < Result < Vec < ObjSymbol > > > ( )
222219}
223220
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+
224256fn find_section_symbol (
225257 arch : & dyn ObjArch ,
226258 obj_file : & File < ' _ > ,
259+ section_symbols : & [ Symbol < ' _ , ' _ > ] ,
227260 target : & Symbol < ' _ , ' _ > ,
228261 address : u64 ,
229262 split_meta : Option < & SplitMeta > ,
230263) -> 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
231274 let section_index =
232275 target. section_index ( ) . ok_or_else ( || anyhow:: Error :: msg ( "Unknown section index" ) ) ?;
233276 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;
256277 Ok ( ObjSymbol {
257- name : name. to_string ( ) ,
278+ name : section . name ( ) ? . to_string ( ) ,
258279 demangled_name : None ,
259- address : offset ,
260- section_address : address - section . address ( ) ,
280+ address : section . address ( ) ,
281+ section_address : 0 ,
261282 size : 0 ,
262283 size_known : false ,
263284 flags : Default :: default ( ) ,
264- addend : offset_addr as i64 ,
285+ addend : address as i64 - section . address ( ) as i64 ,
265286 virtual_address : None ,
266287 original_index : None ,
267288 bytes : Vec :: new ( ) ,
@@ -272,6 +293,7 @@ fn relocations_by_section(
272293 arch : & dyn ObjArch ,
273294 obj_file : & File < ' _ > ,
274295 section : & ObjSection ,
296+ section_symbols : & [ Symbol < ' _ , ' _ > ] ,
275297 split_meta : Option < & SplitMeta > ,
276298) -> Result < Vec < ObjReloc > > {
277299 let obj_section = obj_file. section_by_index ( SectionIndex ( section. orig_index ) ) ?;
@@ -315,7 +337,14 @@ fn relocations_by_section(
315337 }
316338 SymbolKind :: Section => {
317339 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+ )
319348 }
320349 kind => Err ( anyhow ! ( "Unhandled relocation symbol type {kind:?}" ) ) ,
321350 } ?;
@@ -650,15 +679,26 @@ pub fn parse(data: &[u8], config: &DiffObjConfig) -> Result<ObjInfo> {
650679 let mut sections = filter_sections ( & obj_file, split_meta. as_ref ( ) ) ?;
651680 let mut name_counts: HashMap < String , u32 > = HashMap :: new ( ) ;
652681 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 ( ) ) ;
653687 section. symbols = symbols_by_section (
654688 arch. as_ref ( ) ,
655689 & obj_file,
656690 section,
691+ & symbols,
657692 split_meta. as_ref ( ) ,
658693 & mut name_counts,
659694 ) ?;
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+ ) ?;
662702 }
663703 if config. combine_data_sections {
664704 combine_data_sections ( & mut sections) ?;
0 commit comments