From 36bb5ddcc67dabaf5d00d7335a9e764c4c668ee7 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Sun, 1 Oct 2023 12:50:21 -0400 Subject: [PATCH] Zero out section data for relocations in relocatable ELFs Fixes issues with Wii versions of mwld. --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/util/elf.rs | 41 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b589f57..5997702 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -331,7 +331,7 @@ dependencies = [ [[package]] name = "decomp-toolkit" -version = "0.5.4" +version = "0.5.5" dependencies = [ "anyhow", "ar", diff --git a/Cargo.toml b/Cargo.toml index 90d68ec..80ebb09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "decomp-toolkit" description = "Yet another GameCube/Wii decompilation toolkit." authors = ["Luke Street "] license = "MIT OR Apache-2.0" -version = "0.5.4" +version = "0.5.5" edition = "2021" publish = false build = "build.rs" diff --git a/src/util/elf.rs b/src/util/elf.rs index 9f99c3f..fc772e5 100644 --- a/src/util/elf.rs +++ b/src/util/elf.rs @@ -13,7 +13,7 @@ use object::{ elf, elf::{SHF_ALLOC, SHF_EXECINSTR, SHF_WRITE, SHT_NOBITS, SHT_PROGBITS}, write::{ - elf::{ProgramHeader, Rel, SectionHeader, SectionIndex, SymbolIndex}, + elf::{ProgramHeader, Rel, SectionHeader, SectionIndex, SymbolIndex, Writer}, StringId, }, Architecture, Endianness, Object, ObjectKind, ObjectSection, ObjectSymbol, Relocation, @@ -21,6 +21,7 @@ use object::{ }; use crate::{ + array_ref, obj::{ ObjArchitecture, ObjInfo, ObjKind, ObjReloc, ObjRelocKind, ObjSection, ObjSectionKind, ObjSplit, ObjSymbol, ObjSymbolFlagSet, ObjSymbolFlags, ObjSymbolKind, ObjUnit, @@ -631,7 +632,11 @@ pub fn write_elf(obj: &ObjInfo) -> Result> { } writer.write_align(32); ensure!(writer.len() == out_section.offset); - writer.write(§ion.data); + if obj.kind == ObjKind::Relocatable { + write_relocatable_section_data(&mut writer, section)?; + } else { + writer.write(§ion.data); + } } for ((_, section), out_section) in obj.sections.iter().zip(&out_sections) { @@ -876,3 +881,35 @@ fn to_obj_reloc( }?; Ok(Some(ObjReloc { kind: reloc_kind, target_symbol, addend, module: None })) } + +/// Writes section data while zeroing out relocations. +fn write_relocatable_section_data(w: &mut Writer, section: &ObjSection) -> Result<()> { + ensure!(section.address == 0); + let mut current_address = 0; + for (addr, reloc) in section.relocations.iter() { + w.write(§ion.data[current_address..addr as usize]); + let mut ins = u32::from_be_bytes(*array_ref!(section.data, addr as usize, 4)); + match reloc.kind { + ObjRelocKind::Absolute => { + ins = 0; + } + ObjRelocKind::PpcAddr16Hi | ObjRelocKind::PpcAddr16Ha | ObjRelocKind::PpcAddr16Lo => { + ins &= !0xFFFF; + } + ObjRelocKind::PpcRel24 => { + ins &= !0x3FFFFFC; + } + ObjRelocKind::PpcRel14 => { + ins &= !0xFFFC; + } + ObjRelocKind::PpcEmbSda21 => { + ins &= !0x1FFFFF; + } + } + w.write(&ins.to_be_bytes()); + current_address = addr as usize + 4; + } + // Write remaining data + w.write(§ion.data[current_address..]); + Ok(()) +}