diff --git a/src/cmd/elf.rs b/src/cmd/elf.rs index d1ed44d..8a7363d 100644 --- a/src/cmd/elf.rs +++ b/src/cmd/elf.rs @@ -159,14 +159,15 @@ fn disasm(args: DisasmArgs) -> Result<()> { let mut files_out = buf_writer(&args.out.join("link_order.txt"))?; for (unit, split_obj) in obj.link_order.iter().zip(&split_objs) { - let out_path = asm_dir.join(file_name_from_unit(&unit.name, ".s")); + let out_name = file_stem_from_unit(&unit.name); + let out_path = asm_dir.join(format!("{}.s", out_name)); log::info!("Writing {}", out_path); let mut w = buf_writer(&out_path)?; write_asm(&mut w, split_obj)?; w.flush()?; - writeln!(files_out, "{}", file_name_from_unit(&unit.name, ".o"))?; + writeln!(files_out, "{}.o", out_name)?; } files_out.flush()?; } @@ -199,7 +200,8 @@ fn split(args: SplitArgs) -> Result<()> { let object = file_map .get(&unit.name) .ok_or_else(|| anyhow!("Failed to find object file for unit '{}'", unit.name))?; - let out_path = args.out_dir.join(file_name_from_unit(&unit.name, ".o")); + let out_name = file_stem_from_unit(&unit.name); + let out_path = args.out_dir.join(format!("{}.o", out_name)); writeln!(rsp_file, "{}", out_path)?; if let Some(parent) = out_path.parent() { DirBuilder::new().recursive(true).create(parent)?; @@ -210,7 +212,7 @@ fn split(args: SplitArgs) -> Result<()> { Ok(()) } -fn file_name_from_unit(str: &str, suffix: &str) -> String { +fn file_stem_from_unit(str: &str) -> String { let str = str.strip_suffix(ASM_SUFFIX).unwrap_or(str); let str = str.strip_prefix("C:").unwrap_or(str); let str = str.strip_prefix("D:").unwrap_or(str); @@ -222,8 +224,7 @@ fn file_name_from_unit(str: &str, suffix: &str) -> String { .or_else(|| str.strip_suffix(".o")) .unwrap_or(str); let str = str.replace('\\', "/"); - let str = str.strip_prefix('/').unwrap_or(&str); - format!("{str}{suffix}") + str.strip_prefix('/').unwrap_or(&str).to_string() } const ASM_SUFFIX: &str = " (asm)"; diff --git a/src/util/elf.rs b/src/util/elf.rs index c50572f..fff1041 100644 --- a/src/util/elf.rs +++ b/src/util/elf.rs @@ -17,7 +17,7 @@ use object::{ elf::{ProgramHeader, Rel, SectionHeader, SectionIndex, SymbolIndex, Writer}, StringId, }, - Architecture, Endianness, Object, ObjectKind, ObjectSection, ObjectSymbol, Relocation, + Architecture, Endianness, File, Object, ObjectKind, ObjectSection, ObjectSymbol, Relocation, RelocationFlags, RelocationTarget, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection, }; use typed_path::Utf8NativePath; @@ -49,7 +49,7 @@ enum BoundaryState { pub fn process_elf(path: &Utf8NativePath) -> Result { let mut file = open_file(path, true)?; - let obj_file = object::read::File::parse(file.map()?)?; + let obj_file = File::parse(file.map()?)?; let architecture = match obj_file.architecture() { Architecture::PowerPc => ObjArchitecture::PowerPc, arch => bail!("Unexpected architecture: {arch:?}"), @@ -106,49 +106,14 @@ pub fn process_elf(path: &Utf8NativePath) -> Result { }); } - let mw_comment = if let Some(comment_section) = obj_file.section_by_name(".comment") { - let data = comment_section.uncompressed_data()?; - if data.is_empty() { - None - } else { - let mut reader = Cursor::new(&*data); - let header = MWComment::from_reader(&mut reader, Endian::Big) - .context("While reading .comment section")?; - log::debug!("Loaded .comment section header {:?}", header); - let mut comment_syms = Vec::with_capacity(obj_file.symbols().count()); - comment_syms.push(CommentSym::from_reader(&mut reader, Endian::Big)?); // ELF null symbol - for symbol in obj_file.symbols() { - let comment_sym = CommentSym::from_reader(&mut reader, Endian::Big)?; - log::debug!("Symbol {:?} -> Comment {:?}", symbol, comment_sym); - comment_syms.push(comment_sym); - } - ensure!( - data.len() - reader.position() as usize == 0, - ".comment section data not fully read" - ); - Some((header, comment_syms)) - } - } else { + let mw_comment = load_comment(&obj_file).unwrap_or_else(|e| { + log::warn!("Failed to read .comment section: {e:#}"); 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 metadata = SplitMeta::from_section( - split_meta_section, - obj_file.endianness(), - obj_file.is_64(), - ) - .context("While reading .note.split section")?; - log::debug!("Loaded .note.split section"); - Some(metadata) - } - } else { + }); + let split_meta = load_split_meta(&obj_file).unwrap_or_else(|e| { + log::warn!("Failed to read .note.split section: {e:#}"); None - }; + }); let mut symbols: Vec = vec![]; let mut symbol_indexes: Vec> = vec![None /* ELF null symbol */]; @@ -384,6 +349,41 @@ pub fn process_elf(path: &Utf8NativePath) -> Result { Ok(obj) } +fn load_split_meta(obj_file: &File) -> Result> { + let Some(split_meta_section) = obj_file.section_by_name(SPLITMETA_SECTION) else { + return Ok(None); + }; + let data = split_meta_section.uncompressed_data()?; + if data.is_empty() { + return Ok(None); + } + let metadata = + SplitMeta::from_section(split_meta_section, obj_file.endianness(), obj_file.is_64())?; + log::debug!("Loaded .note.split section"); + Ok(Some(metadata)) +} + +fn load_comment(obj_file: &File) -> Result)>> { + let Some(comment_section) = obj_file.section_by_name(".comment") else { + return Ok(None); + }; + let data = comment_section.uncompressed_data()?; + if data.is_empty() { + return Ok(None); + } + let mut reader = Cursor::new(&*data); + let header = MWComment::from_reader(&mut reader, Endian::Big)?; + log::debug!("Loaded .comment section header {:?}", header); + let mut comment_syms = Vec::with_capacity(obj_file.symbols().count()); + for symbol in obj_file.symbols() { + let comment_sym = CommentSym::from_reader(&mut reader, Endian::Big)?; + log::debug!("Symbol {:?} -> Comment {:?}", symbol, comment_sym); + comment_syms.push(comment_sym); + } + ensure!(data.len() == reader.position() as usize, "Section data not fully read"); + Ok(Some((header, comment_syms))) +} + pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result> { let mut out_data = Vec::new(); let mut writer = Writer::new(Endianness::Big, false, &mut out_data);