1
- use std:: { fs, io:: Cursor , path:: Path } ;
1
+ use std:: { collections :: HashSet , fs, io:: Cursor , path:: Path } ;
2
2
3
3
use anyhow:: { anyhow, bail, ensure, Context , Result } ;
4
4
use byteorder:: { BigEndian , ReadBytesExt } ;
@@ -11,6 +11,7 @@ use object::{
11
11
12
12
use crate :: {
13
13
arch:: { new_arch, ObjArch } ,
14
+ diff:: DiffObjConfig ,
14
15
obj:: {
15
16
split_meta:: { SplitMeta , SPLITMETA_SECTION } ,
16
17
ObjInfo , ObjReloc , ObjSection , ObjSectionKind , ObjSymbol , ObjSymbolFlagSet , ObjSymbolFlags ,
@@ -361,7 +362,105 @@ fn line_info(obj_file: &File<'_>, sections: &mut [ObjSection]) -> Result<()> {
361
362
Ok ( ( ) )
362
363
}
363
364
364
- pub fn read ( obj_path : & Path ) -> Result < ObjInfo > {
365
+ fn update_combined_symbol ( symbol : ObjSymbol , address_change : i64 ) -> Result < ObjSymbol > {
366
+ Ok ( ObjSymbol {
367
+ name : symbol. name ,
368
+ demangled_name : symbol. demangled_name ,
369
+ address : ( symbol. address as i64 + address_change) . try_into ( ) ?,
370
+ section_address : ( symbol. section_address as i64 + address_change) . try_into ( ) ?,
371
+ size : symbol. size ,
372
+ size_known : symbol. size_known ,
373
+ flags : symbol. flags ,
374
+ addend : symbol. addend ,
375
+ virtual_address : if let Some ( virtual_address) = symbol. virtual_address {
376
+ Some ( ( virtual_address as i64 + address_change) . try_into ( ) ?)
377
+ } else {
378
+ None
379
+ } ,
380
+ } )
381
+ }
382
+
383
+ fn combine_sections ( section : ObjSection , combine : ObjSection ) -> Result < ObjSection > {
384
+ let mut data = section. data ;
385
+ data. extend ( combine. data ) ;
386
+
387
+ let address_change: i64 = ( section. address + section. size ) as i64 - combine. address as i64 ;
388
+ let mut symbols = section. symbols ;
389
+ for symbol in combine. symbols {
390
+ symbols. push ( update_combined_symbol ( symbol, address_change) ?) ;
391
+ }
392
+
393
+ let mut relocations = section. relocations ;
394
+ for reloc in combine. relocations {
395
+ relocations. push ( ObjReloc {
396
+ flags : reloc. flags ,
397
+ address : ( reloc. address as i64 + address_change) . try_into ( ) ?,
398
+ target : reloc. target , // TODO: Should be updated?
399
+ target_section : reloc. target_section , // TODO: Same as above
400
+ } ) ;
401
+ }
402
+
403
+ let mut line_info = section. line_info ;
404
+ for ( addr, line) in combine. line_info {
405
+ let key = ( addr as i64 + address_change) . try_into ( ) ?;
406
+ line_info. insert ( key, line) ;
407
+ }
408
+
409
+ Ok ( ObjSection {
410
+ name : section. name ,
411
+ kind : section. kind ,
412
+ address : section. address ,
413
+ size : section. size + combine. size ,
414
+ data,
415
+ orig_index : section. orig_index ,
416
+ symbols,
417
+ relocations,
418
+ virtual_address : section. virtual_address ,
419
+ line_info,
420
+ } )
421
+ }
422
+
423
+ fn combine_data_sections ( sections : & mut Vec < ObjSection > ) -> Result < ( ) > {
424
+ let names_to_combine: HashSet < _ > = sections
425
+ . iter ( )
426
+ . filter ( |s| s. kind == ObjSectionKind :: Data )
427
+ . map ( |s| s. name . clone ( ) )
428
+ . collect ( ) ;
429
+
430
+ for name in names_to_combine {
431
+ // Take section with lowest index
432
+ let ( mut section_index, _) = sections
433
+ . iter ( )
434
+ . enumerate ( )
435
+ . filter ( |( _, s) | s. name == name)
436
+ . min_by_key ( |( _, s) | s. orig_index )
437
+ // Should not happen
438
+ . context ( "No combine section found with name" ) ?;
439
+ let mut section = sections. remove ( section_index) ;
440
+
441
+ // Remove equally named sections
442
+ let mut combines = vec ! [ ] ;
443
+ for i in ( 0 ..sections. len ( ) ) . rev ( ) {
444
+ if sections[ i] . name != name || sections[ i] . orig_index == section. orig_index {
445
+ continue ;
446
+ }
447
+ combines. push ( sections. remove ( i) ) ;
448
+ if i < section_index {
449
+ section_index -= 1 ;
450
+ }
451
+ }
452
+
453
+ // Combine sections ordered by index
454
+ combines. sort_unstable_by_key ( |c| c. orig_index ) ;
455
+ for combine in combines {
456
+ section = combine_sections ( section, combine) ?;
457
+ }
458
+ sections. insert ( section_index, section) ;
459
+ }
460
+ Ok ( ( ) )
461
+ }
462
+
463
+ pub fn read ( obj_path : & Path , config : & DiffObjConfig ) -> Result < ObjInfo > {
365
464
let ( data, timestamp) = {
366
465
let file = fs:: File :: open ( obj_path) ?;
367
466
let timestamp = FileTime :: from_last_modification_time ( & file. metadata ( ) ?) ;
@@ -377,6 +476,9 @@ pub fn read(obj_path: &Path) -> Result<ObjInfo> {
377
476
section. relocations =
378
477
relocations_by_section ( arch. as_ref ( ) , & obj_file, section, split_meta. as_ref ( ) ) ?;
379
478
}
479
+ if config. combine_data_sections {
480
+ combine_data_sections ( & mut sections) ?;
481
+ }
380
482
line_info ( & obj_file, & mut sections) ?;
381
483
let common = common_symbols ( arch. as_ref ( ) , & obj_file, split_meta. as_ref ( ) ) ?;
382
484
Ok ( ObjInfo { arch, path : obj_path. to_owned ( ) , timestamp, sections, common, split_meta } )
0 commit comments