From 89864dc76ed8d57c3886b5518489a44315f0f430 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Sat, 13 Sep 2025 02:17:36 -0600 Subject: [PATCH] refactor: rename relocations field and flatten relocs (#115) --- src/cmd/dol.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/cmd/dol.rs b/src/cmd/dol.rs index 544f236..653f1e2 100644 --- a/src/cmd/dol.rs +++ b/src/cmd/dol.rs @@ -317,6 +317,10 @@ pub struct ExtractConfig { /// Path is relative to `out_dir/include`. #[serde(with = "unix_path_serde_option", default, skip_serializing_if = "Option::is_none")] pub header: Option, + /// If specified, any relocations within the symbol will be written to the given file in JSON + /// format. Path is relative to `out_dir/bin`. + #[serde(with = "unix_path_serde_option", default, skip_serializing_if = "Option::is_none")] + pub relocations: Option, /// The type for the extracted symbol in the header file. By default, the header will emit /// a full symbol declaration (a.k.a. `symbol`), but this can be set to `raw` to emit the raw /// data as a byte array. `none` avoids emitting a header entirely, in which case the `header` @@ -403,11 +407,24 @@ pub struct OutputExtract { pub binary: Option, #[serde(with = "unix_path_serde_option")] pub header: Option, + #[serde(with = "unix_path_serde_option")] + pub relocations: Option, pub header_type: String, pub custom_type: Option, pub custom_data: Option, } +#[derive(Serialize)] +struct ExtractRelocInfo { + offset: u32, + #[serde(rename = "type")] + kind: ObjRelocKind, + target: String, + addend: i64, + #[serde(skip_serializing_if = "Option::is_none")] + module: Option, +} + #[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq, Eq, Hash)] pub struct OutputLink { pub modules: Vec, @@ -1063,12 +1080,35 @@ fn split_write_obj( } } + if let Some(relocations) = &extract.relocations { + let start = symbol.address as u32 - section.address as u32; + let end = start + symbol.size as u32; + let mut reloc_entries = Vec::new(); + for (addr, reloc) in section.relocations.range(start..end) { + let target_symbol = &module.obj.symbols[reloc.target_symbol]; + reloc_entries.push(ExtractRelocInfo { + offset: addr - start, + kind: reloc.kind, + target: target_symbol.name.clone(), + addend: reloc.addend, + module: reloc.module, + }); + } + let relocations_json = serde_json::to_vec_pretty(&reloc_entries)?; + let out_path = base_dir.join("bin").join(relocations.with_encoding()); + if let Some(parent) = out_path.parent() { + DirBuilder::new().recursive(true).create(parent)?; + } + write_if_changed(&out_path, &relocations_json)?; + } + // Copy to output config out_config.extract.push(OutputExtract { symbol: symbol.name.clone(), rename: extract.rename.clone(), binary: extract.binary.clone(), header: extract.header.clone(), + relocations: extract.relocations.clone(), header_type: header_kind.to_string(), custom_type: extract.custom_type.clone(), custom_data: extract.custom_data.clone(),