@@ -8,7 +8,6 @@ use alloc::{
88use core:: { cmp:: Ordering , num:: NonZeroU64 } ;
99
1010use anyhow:: { Context , Result , anyhow, bail, ensure} ;
11- use itertools:: Itertools ;
1211use object:: { Object as _, ObjectSection as _, ObjectSymbol as _} ;
1312
1413use crate :: {
@@ -164,19 +163,37 @@ fn map_symbols(
164163 split_meta : Option < & SplitMeta > ,
165164 config : & DiffObjConfig ,
166165) -> Result < ( Vec < Symbol > , Vec < usize > ) > {
167- let symbol_count = obj_file. symbols ( ) . count ( ) ;
168- let mut symbols = Vec :: < Symbol > :: with_capacity ( symbol_count + obj_file. sections ( ) . count ( ) ) ;
169- let mut symbol_indices = Vec :: < usize > :: with_capacity ( symbol_count + 1 ) ;
170- let obj_symbols = obj_file. symbols ( ) ;
171166 // symbols() is not guaranteed to be sorted by address.
172167 // We sort it here to fix pairing bugs with diff algorithms that assume the symbols are ordered.
173168 // Sorting everything here once is less expensive than sorting subsets later in expensive loops.
174- let obj_symbols =
175- obj_symbols. sorted_by_key ( |symbol| ( symbol. section_index ( ) . map ( |i| i. 0 ) , symbol. address ( ) ) ) ;
169+ let mut max_index = 0 ;
170+ let mut obj_symbols = obj_file
171+ . symbols ( )
172+ . inspect ( |sym| max_index = max_index. max ( sym. index ( ) . 0 ) )
173+ . collect :: < Vec < _ > > ( ) ;
174+ obj_symbols. sort_by ( |a, b| {
175+ // Sort symbols by section index, placing absolute symbols last
176+ a. section_index ( )
177+ . map_or ( usize:: MAX , |s| s. 0 )
178+ . cmp ( & b. section_index ( ) . map_or ( usize:: MAX , |s| s. 0 ) )
179+ . then_with ( || {
180+ // Sort section symbols first in a section
181+ if a. kind ( ) == object:: SymbolKind :: Section {
182+ Ordering :: Less
183+ } else if b. kind ( ) == object:: SymbolKind :: Section {
184+ Ordering :: Greater
185+ } else {
186+ Ordering :: Equal
187+ }
188+ } )
189+ // Sort by address within section
190+ . then_with ( || a. address ( ) . cmp ( & b. address ( ) ) )
191+ // If there are multiple symbols with the same address, smaller symbol first
192+ . then_with ( || a. size ( ) . cmp ( & b. size ( ) ) )
193+ } ) ;
194+ let mut symbols = Vec :: < Symbol > :: with_capacity ( obj_symbols. len ( ) + obj_file. sections ( ) . count ( ) ) ;
195+ let mut symbol_indices = vec ! [ usize :: MAX ; max_index + 1 ] ;
176196 for obj_symbol in obj_symbols {
177- if symbol_indices. len ( ) <= obj_symbol. index ( ) . 0 {
178- symbol_indices. resize ( obj_symbol. index ( ) . 0 + 1 , usize:: MAX ) ;
179- }
180197 let symbol = map_symbol ( arch, obj_file, & obj_symbol, section_indices, split_meta, config) ?;
181198 symbol_indices[ obj_symbol. index ( ) . 0 ] = symbols. len ( ) ;
182199 symbols. push ( symbol) ;
@@ -246,40 +263,18 @@ fn is_local_label(symbol: &Symbol) -> bool {
246263}
247264
248265fn infer_symbol_sizes ( arch : & dyn Arch , symbols : & mut [ Symbol ] , sections : & [ Section ] ) -> Result < ( ) > {
249- // Create a sorted list of symbol indices by section
250- let mut symbols_with_section = Vec :: < usize > :: with_capacity ( symbols. len ( ) ) ;
251- for ( i, symbol) in symbols. iter ( ) . enumerate ( ) {
252- if symbol. section . is_some ( ) {
253- symbols_with_section. push ( i) ;
254- }
255- }
256- symbols_with_section. sort_by ( |a, b| {
257- let a = & symbols[ * a] ;
258- let b = & symbols[ * b] ;
259- a. section
260- . unwrap_or ( usize:: MAX )
261- . cmp ( & b. section . unwrap_or ( usize:: MAX ) )
262- . then_with ( || {
263- // Sort section symbols first
264- if a. kind == SymbolKind :: Section {
265- Ordering :: Less
266- } else if b. kind == SymbolKind :: Section {
267- Ordering :: Greater
268- } else {
269- Ordering :: Equal
270- }
271- } )
272- . then_with ( || a. address . cmp ( & b. address ) )
273- . then_with ( || a. size . cmp ( & b. size ) )
274- } ) ;
266+ // Above, we've sorted the symbols by section and then by address.
275267
276268 // Set symbol sizes based on the next symbol's address
277269 let mut iter_idx = 0 ;
278270 let mut last_end = ( 0 , 0 ) ;
279- while iter_idx < symbols_with_section . len ( ) {
280- let symbol_idx = symbols_with_section [ iter_idx] ;
271+ while iter_idx < symbols . len ( ) {
272+ let symbol_idx = iter_idx;
281273 let symbol = & symbols[ symbol_idx] ;
282- let section_idx = symbol. section . unwrap ( ) ;
274+ let Some ( section_idx) = symbol. section else {
275+ // Start of absolute symbols
276+ break ;
277+ } ;
283278 iter_idx += 1 ;
284279 if symbol. size != 0 {
285280 if symbol. kind != SymbolKind :: Section {
@@ -292,10 +287,9 @@ fn infer_symbol_sizes(arch: &dyn Arch, symbols: &mut [Symbol], sections: &[Secti
292287 continue ;
293288 }
294289 let next_symbol = loop {
295- if iter_idx >= symbols_with_section . len ( ) {
290+ let Some ( next_symbol ) = symbols . get ( iter_idx ) else {
296291 break None ;
297- }
298- let next_symbol = & symbols[ symbols_with_section[ iter_idx] ] ;
292+ } ;
299293 if next_symbol. section != Some ( section_idx) {
300294 break None ;
301295 }
@@ -351,9 +345,11 @@ fn map_sections(
351345 split_meta : Option < & SplitMeta > ,
352346) -> Result < ( Vec < Section > , Vec < usize > ) > {
353347 let mut section_names = BTreeMap :: < String , usize > :: new ( ) ;
354- let section_count = obj_file. sections ( ) . count ( ) ;
348+ let mut max_index = 0 ;
349+ let section_count =
350+ obj_file. sections ( ) . inspect ( |s| max_index = max_index. max ( s. index ( ) . 0 ) ) . count ( ) ;
355351 let mut result = Vec :: < Section > :: with_capacity ( section_count) ;
356- let mut section_indices = Vec :: < usize > :: with_capacity ( section_count + 1 ) ;
352+ let mut section_indices = vec ! [ usize :: MAX ; max_index + 1 ] ;
357353 for section in obj_file. sections ( ) {
358354 let name = section. name ( ) . context ( "Failed to process section name" ) ?;
359355 let kind = map_section_kind ( & section) ;
@@ -378,9 +374,6 @@ fn map_sections(
378374 let id = format ! ( "{name}-{unique_id}" ) ;
379375 * unique_id += 1 ;
380376
381- if section_indices. len ( ) <= section. index ( ) . 0 {
382- section_indices. resize ( section. index ( ) . 0 + 1 , usize:: MAX ) ;
383- }
384377 section_indices[ section. index ( ) . 0 ] = result. len ( ) ;
385378 result. push ( Section {
386379 id,
0 commit comments