mirror of
https://github.com/encounter/decomp-toolkit.git
synced 2025-12-12 06:45:09 +00:00
Write .splitmeta section in split objects
This enables showing the original address of symbols in objdiff, as well as `elf disasm` on split objects retaining the original addresses.
This commit is contained in:
@@ -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()
|
||||
@@ -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()),
|
||||
|
||||
@@ -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},
|
||||
@@ -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");
|
||||
@@ -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()) {
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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};
|
||||
@@ -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>,
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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}"),
|
||||
@@ -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}"),
|
||||
@@ -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(())
|
||||
}
|
||||
@@ -257,7 +257,7 @@ 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,
|
||||
@@ -265,7 +265,7 @@ where
|
||||
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,
|
||||
@@ -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
|
||||
);
|
||||
}
|
||||
@@ -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 => {
|
||||
|
||||
@@ -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(),
|
||||
@@ -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(),
|
||||
@@ -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(),
|
||||
@@ -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(),
|
||||
@@ -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(),
|
||||
|
||||
153
src/util/elf.rs
153
src/util/elf.rs
@@ -9,6 +9,7 @@ use anyhow::{anyhow, bail, ensure, Context, Result};
|
||||
use cwdemangle::demangle;
|
||||
use flagset::Flags;
|
||||
use indexmap::IndexMap;
|
||||
use objdiff_core::obj::split_meta::{SplitMeta, SHT_SPLITMETA, SPLITMETA_SECTION};
|
||||
use object::{
|
||||
elf,
|
||||
elf::{SHF_ALLOC, SHF_EXECINSTR, SHF_WRITE, SHT_NOBITS, SHT_PROGBITS},
|
||||
@@ -95,7 +96,7 @@ where P: AsRef<Path> {
|
||||
align: section.align(),
|
||||
elf_index: section.index().0,
|
||||
relocations: Default::default(),
|
||||
original_address: 0, // TODO load from abs symbol
|
||||
virtual_address: None, // Loaded from section symbol
|
||||
file_offset: section.file_range().map(|(v, _)| v).unwrap_or_default(),
|
||||
section_known: true,
|
||||
splits: Default::default(),
|
||||
@@ -127,6 +128,26 @@ where P: AsRef<Path> {
|
||||
None
|
||||
};
|
||||
|
||||
let split_meta = if let Some(split_meta_section) = obj_file.section_by_name(SPLITMETA_SECTION) {
|
||||
let data = split_meta_section.uncompressed_data()?;
|
||||
if data.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let mut reader = Cursor::new(&*data);
|
||||
let metadata =
|
||||
SplitMeta::from_reader(&mut reader, obj_file.endianness(), obj_file.is_64())
|
||||
.context("While reading .splitmeta section")?;
|
||||
log::debug!("Loaded .splitmeta section");
|
||||
ensure!(
|
||||
data.len() - reader.position() as usize == 0,
|
||||
".splitmeta section data not fully read"
|
||||
);
|
||||
Some(metadata)
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut symbols: Vec<ObjSymbol> = vec![];
|
||||
let mut symbol_indexes: Vec<Option<usize>> = vec![];
|
||||
let mut section_starts = IndexMap::<String, Vec<(u64, String)>>::new();
|
||||
@@ -209,6 +230,16 @@ where P: AsRef<Path> {
|
||||
let section_index = symbol
|
||||
.section_index()
|
||||
.ok_or_else(|| anyhow!("Section symbol without section"))?;
|
||||
|
||||
// Resolve original address from split metadata
|
||||
if let Some(addr) = split_meta
|
||||
.as_ref()
|
||||
.and_then(|m| m.virtual_addresses.as_ref())
|
||||
.and_then(|v| v.get(symbol.index().0).cloned())
|
||||
{
|
||||
sections[section_index.0].virtual_address = Some(addr);
|
||||
}
|
||||
|
||||
let section = obj_file.section_by_index(section_index)?;
|
||||
let section_name = section.name()?.to_string();
|
||||
match &mut boundary_state {
|
||||
@@ -335,6 +366,7 @@ where P: AsRef<Path> {
|
||||
let mut obj = ObjInfo::new(kind, architecture, obj_name, symbols, sections);
|
||||
obj.entry = NonZeroU64::new(obj_file.entry()).map(|n| n.get());
|
||||
obj.mw_comment = mw_comment.map(|(header, _)| header);
|
||||
obj.split_meta = split_meta;
|
||||
obj.sda2_base = sda2_base;
|
||||
obj.sda_base = sda_base;
|
||||
obj.stack_address = stack_address;
|
||||
@@ -348,7 +380,7 @@ where P: AsRef<Path> {
|
||||
|
||||
pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
let mut out_data = Vec::new();
|
||||
let mut writer = object::write::elf::Writer::new(Endianness::Big, false, &mut out_data);
|
||||
let mut writer = Writer::new(Endianness::Big, false, &mut out_data);
|
||||
|
||||
struct OutSection {
|
||||
index: SectionIndex,
|
||||
@@ -357,6 +389,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
rela_offset: usize,
|
||||
name: StringId,
|
||||
rela_name: Option<StringId>,
|
||||
virtual_address: Option<u64>,
|
||||
}
|
||||
struct OutSymbol {
|
||||
#[allow(dead_code)]
|
||||
@@ -376,6 +409,7 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
rela_offset: 0,
|
||||
name,
|
||||
rela_name: None,
|
||||
virtual_address: section.virtual_address,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -395,11 +429,12 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
writer.reserve_strtab_section_index();
|
||||
writer.reserve_shstrtab_section_index();
|
||||
|
||||
// Generate comment section
|
||||
// Generate .comment section
|
||||
let mut comment_data = if let Some(mw_comment) = &obj.mw_comment {
|
||||
let mut comment_data = Vec::<u8>::with_capacity(0x2C + obj.symbols.count() * 8);
|
||||
// Reserve section
|
||||
let name = writer.add_section_name(".comment".as_bytes());
|
||||
let index = writer.reserve_section_index();
|
||||
let out_section_idx = out_sections.len();
|
||||
out_sections.push(OutSection {
|
||||
index,
|
||||
rela_index: None,
|
||||
@@ -407,12 +442,42 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
rela_offset: 0,
|
||||
name,
|
||||
rela_name: None,
|
||||
virtual_address: None,
|
||||
});
|
||||
|
||||
// Generate .comment data
|
||||
let mut comment_data = Vec::<u8>::with_capacity(0x2C + obj.symbols.count() * 8);
|
||||
mw_comment.to_writer_static(&mut comment_data, Endian::Big)?;
|
||||
// Null symbol
|
||||
CommentSym { align: 0, vis_flags: 0, active_flags: 0 }
|
||||
.to_writer_static(&mut comment_data, Endian::Big)?;
|
||||
Some(comment_data)
|
||||
Some((comment_data, out_section_idx))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
// Generate .splitmeta section
|
||||
let mut split_meta = if let Some(metadata) = &obj.split_meta {
|
||||
// Reserve section
|
||||
let name = writer.add_section_name(SPLITMETA_SECTION.as_bytes());
|
||||
let index = writer.reserve_section_index();
|
||||
let out_section_idx = out_sections.len();
|
||||
out_sections.push(OutSection {
|
||||
index,
|
||||
rela_index: None,
|
||||
offset: 0,
|
||||
rela_offset: 0,
|
||||
name,
|
||||
rela_name: None,
|
||||
virtual_address: None,
|
||||
});
|
||||
|
||||
// Generate .splitmeta data
|
||||
let mut out = metadata.clone();
|
||||
out.virtual_addresses = Some(vec![
|
||||
0, // Null symbol
|
||||
]);
|
||||
Some((out, out_section_idx))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
@@ -449,10 +514,15 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
st_size: 0,
|
||||
},
|
||||
});
|
||||
if let Some(comment_data) = &mut comment_data {
|
||||
if let Some((comment_data, _)) = &mut comment_data {
|
||||
CommentSym { align: 1, vis_flags: 0, active_flags: 0 }
|
||||
.to_writer_static(comment_data, Endian::Big)?;
|
||||
}
|
||||
if let Some(virtual_addresses) =
|
||||
split_meta.as_mut().and_then(|(m, _)| m.virtual_addresses.as_mut())
|
||||
{
|
||||
virtual_addresses.push(0);
|
||||
}
|
||||
section_symbol_offset += 1;
|
||||
}
|
||||
|
||||
@@ -472,10 +542,15 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
};
|
||||
num_local = writer.symbol_count();
|
||||
out_symbols.push(OutSymbol { index, sym });
|
||||
if let Some(comment_data) = &mut comment_data {
|
||||
if let Some((comment_data, _)) = &mut comment_data {
|
||||
CommentSym { align: section.align as u32, vis_flags: 0, active_flags: 0 }
|
||||
.to_writer_static(comment_data, Endian::Big)?;
|
||||
}
|
||||
if let Some(virtual_addresses) =
|
||||
split_meta.as_mut().and_then(|(m, _)| m.virtual_addresses.as_mut())
|
||||
{
|
||||
virtual_addresses.push(section.virtual_address.unwrap_or(0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -495,7 +570,8 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
continue;
|
||||
}
|
||||
|
||||
let section_index = symbol.section.and_then(|idx| out_sections.get(idx)).map(|s| s.index);
|
||||
let section = symbol.section.and_then(|idx| out_sections.get(idx));
|
||||
let section_index = section.map(|s| s.index);
|
||||
let index = writer.reserve_symbol_index(section_index);
|
||||
let name_index = if symbol.name.is_empty() {
|
||||
None
|
||||
@@ -539,9 +615,18 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
}
|
||||
out_symbols.push(OutSymbol { index, sym });
|
||||
symbol_map[symbol_index] = Some(index.0);
|
||||
if let Some(comment_data) = &mut comment_data {
|
||||
if let Some((comment_data, _)) = &mut comment_data {
|
||||
CommentSym::from(symbol, export_all).to_writer_static(comment_data, Endian::Big)?;
|
||||
}
|
||||
if let Some(virtual_addresses) =
|
||||
split_meta.as_mut().and_then(|(m, _)| m.virtual_addresses.as_mut())
|
||||
{
|
||||
if let Some(section_vaddr) = section.and_then(|s| s.virtual_address) {
|
||||
virtual_addresses.push(section_vaddr + symbol.address);
|
||||
} else {
|
||||
virtual_addresses.push(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writer.reserve_file_header();
|
||||
@@ -576,12 +661,18 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
writer.reserve_strtab();
|
||||
writer.reserve_shstrtab();
|
||||
|
||||
// Reserve comment section
|
||||
if let Some(comment_data) = &comment_data {
|
||||
let out_section = out_sections.last_mut().unwrap();
|
||||
// Reserve .comment section
|
||||
if let Some((comment_data, idx)) = &comment_data {
|
||||
let out_section = &mut out_sections[*idx];
|
||||
out_section.offset = writer.reserve(comment_data.len(), 32);
|
||||
}
|
||||
|
||||
// Reserve .splitmeta section
|
||||
if let Some((metadata, idx)) = &split_meta {
|
||||
let out_section = &mut out_sections[*idx];
|
||||
out_section.offset = writer.reserve(metadata.write_size(false), 32);
|
||||
}
|
||||
|
||||
writer.reserve_section_headers();
|
||||
|
||||
writer.write_file_header(&object::write::elf::FileHeader {
|
||||
@@ -688,13 +779,24 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
writer.write_shstrtab();
|
||||
|
||||
// Write comment section
|
||||
if let Some(comment_data) = &comment_data {
|
||||
let out_section = out_sections.last().unwrap();
|
||||
if let Some((comment_data, idx)) = &comment_data {
|
||||
let out_section = &out_sections[*idx];
|
||||
writer.write_align(32);
|
||||
ensure!(writer.len() == out_section.offset);
|
||||
writer.write(comment_data);
|
||||
}
|
||||
|
||||
// Write .splitmeta section
|
||||
if let Some((metadata, idx)) = &split_meta {
|
||||
let out_section = &out_sections[*idx];
|
||||
writer.write_align(32);
|
||||
ensure!(writer.len() == out_section.offset);
|
||||
// object::write::elf::Writer doesn't implement std::io::Write...
|
||||
let mut data = Vec::with_capacity(metadata.write_size(false));
|
||||
metadata.to_writer(&mut data, object::BigEndian, false)?;
|
||||
writer.write(&data);
|
||||
}
|
||||
|
||||
writer.write_null_section_header();
|
||||
for ((_, section), out_section) in obj.sections.iter().zip(&out_sections) {
|
||||
writer.write_section_header(&SectionHeader {
|
||||
@@ -737,9 +839,9 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
writer.write_strtab_section_header();
|
||||
writer.write_shstrtab_section_header();
|
||||
|
||||
// Write comment section header
|
||||
if let Some(comment_data) = &comment_data {
|
||||
let out_section = out_sections.last().unwrap();
|
||||
// Write .comment section header
|
||||
if let Some((comment_data, idx)) = &comment_data {
|
||||
let out_section = &out_sections[*idx];
|
||||
writer.write_section_header(&SectionHeader {
|
||||
name: Some(out_section.name),
|
||||
sh_type: SHT_PROGBITS,
|
||||
@@ -754,6 +856,23 @@ pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
|
||||
});
|
||||
}
|
||||
|
||||
// Write .splitmeta section header
|
||||
if let Some((metadata, idx)) = &split_meta {
|
||||
let out_section = &out_sections[*idx];
|
||||
writer.write_section_header(&SectionHeader {
|
||||
name: Some(out_section.name),
|
||||
sh_type: SHT_SPLITMETA,
|
||||
sh_flags: 0,
|
||||
sh_addr: 0,
|
||||
sh_offset: out_section.offset as u64,
|
||||
sh_size: metadata.write_size(false) as u64,
|
||||
sh_link: 0,
|
||||
sh_info: 0,
|
||||
sh_addralign: 1,
|
||||
sh_entsize: 1,
|
||||
});
|
||||
}
|
||||
|
||||
ensure!(writer.reserved_len() == writer.len());
|
||||
Ok(out_data)
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ where R: Read + Seek + ?Sized {
|
||||
.unwrap_or_default() as u64,
|
||||
elf_index: idx,
|
||||
relocations: Default::default(),
|
||||
original_address: 0,
|
||||
virtual_address: None, // TODO option to set?
|
||||
file_offset: offset as u64,
|
||||
section_known,
|
||||
splits: Default::default(),
|
||||
|
||||
@@ -410,7 +410,7 @@ where R: Read + Seek + ?Sized {
|
||||
align: 0,
|
||||
elf_index: idx as usize,
|
||||
relocations: Default::default(),
|
||||
original_address: 0,
|
||||
virtual_address: None, // TODO option to set?
|
||||
file_offset: offset as u64,
|
||||
section_known: false,
|
||||
splits: Default::default(),
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::{
|
||||
|
||||
use anyhow::{anyhow, bail, ensure, Context, Result};
|
||||
use itertools::Itertools;
|
||||
use objdiff_core::obj::split_meta::SplitMeta;
|
||||
use petgraph::{graph::NodeIndex, Graph};
|
||||
use sanitise_file_name::sanitize_with_options;
|
||||
use tracing_attributes::instrument;
|
||||
@@ -882,7 +883,7 @@ fn resolve_link_order(obj: &ObjInfo) -> Result<Vec<ObjUnit>> {
|
||||
|
||||
/// Split an object into multiple relocatable objects.
|
||||
#[instrument(level = "debug", skip(obj))]
|
||||
pub fn split_obj(obj: &ObjInfo) -> Result<Vec<ObjInfo>> {
|
||||
pub fn split_obj(obj: &ObjInfo, module_name: Option<&str>) -> Result<Vec<ObjInfo>> {
|
||||
let mut objects: Vec<ObjInfo> = vec![];
|
||||
let mut object_symbols: Vec<Vec<Option<usize>>> = vec![];
|
||||
let mut name_to_obj: HashMap<String, usize> = HashMap::new();
|
||||
@@ -903,6 +904,12 @@ pub fn split_obj(obj: &ObjInfo) -> Result<Vec<ObjInfo>> {
|
||||
} else {
|
||||
split_obj.mw_comment = obj.mw_comment.clone();
|
||||
}
|
||||
split_obj.split_meta = Some(SplitMeta {
|
||||
generator: Some(format!("{} {}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION"))),
|
||||
module_name: module_name.map(str::to_string),
|
||||
module_id: Some(obj.module_id),
|
||||
virtual_addresses: None,
|
||||
});
|
||||
objects.push(split_obj);
|
||||
}
|
||||
|
||||
@@ -1083,7 +1090,7 @@ pub fn split_obj(obj: &ObjInfo) -> Result<Vec<ObjInfo>> {
|
||||
align,
|
||||
elf_index: out_section_idx + 1,
|
||||
relocations: ObjRelocations::new(out_relocations)?,
|
||||
original_address: current_address.address as u64,
|
||||
virtual_address: Some(current_address.address as u64),
|
||||
file_offset: section.file_offset
|
||||
+ (current_address.address as u64 - section.address),
|
||||
section_known: true,
|
||||
@@ -1148,7 +1155,7 @@ pub fn split_obj(obj: &ObjInfo) -> Result<Vec<ObjInfo>> {
|
||||
else {
|
||||
bail!(
|
||||
"Bad extabindex relocation @ {:#010X}",
|
||||
reloc_address as u64 + section.original_address
|
||||
reloc_address as u64 + section.virtual_address.unwrap_or(0)
|
||||
);
|
||||
};
|
||||
let target_section = &obj.sections.at_address(target_addr)?.1.name;
|
||||
@@ -1158,9 +1165,9 @@ pub fn split_obj(obj: &ObjInfo) -> Result<Vec<ObjInfo>> {
|
||||
\tTarget object: {}:{:#010X} ({})\n\
|
||||
\tTarget symbol: {:#010X} ({})\n\
|
||||
This will cause the linker to crash.\n",
|
||||
reloc_address as u64 + section.original_address,
|
||||
reloc_address as u64 + section.virtual_address.unwrap_or(0),
|
||||
section.name,
|
||||
section.original_address,
|
||||
section.virtual_address.unwrap_or(0),
|
||||
out_obj.name,
|
||||
target_section,
|
||||
target_addr,
|
||||
|
||||
Reference in New Issue
Block a user