Skip to content

Commit

Permalink
Write .splitmeta section in split objects
Browse files Browse the repository at this point in the history
This enables showing the original address of
symbols in objdiff, as well as `elf disasm`
on split objects retaining the original
addresses.
  • Loading branch information
encounter committed Feb 29, 2024
1 parent a2cae4f commit 4f8a9e6
Show file tree
Hide file tree
Showing 14 changed files with 364 additions and 83 deletions.
204 changes: 165 additions & 39 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ memmap2 = "0.9.0"
multimap = "0.9.1"
nintendo-lz = "0.1.3"
num_enum = "0.7.1"
objdiff-core = { git = "https://github.com/encounter/objdiff", rev = "5b9ac93c084bd0a9ae710e8c8195c4b0db939b8a", features = ["ppc"] }
object = { version = "0.32.1", features = ["read_core", "std", "elf", "write_std"], default-features = false }
once_cell = "1.18.0"
owo-colors = { version = "3.5.0", features = ["supports-colors"] }
Expand Down
5 changes: 3 additions & 2 deletions src/cmd/dol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -836,7 +836,8 @@ fn split_write_obj(
}

debug!("Splitting {} objects", module.obj.link_order.len());
let split_objs = split_obj(&module.obj)?;
let module_name = module.config.name().to_string();
let split_objs = split_obj(&module.obj, Some(module_name.as_str()))?;

debug!("Writing object files");
DirBuilder::new()
Expand All @@ -855,7 +856,7 @@ fn split_write_obj(
module.obj.symbols.by_name("_prolog")?.map(|(_, s)| s.name.clone())
};
let mut out_config = OutputModule {
name: module.config.name().to_string(),
name: module_name,
module_id,
ldscript: out_dir.join("ldscript.lcf"),
units: Vec::with_capacity(split_objs.len()),
Expand Down
27 changes: 25 additions & 2 deletions src/cmd/elf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use std::{

use anyhow::{anyhow, bail, ensure, Context, Result};
use argp::FromArgs;
use objdiff_core::obj::split_meta::{SplitMeta, SPLITMETA_SECTION};
use object::{
elf,
write::{Mangling, SectionId, SymbolId},
Expand Down Expand Up @@ -148,7 +149,7 @@ fn disasm(args: DisasmArgs) -> Result<()> {
match obj.kind {
ObjKind::Executable => {
log::info!("Splitting {} objects", obj.link_order.len());
let split_objs = split_obj(&obj)?;
let split_objs = split_obj(&obj, None)?;

let asm_dir = args.out.join("asm");
let include_dir = args.out.join("include");
Expand Down Expand Up @@ -183,7 +184,7 @@ fn split(args: SplitArgs) -> Result<()> {

let mut file_map = HashMap::<String, Vec<u8>>::new();

let split_objs = split_obj(&obj)?;
let split_objs = split_obj(&obj, None)?;
for (unit, split_obj) in obj.link_order.iter().zip(&split_objs) {
let out_obj = write_elf(split_obj, false)?;
match file_map.entry(unit.name.clone()) {
Expand Down Expand Up @@ -596,5 +597,27 @@ fn info(args: InfoArgs) -> Result<()> {
}
}

if let Some(split_meta_section) = in_file.section_by_name(SPLITMETA_SECTION) {
let data = split_meta_section.uncompressed_data()?;
if !data.is_empty() {
let meta =
SplitMeta::from_reader(&mut data.as_ref(), in_file.endianness(), in_file.is_64())
.context("While reading .splitmeta section")?;
println!("\nSplit metadata (.splitmeta):");
if let Some(generator) = &meta.generator {
println!("\tGenerator: {}", generator);
}
if let Some(virtual_addresses) = &meta.virtual_addresses {
println!("\tVirtual addresses:");
println!("\t{: >10} | {: <10}", "Addr", "Symbol");
for (symbol, addr) in in_file.symbols().zip(virtual_addresses) {
if symbol.is_definition() {
println!("\t{: >10} | {: <10}", format!("{:#X}", addr), symbol.name()?);
}
}
}
}
}

Ok(())
}
2 changes: 1 addition & 1 deletion src/cmd/rel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ fn merge(args: MergeArgs) -> Result<()> {
align: mod_section.align,
elf_index: mod_section.elf_index,
relocations: Default::default(),
original_address: mod_section.original_address,
virtual_address: mod_section.virtual_address,
file_offset: mod_section.file_offset,
section_known: mod_section.section_known,
splits: mod_section.splits.clone(),
Expand Down
2 changes: 1 addition & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ enum SubCommand {
// Duplicated from supports-color so we can check early.
fn env_no_color() -> bool {
match env::var("NO_COLOR").as_deref() {
Ok("0") | Err(_) => false,
Ok("") | Ok("0") | Err(_) => false,
Ok(_) => true,
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/obj/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::{
};

use anyhow::{anyhow, bail, ensure, Result};
use objdiff_core::obj::split_meta::SplitMeta;
pub use relocations::{ObjReloc, ObjRelocKind, ObjRelocations};
pub use sections::{ObjSection, ObjSectionKind, ObjSections};
pub use splits::{ObjSplit, ObjSplits};
Expand Down Expand Up @@ -55,6 +56,7 @@ pub struct ObjInfo {
pub sections: ObjSections,
pub entry: Option<u64>,
pub mw_comment: Option<MWComment>,
pub split_meta: Option<SplitMeta>,

// Linker generated
pub sda2_base: Option<u32>,
Expand Down Expand Up @@ -94,6 +96,7 @@ impl ObjInfo {
sections: ObjSections::new(kind, sections),
entry: None,
mw_comment: Default::default(),
split_meta: None,
sda2_base: None,
sda_base: None,
stack_address: None,
Expand Down
2 changes: 1 addition & 1 deletion src/obj/sections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub struct ObjSection {
/// REL files reference the original ELF section indices
pub elf_index: usize,
pub relocations: ObjRelocations,
pub original_address: u64,
pub virtual_address: Option<u64>,
pub file_offset: u64,
pub section_known: bool,
pub splits: ObjSplits,
Expand Down
17 changes: 9 additions & 8 deletions src/util/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ where W: Write + ?Sized {
.or_else(|| vec.iter().find(|e| e.kind == SymbolEntryKind::Start))
.map(|e| e.index);
if target_symbol_idx.is_none() {
let display_address = address as u64 + section.original_address;
let display_address = address as u64 + section.virtual_address.unwrap_or(0);
let symbol_idx = symbols.len();
symbols.push(ObjSymbol {
name: format!(".L_{display_address:08X}"),
Expand Down Expand Up @@ -148,7 +148,7 @@ where W: Write + ?Sized {
.iter()
.any(|e| e.kind == SymbolEntryKind::Label || e.kind == SymbolEntryKind::Start)
{
let display_address = address + target_section.original_address;
let display_address = address + target_section.virtual_address.unwrap_or(0);
let symbol_idx = symbols.len();
symbols.push(ObjSymbol {
name: format!(".L_{display_address:08X}"),
Expand Down Expand Up @@ -246,7 +246,7 @@ where
for ins in disasm_iter(data, address) {
let reloc = relocations.get(&ins.addr);
let file_offset = section.file_offset + (ins.addr as u64 - section.address);
write_ins(w, symbols, ins, reloc, file_offset, section.original_address)?;
write_ins(w, symbols, ins, reloc, file_offset, section.virtual_address)?;
}
Ok(())
}
Expand All @@ -257,15 +257,15 @@ fn write_ins<W>(
mut ins: Ins,
reloc: Option<&ObjReloc>,
file_offset: u64,
section_address: u64,
section_vaddr: Option<u64>,
) -> Result<()>
where
W: Write + ?Sized,
{
write!(
w,
"/* {:08X} {:08X} {:02X} {:02X} {:02X} {:02X} */\t",
ins.addr as u64 + section_address,
ins.addr as u64 + section_vaddr.unwrap_or(0),
file_offset,
(ins.code >> 24) & 0xFF,
(ins.code >> 16) & 0xFF,
Expand Down Expand Up @@ -466,7 +466,7 @@ where
let dbg_symbols = vec.iter().map(|e| &symbols[e.index]).collect_vec();
bail!(
"Unaligned symbol entry @ {:#010X}:\n\t{:?}",
section.original_address as u32 + sym_addr,
section.virtual_address.unwrap_or(0) as u32 + sym_addr,
dbg_symbols
);
}
Expand Down Expand Up @@ -838,11 +838,12 @@ fn write_section_header<W>(
where
W: Write + ?Sized,
{
let section_virtual_address = section.virtual_address.unwrap_or(0);
writeln!(
w,
"\n# {:#010X} - {:#010X}",
start as u64 + section.original_address,
end as u64 + section.original_address
start as u64 + section_virtual_address,
end as u64 + section_virtual_address
)?;
match section.name.as_str() {
".text" if subsection == 0 => {
Expand Down
10 changes: 5 additions & 5 deletions src/util/dol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
align: 0,
elf_index: 0,
relocations: Default::default(),
original_address: 0,
virtual_address: Some(dol_section.address as u64),
file_offset: dol_section.file_offset as u64,
section_known: known,
splits: Default::default(),
Expand Down Expand Up @@ -460,7 +460,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
align: 0,
elf_index: 0,
relocations: Default::default(),
original_address: 0,
virtual_address: Some(addr as u64),
file_offset: 0,
section_known: false,
splits: Default::default(),
Expand All @@ -480,7 +480,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
align: 0,
elf_index: 0,
relocations: Default::default(),
original_address: 0,
virtual_address: Some(bss_section.address as u64),
file_offset: 0,
section_known: false,
splits: Default::default(),
Expand All @@ -507,7 +507,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
align: 0,
elf_index: 0,
relocations: Default::default(),
original_address: 0,
virtual_address: Some(bss_sections[0].0 as u64),
file_offset: 0,
section_known: false,
splits: Default::default(),
Expand All @@ -521,7 +521,7 @@ pub fn process_dol(buf: &[u8], name: &str) -> Result<ObjInfo> {
align: 0,
elf_index: 0,
relocations: Default::default(),
original_address: 0,
virtual_address: Some(bss_sections[1].0 as u64),
file_offset: 0,
section_known: false,
splits: Default::default(),
Expand Down
Loading

0 comments on commit 4f8a9e6

Please sign in to comment.