Warn rather than fail on .note.split/.comment reading

This commit is contained in:
Luke Street 2025-01-27 17:18:11 -07:00
parent 6819a8bd5f
commit 589e59a620
2 changed files with 50 additions and 49 deletions

View File

@ -159,14 +159,15 @@ fn disasm(args: DisasmArgs) -> Result<()> {
let mut files_out = buf_writer(&args.out.join("link_order.txt"))?; let mut files_out = buf_writer(&args.out.join("link_order.txt"))?;
for (unit, split_obj) in obj.link_order.iter().zip(&split_objs) { 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); log::info!("Writing {}", out_path);
let mut w = buf_writer(&out_path)?; let mut w = buf_writer(&out_path)?;
write_asm(&mut w, split_obj)?; write_asm(&mut w, split_obj)?;
w.flush()?; w.flush()?;
writeln!(files_out, "{}", file_name_from_unit(&unit.name, ".o"))?; writeln!(files_out, "{}.o", out_name)?;
} }
files_out.flush()?; files_out.flush()?;
} }
@ -199,7 +200,8 @@ fn split(args: SplitArgs) -> Result<()> {
let object = file_map let object = file_map
.get(&unit.name) .get(&unit.name)
.ok_or_else(|| anyhow!("Failed to find object file for unit '{}'", 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)?; writeln!(rsp_file, "{}", out_path)?;
if let Some(parent) = out_path.parent() { if let Some(parent) = out_path.parent() {
DirBuilder::new().recursive(true).create(parent)?; DirBuilder::new().recursive(true).create(parent)?;
@ -210,7 +212,7 @@ fn split(args: SplitArgs) -> Result<()> {
Ok(()) 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_suffix(ASM_SUFFIX).unwrap_or(str);
let str = str.strip_prefix("C:").unwrap_or(str); let str = str.strip_prefix("C:").unwrap_or(str);
let str = str.strip_prefix("D:").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")) .or_else(|| str.strip_suffix(".o"))
.unwrap_or(str); .unwrap_or(str);
let str = str.replace('\\', "/"); let str = str.replace('\\', "/");
let str = str.strip_prefix('/').unwrap_or(&str); str.strip_prefix('/').unwrap_or(&str).to_string()
format!("{str}{suffix}")
} }
const ASM_SUFFIX: &str = " (asm)"; const ASM_SUFFIX: &str = " (asm)";

View File

@ -17,7 +17,7 @@ use object::{
elf::{ProgramHeader, Rel, SectionHeader, SectionIndex, SymbolIndex, Writer}, elf::{ProgramHeader, Rel, SectionHeader, SectionIndex, SymbolIndex, Writer},
StringId, StringId,
}, },
Architecture, Endianness, Object, ObjectKind, ObjectSection, ObjectSymbol, Relocation, Architecture, Endianness, File, Object, ObjectKind, ObjectSection, ObjectSymbol, Relocation,
RelocationFlags, RelocationTarget, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection, RelocationFlags, RelocationTarget, SectionKind, Symbol, SymbolKind, SymbolScope, SymbolSection,
}; };
use typed_path::Utf8NativePath; use typed_path::Utf8NativePath;
@ -49,7 +49,7 @@ enum BoundaryState {
pub fn process_elf(path: &Utf8NativePath) -> Result<ObjInfo> { pub fn process_elf(path: &Utf8NativePath) -> Result<ObjInfo> {
let mut file = open_file(path, true)?; 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() { let architecture = match obj_file.architecture() {
Architecture::PowerPc => ObjArchitecture::PowerPc, Architecture::PowerPc => ObjArchitecture::PowerPc,
arch => bail!("Unexpected architecture: {arch:?}"), arch => bail!("Unexpected architecture: {arch:?}"),
@ -106,49 +106,14 @@ pub fn process_elf(path: &Utf8NativePath) -> Result<ObjInfo> {
}); });
} }
let mw_comment = if let Some(comment_section) = obj_file.section_by_name(".comment") { let mw_comment = load_comment(&obj_file).unwrap_or_else(|e| {
let data = comment_section.uncompressed_data()?; log::warn!("Failed to read .comment section: {e:#}");
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 {
None None
}; });
let split_meta = load_split_meta(&obj_file).unwrap_or_else(|e| {
let split_meta = if let Some(split_meta_section) = obj_file.section_by_name(SPLITMETA_SECTION) { log::warn!("Failed to read .note.split section: {e:#}");
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 {
None None
}; });
let mut symbols: Vec<ObjSymbol> = vec![]; let mut symbols: Vec<ObjSymbol> = vec![];
let mut symbol_indexes: Vec<Option<ObjSymbolIndex>> = vec![None /* ELF null symbol */]; let mut symbol_indexes: Vec<Option<ObjSymbolIndex>> = vec![None /* ELF null symbol */];
@ -384,6 +349,41 @@ pub fn process_elf(path: &Utf8NativePath) -> Result<ObjInfo> {
Ok(obj) Ok(obj)
} }
fn load_split_meta(obj_file: &File) -> Result<Option<SplitMeta>> {
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<Option<(MWComment, Vec<CommentSym>)>> {
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<Vec<u8>> { pub fn write_elf(obj: &ObjInfo, export_all: bool) -> Result<Vec<u8>> {
let mut out_data = Vec::new(); let mut out_data = Vec::new();
let mut writer = Writer::new(Endianness::Big, false, &mut out_data); let mut writer = Writer::new(Endianness::Big, false, &mut out_data);