@@ -317,6 +317,10 @@ pub struct ExtractConfig {
317317 /// Path is relative to `out_dir/include`.
318318 #[ serde( with = "unix_path_serde_option" , default , skip_serializing_if = "Option::is_none" ) ]
319319 pub header : Option < Utf8UnixPathBuf > ,
320+ /// If specified, any relocations within the symbol will be written to the given file in JSON
321+ /// format. Path is relative to `out_dir/bin`.
322+ #[ serde( with = "unix_path_serde_option" , default , skip_serializing_if = "Option::is_none" ) ]
323+ pub relocations : Option < Utf8UnixPathBuf > ,
320324 /// The type for the extracted symbol in the header file. By default, the header will emit
321325 /// a full symbol declaration (a.k.a. `symbol`), but this can be set to `raw` to emit the raw
322326 /// data as a byte array. `none` avoids emitting a header entirely, in which case the `header`
@@ -403,11 +407,24 @@ pub struct OutputExtract {
403407 pub binary : Option < Utf8UnixPathBuf > ,
404408 #[ serde( with = "unix_path_serde_option" ) ]
405409 pub header : Option < Utf8UnixPathBuf > ,
410+ #[ serde( with = "unix_path_serde_option" ) ]
411+ pub relocations : Option < Utf8UnixPathBuf > ,
406412 pub header_type : String ,
407413 pub custom_type : Option < String > ,
408414 pub custom_data : Option < serde_json:: Value > ,
409415}
410416
417+ #[ derive( Serialize ) ]
418+ struct ExtractRelocInfo {
419+ offset : u32 ,
420+ #[ serde( rename = "type" ) ]
421+ kind : ObjRelocKind ,
422+ target : String ,
423+ addend : i64 ,
424+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
425+ module : Option < u32 > ,
426+ }
427+
411428#[ derive( Serialize , Deserialize , Debug , Clone , Default , PartialEq , Eq , Hash ) ]
412429pub struct OutputLink {
413430 pub modules : Vec < String > ,
@@ -1063,12 +1080,35 @@ fn split_write_obj(
10631080 }
10641081 }
10651082
1083+ if let Some ( relocations) = & extract. relocations {
1084+ let start = symbol. address as u32 - section. address as u32 ;
1085+ let end = start + symbol. size as u32 ;
1086+ let mut reloc_entries = Vec :: new ( ) ;
1087+ for ( addr, reloc) in section. relocations . range ( start..end) {
1088+ let target_symbol = & module. obj . symbols [ reloc. target_symbol ] ;
1089+ reloc_entries. push ( ExtractRelocInfo {
1090+ offset : addr - start,
1091+ kind : reloc. kind ,
1092+ target : target_symbol. name . clone ( ) ,
1093+ addend : reloc. addend ,
1094+ module : reloc. module ,
1095+ } ) ;
1096+ }
1097+ let relocations_json = serde_json:: to_vec_pretty ( & reloc_entries) ?;
1098+ let out_path = base_dir. join ( "bin" ) . join ( relocations. with_encoding ( ) ) ;
1099+ if let Some ( parent) = out_path. parent ( ) {
1100+ DirBuilder :: new ( ) . recursive ( true ) . create ( parent) ?;
1101+ }
1102+ write_if_changed ( & out_path, & relocations_json) ?;
1103+ }
1104+
10661105 // Copy to output config
10671106 out_config. extract . push ( OutputExtract {
10681107 symbol : symbol. name . clone ( ) ,
10691108 rename : extract. rename . clone ( ) ,
10701109 binary : extract. binary . clone ( ) ,
10711110 header : extract. header . clone ( ) ,
1111+ relocations : extract. relocations . clone ( ) ,
10721112 header_type : header_kind. to_string ( ) ,
10731113 custom_type : extract. custom_type . clone ( ) ,
10741114 custom_data : extract. custom_data . clone ( ) ,
0 commit comments