From cabb7e8eb4f25b001088a154717e01f7fc8cd110 Mon Sep 17 00:00:00 2001 From: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com> Date: Tue, 29 Oct 2024 03:53:46 +0800 Subject: [PATCH] add keep-error-msg feature --- Cargo.toml | 4 +- src/build/elf.rs | 80 +++++++++++++++++++--------------- src/build/error.rs | 33 +++++++++++--- src/read/any.rs | 4 +- src/read/archive.rs | 8 ++-- src/read/coff/file.rs | 2 +- src/read/coff/import.rs | 8 ++-- src/read/coff/section.rs | 6 +-- src/read/elf/attributes.rs | 6 ++- src/read/elf/file.rs | 18 +++++--- src/read/elf/note.rs | 2 +- src/read/elf/relocation.rs | 4 +- src/read/elf/section.rs | 8 ++-- src/read/elf/symbol.rs | 2 +- src/read/gnu_compression.rs | 2 +- src/read/macho/dyld_cache.rs | 13 +++--- src/read/macho/fat.rs | 2 +- src/read/macho/file.rs | 2 +- src/read/macho/load_command.rs | 2 +- src/read/mod.rs | 47 ++++++++++++++------ src/read/pe/data_directory.rs | 2 +- src/read/pe/export.rs | 4 +- src/read/pe/file.rs | 8 ++-- src/read/pe/relocation.rs | 2 +- src/read/wasm.rs | 2 +- src/read/xcoff/file.rs | 2 +- src/read/xcoff/section.rs | 2 +- src/read/xcoff/symbol.rs | 8 ++-- src/write/coff/object.rs | 43 +++++++++++------- src/write/coff/writer.rs | 2 +- src/write/elf/object.rs | 27 +++++++----- src/write/elf/writer.rs | 2 +- src/write/macho.rs | 34 +++++++++------ src/write/mod.rs | 29 +++++++++--- src/write/pe.rs | 2 +- src/write/xcoff.rs | 21 +++++---- 36 files changed, 272 insertions(+), 171 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a18b2b1a..707683e4 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,7 +82,7 @@ xcoff = [] #======================================= # By default, support all read features. -default = ["read", "compression"] +default = ["read", "compression", "keep-error-msg"] #======================================= # Umbrella feature for enabling all user-facing features of this crate. Does not @@ -111,6 +111,8 @@ unstable-all = ["all", "unstable"] # stable interface of this crate. rustc-dep-of-std = ['core', 'compiler_builtins', 'alloc', 'memchr/rustc-dep-of-std'] +keep-error-msg = [] + [workspace] members = ["crates/*"] default-members = [".", "crates/examples"] diff --git a/src/build/elf.rs b/src/build/elf.rs index e655de4a..450ef1da 100644 --- a/src/build/elf.rs +++ b/src/build/elf.rs @@ -232,7 +232,7 @@ impl<'data> Builder<'data> { if index == symbols.section() { SectionData::Symbol } else { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported SHT_SYMTAB section at index {}", index ))); @@ -242,7 +242,7 @@ impl<'data> Builder<'data> { if index == symbols.shndx_section() { SectionData::SymbolSectionIndex } else { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported SHT_SYMTAB_SHNDX section at index {}", index ))); @@ -252,7 +252,7 @@ impl<'data> Builder<'data> { if index == dynamic_symbols.section() { SectionData::DynamicSymbol } else { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported SHT_DYNSYM section at index {}", index ))); @@ -270,7 +270,7 @@ impl<'data> Builder<'data> { // We simply need to preserve the data (similar to a .comment section). SectionData::Data(section.data(endian, data)?.into()) } else { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported SHT_STRTAB section at index {}", index ))); @@ -309,7 +309,7 @@ impl<'data> Builder<'data> { | (elf::EM_X86_64, elf::SHT_X86_64_UNWIND) => { SectionData::Data(section.data(endian, data)?.into()) } - _ => return Err(Error(format!("Unsupported section type {:x}", other))), + _ => return Err(Error::new(format!("Unsupported section type {:x}", other))), }, }; let sh_flags = section.sh_flags(endian).into(); @@ -318,7 +318,7 @@ impl<'data> Builder<'data> { None } else { if sh_link as usize >= sections.len() { - return Err(Error(format!( + return Err(Error::new(format!( "Invalid sh_link {} in section at index {}", sh_link, index ))); @@ -330,7 +330,7 @@ impl<'data> Builder<'data> { None } else { if sh_info as usize >= sections.len() { - return Err(Error(format!( + return Err(Error::new(format!( "Invalid sh_info link {} in section at index {}", sh_info, index ))); @@ -430,7 +430,7 @@ impl<'data> Builder<'data> { ) .map(SectionData::Relocation) } else { - return Err(Error(format!( + return Err(Error::new(format!( "Invalid sh_link {} in relocation section at index {}", link.0, index, ))); @@ -453,7 +453,7 @@ impl<'data> Builder<'data> { let rel = (*rel).into(); let symbol = if let Some(symbol) = rel.symbol(endian, is_mips64el) { if symbol.0 >= symbols_len { - return Err(Error(format!( + return Err(Error::new(format!( "Invalid symbol index {} in relocation section at index {}", symbol, index, ))); @@ -484,7 +484,7 @@ impl<'data> Builder<'data> { let mut dynamics = Vec::with_capacity(dyns.len()); for d in dyns { let tag = d.d_tag(endian).into().try_into().map_err(|_| { - Error(format!( + Error::new(format!( "Unsupported dynamic tag 0x{:x}", d.d_tag(endian).into() )) @@ -494,12 +494,11 @@ impl<'data> Builder<'data> { } let val = d.d_val(endian).into(); dynamics.push(if d.is_string(endian) { - let val = - strings - .get(val.try_into().map_err(|_| { - Error(format!("Unsupported dynamic string 0x{:x}", val)) - })?) - .map_err(|_| Error(format!("Invalid dynamic string 0x{:x}", val)))?; + let val = strings + .get(val.try_into().map_err(|_| { + Error::new(format!("Unsupported dynamic string 0x{:x}", val)) + })?) + .map_err(|_| Error::new(format!("Invalid dynamic string 0x{:x}", val)))?; Dynamic::String { tag, val: val.into(), @@ -585,7 +584,7 @@ impl<'data> Builder<'data> { while let Some(index) = indices.next()? { let index = index as usize; if index >= sections_len { - return Err(Error(format!( + return Err(Error::new(format!( "Invalid section index {} in attribute", index ))); @@ -600,7 +599,7 @@ impl<'data> Builder<'data> { while let Some(index) = indices.next()? { let index = index as usize; if index >= symbols_len { - return Err(Error(format!( + return Err(Error::new(format!( "Invalid symbol index {} in attribute", index ))); @@ -610,7 +609,7 @@ impl<'data> Builder<'data> { AttributeTag::Symbol(tag_symbols) } tag => { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported attribute tag 0x{:x} in section at index {}", tag, index, ))) @@ -668,7 +667,10 @@ impl<'data> Builder<'data> { let index = verdef.vd_ndx.get(endian) & elf::VERSYM_VERSION; let id = self.versions.next_id(); if ids.insert(index, id).is_some() { - return Err(Error(format!("Duplicate SHT_GNU_VERDEF index {}", index))); + return Err(Error::new(format!( + "Duplicate SHT_GNU_VERDEF index {}", + index + ))); } let mut names = Vec::new(); @@ -700,7 +702,10 @@ impl<'data> Builder<'data> { let index = vernaux.vna_other.get(endian) & elf::VERSYM_VERSION; let id = self.versions.next_id(); if ids.insert(index, id).is_some() { - return Err(Error(format!("Duplicate SHT_GNU_VERNEED index {}", index))); + return Err(Error::new(format!( + "Duplicate SHT_GNU_VERNEED index {}", + index + ))); } let data = VersionData::Need(VersionNeed { @@ -724,9 +729,9 @@ impl<'data> Builder<'data> { for (id, versym) in versyms.iter().skip(1).enumerate() { let index = versym.0.get(endian); let symbol = self.dynamic_symbols.get_mut(SymbolId(id)); - symbol.version = *ids - .get(&(index & elf::VERSYM_VERSION)) - .ok_or_else(|| Error(format!("Invalid SHT_GNU_VERSYM index {:x}", index)))?; + symbol.version = *ids.get(&(index & elf::VERSYM_VERSION)).ok_or_else(|| { + Error::new(format!("Invalid SHT_GNU_VERSYM index {:x}", index)) + })?; symbol.version_hidden = index & elf::VERSYM_HIDDEN != 0; } } @@ -1134,7 +1139,7 @@ impl<'data> Builder<'data> { if !self.segments.is_empty() { // TODO: support program headers in other locations. if self.header.e_phoff != writer.reserved_len() as u64 { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported e_phoff value 0x{:x}", self.header.e_phoff ))); @@ -1176,7 +1181,7 @@ impl<'data> Builder<'data> { } if section.sh_offset < writer.reserved_len() as u64 { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported sh_offset value 0x{:x} for section '{}', expected at least 0x{:x}", section.sh_offset, section.name, @@ -1229,14 +1234,14 @@ impl<'data> Builder<'data> { writer.reserve_gnu_verneed(verneed_count, vernaux_count) } _ => { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported alloc section type {:x} for section '{}'", section.sh_type, section.name, ))); } }; if out_section.offset as u64 != section.sh_offset { - return Err(Error(format!( + return Err(Error::new(format!( "Unaligned sh_offset value 0x{:x} for section '{}', expected 0x{:x}", section.sh_offset, section.name, out_section.offset, ))); @@ -1270,7 +1275,7 @@ impl<'data> Builder<'data> { continue; } _ => { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported non-alloc section type {:x}", section.sh_type ))); @@ -1391,7 +1396,7 @@ impl<'data> Builder<'data> { ))?, elf::DT_VERNEEDNUM => verneed_count as u64, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "Cannot generate value for dynamic tag 0x{:x}", tag ))) @@ -1488,7 +1493,10 @@ impl<'data> Builder<'data> { if let VersionData::Def(def) = &version.data { let mut names = def.names.iter(); let name = names.next().ok_or_else(|| { - Error(format!("Missing SHT_GNU_VERDEF name {}", version.id.0)) + Error::new(format!( + "Missing SHT_GNU_VERDEF name {}", + version.id.0 + )) })?; writer.write_gnu_verdef(&write::elf::Verdef { version: elf::VER_DEF_CURRENT, @@ -1530,7 +1538,7 @@ impl<'data> Builder<'data> { } } _ => { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported alloc section type {:x}", section.sh_type ))); @@ -1571,7 +1579,7 @@ impl<'data> Builder<'data> { | SectionData::SymbolSectionIndex | SectionData::String => {} _ => { - return Err(Error(format!( + return Err(Error::new(format!( "Unsupported non-alloc section type {:x}", section.sh_type ))); @@ -1655,7 +1663,7 @@ impl<'data> Builder<'data> { } SectionData::Attributes(_) => out_section.attributes.len() as u64, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "Unimplemented size for section type {:x}", section.sh_type ))) @@ -1665,7 +1673,7 @@ impl<'data> Builder<'data> { if let Some(index) = out_sections_index[id.0] { index.0 } else { - return Err(Error(format!( + return Err(Error::new(format!( "Invalid sh_link from section '{}' to deleted section '{}'", section.name, self.sections.get(id).name, @@ -1678,7 +1686,7 @@ impl<'data> Builder<'data> { if let Some(index) = out_sections_index[id.0] { index.0 } else { - return Err(Error(format!( + return Err(Error::new(format!( "Invalid sh_info link from section '{}' to deleted section '{}'", section.name, self.sections.get(id).name, diff --git a/src/build/error.rs b/src/build/error.rs index 364aa2f9..7331a7ec 100644 --- a/src/build/error.rs +++ b/src/build/error.rs @@ -1,4 +1,4 @@ -use alloc::string::String; +use alloc::string::{String, ToString}; use core::{fmt, result}; #[cfg(feature = "std")] use std::error; @@ -7,18 +7,31 @@ use crate::{read, write}; /// The error type used within the build module. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct Error(pub(super) String); +pub struct Error(#[cfg(feature = "keep-error-msg")] pub(crate) String); impl Error { - pub(super) fn new(message: impl Into) -> Self { - Error(message.into()) + #[inline(always)] + pub(super) fn new(#[allow(unused_variables)] message: impl Into) -> Self { + Self( + #[cfg(feature = "keep-error-msg")] + message.into(), + ) } } impl fmt::Display for Error { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.0) + f.write_str({ + #[cfg(feature = "keep-error-msg")] + { + &self.0 + } + #[cfg(not(feature = "keep-error-msg"))] + { + "Error" + } + }) } } @@ -27,13 +40,19 @@ impl error::Error for Error {} impl From for Error { fn from(error: read::Error) -> Error { - Error(format!("{}", error)) + Error( + #[cfg(feature = "keep-error-msg")] + error.0.to_string(), + ) } } impl From for Error { fn from(error: write::Error) -> Error { - Error(error.0) + Error( + #[cfg(feature = "keep-error-msg")] + error.0, + ) } } diff --git a/src/read/any.rs b/src/read/any.rs index 6ce20bc2..6a86151c 100644 --- a/src/read/any.rs +++ b/src/read/any.rs @@ -262,7 +262,7 @@ impl<'data, R: ReadRef<'data>> File<'data, R> { #[cfg(feature = "xcoff")] FileKind::Xcoff64 => File::Xcoff64(xcoff::XcoffFile64::parse(data)?), #[allow(unreachable_patterns)] - _ => return Err(Error("Unsupported file format")), + _ => return Err(Error::new("Unsupported file format")), }) } @@ -278,7 +278,7 @@ impl<'data, R: ReadRef<'data>> File<'data, R> { Some(read::AddressSize::U32) => { File::MachO32(macho::MachOFile32::parse_dyld_cache_image(image)?) } - _ => return Err(Error("Unsupported file format")), + _ => return Err(Error::new("Unsupported file format")), }) } diff --git a/src/read/archive.rs b/src/read/archive.rs index f4fc757c..f3bbefcc 100644 --- a/src/read/archive.rs +++ b/src/read/archive.rs @@ -88,7 +88,7 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> { } else if magic == archive::MAGIC { false } else { - return Err(Error("Unsupported archive identifier")); + return Err(Error::new("Unsupported archive identifier")); }; let mut members_offset = tail; @@ -294,7 +294,7 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> { match self.members { Members::Common { offset, end_offset } => { if member.0 < offset || member.0 >= end_offset { - return Err(Error("Invalid archive member offset")); + return Err(Error::new("Invalid archive member offset")); } let mut offset = member.0; ArchiveMember::parse(self.data, &mut offset, self.names, self.thin) @@ -393,7 +393,7 @@ impl<'data> ArchiveMember<'data> { .read::(offset) .read_error("Invalid archive member header")?; if header.terminator != archive::TERMINATOR { - return Err(Error("Invalid archive terminator")); + return Err(Error::new("Invalid archive terminator")); } let header_file_size = @@ -484,7 +484,7 @@ impl<'data> ArchiveMember<'data> { .read_bytes(&mut offset, 2) .read_error("Invalid AIX big archive terminator")?; if terminator != archive::TERMINATOR { - return Err(Error("Invalid AIX big archive terminator")); + return Err(Error::new("Invalid AIX big archive terminator")); } let size = parse_u64_digits(&header.size, 10) diff --git a/src/read/coff/file.rs b/src/read/coff/file.rs index 525c11d3..6e268853 100644 --- a/src/read/coff/file.rs +++ b/src/read/coff/file.rs @@ -372,7 +372,7 @@ impl CoffHeader for pe::AnonObjectHeaderBigobj { || header.version.get(LE) < 2 || header.class_id != pe::ANON_OBJECT_HEADER_BIGOBJ_CLASS_ID { - return Err(read::Error("Invalid COFF bigobj header values")); + return Err(read::Error::new("Invalid COFF bigobj header values")); } // TODO: maybe validate that the machine is known? diff --git a/src/read/coff/import.rs b/src/read/coff/import.rs index 91f9fd70..de188e74 100644 --- a/src/read/coff/import.rs +++ b/src/read/coff/import.rs @@ -47,7 +47,7 @@ impl<'data> ImportFile<'data> { pe::IMPORT_OBJECT_CODE => ImportType::Code, pe::IMPORT_OBJECT_DATA => ImportType::Data, pe::IMPORT_OBJECT_CONST => ImportType::Const, - _ => return Err(Error("Invalid COFF import library import type")), + _ => return Err(Error::new("Invalid COFF import library import type")), }, import: match header.name_type() { pe::IMPORT_OBJECT_ORDINAL => None, @@ -60,7 +60,7 @@ impl<'data> ImportFile<'data> { .unwrap(), ), pe::IMPORT_OBJECT_NAME_EXPORTAS => data.export(), - _ => return Err(Error("Unknown COFF import library name type")), + _ => return Err(Error::new("Unknown COFF import library name type")), } .map(ByteString), }) @@ -139,9 +139,9 @@ impl pe::ImportObjectHeader { .read::(offset) .read_error("Invalid COFF import library header size")?; if header.sig1.get(LE) != 0 || header.sig2.get(LE) != pe::IMPORT_OBJECT_HDR_SIG2 { - Err(Error("Invalid COFF import library header")) + Err(Error::new("Invalid COFF import library header")) } else if header.version.get(LE) != 0 { - Err(Error("Unknown COFF import library header version")) + Err(Error::new("Unknown COFF import library header version")) } else { Ok(header) } diff --git a/src/read/coff/section.rs b/src/read/coff/section.rs index 280b5c43..755624de 100644 --- a/src/read/coff/section.rs +++ b/src/read/coff/section.rs @@ -468,7 +468,7 @@ impl pe::ImageSectionHeader { b'0'..=b'9' => byte - b'0' + 52, b'+' => 62, b'/' => 63, - _ => return Err(Error("Invalid COFF section name base-64 offset")), + _ => return Err(Error::new("Invalid COFF section name base-64 offset")), }; offset = offset * 64 + digit as u64; } @@ -482,7 +482,7 @@ impl pe::ImageSectionHeader { let digit = match byte { b'0'..=b'9' => byte - b'0', 0 => break, - _ => return Err(Error("Invalid COFF section name base-10 offset")), + _ => return Err(Error::new("Invalid COFF section name base-10 offset")), }; offset = offset * 10 + digit as u32; } @@ -583,7 +583,7 @@ impl pe::ImageSectionHeader { .read_error("Invalid COFF relocation offset or number")?; number = extended_relocation_info.virtual_address.get(LE) as usize; if number == 0 { - return Err(Error("Invalid COFF relocation number")); + return Err(Error::new("Invalid COFF relocation number")); } pointer += core::mem::size_of::() as u64; // Extended relocation info does not contribute to the count of sections. diff --git a/src/read/elf/attributes.rs b/src/read/elf/attributes.rs index 39bc2219..9d3e5012 100644 --- a/src/read/elf/attributes.rs +++ b/src/read/elf/attributes.rs @@ -46,7 +46,7 @@ impl<'data, Elf: FileHeader> AttributesSection<'data, Elf> { pub fn subsections(&self) -> Result> { // There is currently only one format version. if self.version != b'A' { - return Err(Error("Unsupported ELF attributes section version")); + return Err(Error::new("Unsupported ELF attributes section version")); } Ok(AttributesSubsectionIterator { @@ -201,7 +201,9 @@ impl<'data, Elf: FileHeader> AttributesSubsubsectionIterator<'data, Elf> { } else if tag == elf::Tag_File { Bytes(&[]) } else { - return Err(Error("Unimplemented ELF attributes sub-subsection tag")); + return Err(Error::new( + "Unimplemented ELF attributes sub-subsection tag", + )); }; Ok(AttributesSubsubsection { diff --git a/src/read/elf/file.rs b/src/read/elf/file.rs index 6de69ee5..81940cf4 100644 --- a/src/read/elf/file.rs +++ b/src/read/elf/file.rs @@ -529,7 +529,7 @@ pub trait FileHeader: Debug + Pod { .read_at::(0) .read_error("Invalid ELF header size or alignment")?; if !header.is_supported() { - return Err(Error("Unsupported ELF header")); + return Err(Error::new("Unsupported ELF header")); } // TODO: Check self.e_ehsize? Ok(header) @@ -585,7 +585,7 @@ pub trait FileHeader: Debug + Pod { let shentsize = usize::from(self.e_shentsize(endian)); if shentsize != mem::size_of::() { // Section header size must match. - return Err(Error("Invalid ELF section header entry size")); + return Err(Error::new("Invalid ELF section header entry size")); } data.read_at(shoff) .map(Some) @@ -607,7 +607,9 @@ pub trait FileHeader: Debug + Pod { Ok(section_0.sh_info(endian) as usize) } else { // Section 0 must exist if e_phnum overflows. - Err(Error("Missing ELF section headers for e_phnum overflow")) + Err(Error::new( + "Missing ELF section headers for e_phnum overflow", + )) } } @@ -650,10 +652,12 @@ pub trait FileHeader: Debug + Pod { section_0.sh_link(endian) } else { // Section 0 must exist if we're trying to read e_shstrndx. - return Err(Error("Missing ELF section headers for e_shstrndx overflow")); + return Err(Error::new( + "Missing ELF section headers for e_shstrndx overflow", + )); }; if index == 0 { - return Err(Error("Missing ELF e_shstrndx")); + return Err(Error::new("Missing ELF e_shstrndx")); } Ok(index) } @@ -680,7 +684,7 @@ pub trait FileHeader: Debug + Pod { let phentsize = self.e_phentsize(endian) as usize; if phentsize != mem::size_of::() { // Program header size must match. - return Err(Error("Invalid ELF program header entry size")); + return Err(Error::new("Invalid ELF program header entry size")); } data.read_slice_at(phoff, phnum) .read_error("Invalid ELF program header size or alignment") @@ -708,7 +712,7 @@ pub trait FileHeader: Debug + Pod { let shentsize = usize::from(self.e_shentsize(endian)); if shentsize != mem::size_of::() { // Section header size must match. - return Err(Error("Invalid ELF section header entry size")); + return Err(Error::new("Invalid ELF section header entry size")); } data.read_slice_at(shoff, shnum) .read_error("Invalid ELF section header offset/size/alignment") diff --git a/src/read/elf/note.rs b/src/read/elf/note.rs index bf4a3aed..9cb5f920 100644 --- a/src/read/elf/note.rs +++ b/src/read/elf/note.rs @@ -39,7 +39,7 @@ where let align = match align.into() { 0u64..=4 => 4, 8 => 8, - _ => return Err(Error("Invalid ELF note alignment")), + _ => return Err(Error::new("Invalid ELF note alignment")), }; // TODO: check data alignment? Ok(NoteIterator { diff --git a/src/read/elf/relocation.rs b/src/read/elf/relocation.rs index f73ff288..992d2b11 100644 --- a/src/read/elf/relocation.rs +++ b/src/read/elf/relocation.rs @@ -45,14 +45,14 @@ impl RelocationSections { continue; } if sh_info.0 >= relocations.len() { - return Err(Error("Invalid ELF sh_info for relocation section")); + return Err(Error::new("Invalid ELF sh_info for relocation section")); } // We don't support relocations that apply to other relocation sections // because it interferes with the chaining of relocation sections below. let sh_info_type = sections.section(sh_info)?.sh_type(endian); if sh_info_type == elf::SHT_REL || sh_info_type == elf::SHT_RELA { - return Err(Error("Unsupported ELF sh_info for relocation section")); + return Err(Error::new("Unsupported ELF sh_info for relocation section")); } // Handle multiple relocation sections by chaining them. diff --git a/src/read/elf/section.rs b/src/read/elf/section.rs index f175d84d..e6647dbd 100644 --- a/src/read/elf/section.rs +++ b/src/read/elf/section.rs @@ -82,7 +82,7 @@ impl<'data, Elf: FileHeader, R: ReadRef<'data>> SectionTable<'data, Elf, R> { /// Returns an error for the null section at index 0. pub fn section(&self, index: SectionIndex) -> read::Result<&'data Elf::SectionHeader> { if index == SectionIndex(0) { - return Err(read::Error("Invalid ELF section index")); + return Err(read::Error::new("Invalid ELF section index")); } self.sections .get(index.0) @@ -162,7 +162,7 @@ impl<'data, Elf: FileHeader, R: ReadRef<'data>> SectionTable<'data, Elf, R> { let section = self.section(index)?; match section.sh_type(endian) { elf::SHT_DYNSYM | elf::SHT_SYMTAB => {} - _ => return Err(Error("Invalid ELF symbol table section type")), + _ => return Err(Error::new("Invalid ELF symbol table section type")), } SymbolTable::parse(endian, data, self, index, section) } @@ -433,7 +433,7 @@ impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSection<'data, 'file, return Ok(None); }; if self.file.relocations.get(relocation_index).is_some() { - return Err(Error( + return Err(Error::new( "Unsupported ELF section with multiple relocation sections", )); } @@ -495,7 +495,7 @@ impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSection<'data, 'file, let format = match header.ch_type(endian) { elf::ELFCOMPRESS_ZLIB => CompressionFormat::Zlib, elf::ELFCOMPRESS_ZSTD => CompressionFormat::Zstandard, - _ => return Err(Error("Unsupported ELF compression type")), + _ => return Err(Error::new("Unsupported ELF compression type")), }; let uncompressed_size = header.ch_size(endian).into(); Ok(Some(CompressedFileRange { diff --git a/src/read/elf/symbol.rs b/src/read/elf/symbol.rs index 3c0bee35..f134720a 100644 --- a/src/read/elf/symbol.rs +++ b/src/read/elf/symbol.rs @@ -154,7 +154,7 @@ impl<'data, Elf: FileHeader, R: ReadRef<'data>> SymbolTable<'data, Elf, R> { /// Returns an error for null entry at index 0. pub fn symbol(&self, index: SymbolIndex) -> read::Result<&'data Elf::Sym> { if index == SymbolIndex(0) { - return Err(read::Error("Invalid ELF symbol index")); + return Err(read::Error::new("Invalid ELF symbol index")); } self.symbols .get(index.0) diff --git a/src/read/gnu_compression.rs b/src/read/gnu_compression.rs index 7ef7d91e..974417d3 100644 --- a/src/read/gnu_compression.rs +++ b/src/read/gnu_compression.rs @@ -17,7 +17,7 @@ pub(super) fn compressed_file_range<'data, R: ReadRef<'data>>( .read_bytes(&mut offset, 8) .read_error("GNU compressed section is too short")?; if header != b"ZLIB\0\0\0\0" { - return Err(Error("Invalid GNU compressed section header")); + return Err(Error::new("Invalid GNU compressed section header")); } let uncompressed_size = file_data .read::>(&mut offset) diff --git a/src/read/macho/dyld_cache.rs b/src/read/macho/dyld_cache.rs index 6375a369..d2949818 100644 --- a/src/read/macho/dyld_cache.rs +++ b/src/read/macho/dyld_cache.rs @@ -75,7 +75,7 @@ where None => 0, }; if subcache_data.len() != subcaches_count + symbols_subcache_uuid.is_some() as usize { - return Err(Error("Incorrect number of SubCaches")); + return Err(Error::new("Incorrect number of SubCaches")); } // Split out the .symbols subcache data from the other subcaches. @@ -98,7 +98,7 @@ where for (&data, uuid) in subcache_data.iter().zip(uuids) { let sc_header = macho::DyldCacheHeader::::parse(data)?; if &sc_header.uuid != uuid { - return Err(Error("Unexpected SubCache UUID")); + return Err(Error::new("Unexpected SubCache UUID")); } let mappings = sc_header.mappings(endian, data)?; subcaches.push(DyldSubCache { data, mappings }); @@ -111,7 +111,7 @@ where Some((data, uuid)) => { let sc_header = macho::DyldCacheHeader::::parse(data)?; if sc_header.uuid != uuid { - return Err(Error("Unexpected .symbols SubCache UUID")); + return Err(Error::new("Unexpected .symbols SubCache UUID")); } let mappings = sc_header.mappings(endian, data)?; Some(DyldSubCache { data, mappings }) @@ -222,7 +222,8 @@ where pub fn path(&self) -> Result<&'data str> { let path = self.image_info.path(self.cache.endian, self.cache.data)?; // The path should always be ascii, so from_utf8 should always succeed. - let path = core::str::from_utf8(path).map_err(|_| Error("Path string not valid utf-8"))?; + let path = + core::str::from_utf8(path).map_err(|_| Error::new("Path string not valid utf-8"))?; Ok(path) } @@ -232,7 +233,7 @@ where let address = self.image_info.address.get(self.cache.endian); self.cache .data_and_offset_for_address(address) - .ok_or(Error("Address not found in any mapping")) + .ok_or(Error::new("Address not found in any mapping")) } /// Parse this image into an Object. @@ -262,7 +263,7 @@ impl macho::DyldCacheHeader { b"dyld_v1 armv7k\0" => (Architecture::Arm, false), b"dyld_v1 arm64\0" => (Architecture::Aarch64, false), b"dyld_v1 arm64e\0" => (Architecture::Aarch64, false), - _ => return Err(Error("Unrecognized dyld cache magic")), + _ => return Err(Error::new("Unrecognized dyld cache magic")), }; let endian = E::from_big_endian(is_big_endian).read_error("Unsupported dyld cache endian")?; diff --git a/src/read/macho/fat.rs b/src/read/macho/fat.rs index 9a049d98..0fa4947e 100644 --- a/src/read/macho/fat.rs +++ b/src/read/macho/fat.rs @@ -35,7 +35,7 @@ impl<'data, Fat: FatArch> MachOFatFile<'data, Fat> { .read::(&mut offset) .read_error("Invalid fat header size or alignment")?; if header.magic.get(BigEndian) != Fat::MAGIC { - return Err(Error("Invalid fat magic")); + return Err(Error::new("Invalid fat magic")); } let arches = data .read_slice::(&mut offset, header.nfat_arch.get(BigEndian) as usize) diff --git a/src/read/macho/file.rs b/src/read/macho/file.rs index d3721cd1..a564da9a 100644 --- a/src/read/macho/file.rs +++ b/src/read/macho/file.rs @@ -637,7 +637,7 @@ pub trait MachHeader: Debug + Pod { .read_at::(offset) .read_error("Invalid Mach-O header size or alignment")?; if !header.is_supported() { - return Err(Error("Unsupported Mach-O header")); + return Err(Error::new("Unsupported Mach-O header")); } Ok(header) } diff --git a/src/read/macho/load_command.rs b/src/read/macho/load_command.rs index 1429e1d9..773c76b8 100644 --- a/src/read/macho/load_command.rs +++ b/src/read/macho/load_command.rs @@ -47,7 +47,7 @@ impl<'data, E: Endian> LoadCommandIterator<'data, E> { let cmd = header.cmd.get(self.endian); let cmdsize = header.cmdsize.get(self.endian) as usize; if cmdsize < mem::size_of::>() { - return Err(Error("Invalid Mach-O load command size")); + return Err(Error::new("Invalid Mach-O load command size")); } let data = self .data diff --git a/src/read/mod.rs b/src/read/mod.rs index 74954476..17824eff 100644 --- a/src/read/mod.rs +++ b/src/read/mod.rs @@ -113,12 +113,31 @@ mod private { /// The error type used within the read module. #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct Error(pub(crate) &'static str); +pub struct Error(#[cfg(feature = "keep-error-msg")] pub(crate) &'static str); + +impl Error { + #[inline(always)] + pub(crate) fn new(#[allow(unused_variables)] message: &'static str) -> Self { + Self( + #[cfg(feature = "keep-error-msg")] + message, + ) + } +} impl fmt::Display for Error { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.0) + f.write_str({ + #[cfg(feature = "keep-error-msg")] + { + self.0 + } + #[cfg(not(feature = "keep-error-msg"))] + { + "Error" + } + }) } } @@ -134,19 +153,19 @@ trait ReadError { impl ReadError for result::Result { fn read_error(self, error: &'static str) -> Result { - self.map_err(|()| Error(error)) + self.map_err(|()| Error::new(error)) } } impl ReadError for result::Result { fn read_error(self, error: &'static str) -> Result { - self.map_err(|_| Error(error)) + self.map_err(|_| Error::new(error)) } } impl ReadError for Option { fn read_error(self, error: &'static str) -> Result { - self.ok_or(Error(error)) + self.ok_or(Error::new(error)) } } @@ -290,7 +309,7 @@ impl FileKind { .read_bytes_at(offset, 16) .read_error("Could not read file magic")?; if magic.len() < 16 { - return Err(Error("File too short")); + return Err(Error::new("File too short")); } let kind = match [magic[0], magic[1], magic[2], magic[3], magic[4], magic[5], magic[6], magic[7]] { @@ -325,7 +344,7 @@ impl FileKind { Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR64_MAGIC) => { FileKind::Pe64 } - _ => return Err(Error("Unknown MS-DOS file")), + _ => return Err(Error::new("Unknown MS-DOS file")), } } // TODO: more COFF machines @@ -347,14 +366,14 @@ impl FileKind { // offset == 0 restriction is because anon_object_class_id only looks at offset 0 match coff::anon_object_class_id(data) { Ok(crate::pe::ANON_OBJECT_HEADER_BIGOBJ_CLASS_ID) => FileKind::CoffBig, - _ => return Err(Error("Unknown anon object file")), + _ => return Err(Error::new("Unknown anon object file")), } } #[cfg(feature = "xcoff")] [0x01, 0xdf, ..] => FileKind::Xcoff32, #[cfg(feature = "xcoff")] [0x01, 0xf7, ..] => FileKind::Xcoff64, - _ => return Err(Error("Unknown file magic")), + _ => return Err(Error::new("Unknown file magic")), }; Ok(kind) } @@ -833,15 +852,15 @@ impl RelocationMap { } } _ => { - return Err(Error("Unsupported relocation target")); + return Err(Error::new("Unsupported relocation target")); } }, _ => { - return Err(Error("Unsupported relocation type")); + return Err(Error::new("Unsupported relocation type")); } } if self.0.insert(offset, entry).is_some() { - return Err(Error("Multiple relocations for offset")); + return Err(Error::new("Multiple relocations for offset")); } Ok(()) } @@ -1022,14 +1041,14 @@ impl<'data> CompressedData<'data> { _ => unreachable!(), } if size != decompressed.len() { - return Err(Error( + return Err(Error::new( "Uncompressed data size does not match compression header", )); } Ok(Cow::Owned(decompressed)) } - _ => Err(Error("Unsupported compressed data.")), + _ => Err(Error::new("Unsupported compressed data.")), } } } diff --git a/src/read/pe/data_directory.rs b/src/read/pe/data_directory.rs index be7a00fd..bc01e795 100644 --- a/src/read/pe/data_directory.rs +++ b/src/read/pe/data_directory.rs @@ -187,7 +187,7 @@ impl pe::ImageDataDirectory { .read_error("Invalid data dir virtual address")?; let size = self.size.get(LE); if size > section_size { - return Err(Error("Invalid data dir size")); + return Err(Error::new("Invalid data dir size")); } Ok((offset, size)) } diff --git a/src/read/pe/export.rs b/src/read/pe/export.rs index d66d406e..9bca1188 100644 --- a/src/read/pe/export.rs +++ b/src/read/pe/export.rs @@ -116,7 +116,7 @@ impl<'data> ExportTable<'data> { let address_of_name_ordinals = directory.address_of_name_ordinals.get(LE); if address_of_names != 0 { if address_of_name_ordinals == 0 { - return Err(Error("Missing PE export ordinal table")); + return Err(Error::new("Missing PE export ordinal table")); } let number = directory.number_of_names.get(LE) as usize; @@ -247,7 +247,7 @@ impl<'data> ExportTable<'data> { ExportTarget::ForwardByOrdinal(library, ordinal) } [] => { - return Err(Error("Missing PE forwarded export name")); + return Err(Error::new("Missing PE forwarded export name")); } name => ExportTarget::ForwardByName(library, name), } diff --git a/src/read/pe/file.rs b/src/read/pe/file.rs index ec9d9e6c..d2aed1a7 100644 --- a/src/read/pe/file.rs +++ b/src/read/pe/file.rs @@ -513,7 +513,7 @@ impl pe::ImageDosHeader { .read_at::(0) .read_error("Invalid DOS header size or alignment")?; if dos_header.e_magic.get(LE) != pe::IMAGE_DOS_SIGNATURE { - return Err(Error("Invalid DOS magic")); + return Err(Error::new("Invalid DOS magic")); } Ok(dos_header) } @@ -539,7 +539,7 @@ pub fn optional_header_magic<'data, R: ReadRef<'data>>(data: R) -> Result { .read_at::(offset) .read_error("Invalid NT headers offset, size, or alignment")?; if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE { - return Err(Error("Invalid PE magic")); + return Err(Error::new("Invalid PE magic")); } Ok(nt_headers.optional_header().magic()) } @@ -586,10 +586,10 @@ pub trait ImageNtHeaders: Debug + Pod { .read::(offset) .read_error("Invalid PE headers offset or size")?; if nt_headers.signature() != pe::IMAGE_NT_SIGNATURE { - return Err(Error("Invalid PE magic")); + return Err(Error::new("Invalid PE magic")); } if !nt_headers.is_valid_optional_magic() { - return Err(Error("Invalid PE optional header magic")); + return Err(Error::new("Invalid PE optional header magic")); } // Read the rest of the optional header, and then read the data directories from that. diff --git a/src/read/pe/relocation.rs b/src/read/pe/relocation.rs index 92b3f088..b2dee8a5 100644 --- a/src/read/pe/relocation.rs +++ b/src/read/pe/relocation.rs @@ -39,7 +39,7 @@ impl<'data> RelocationBlockIterator<'data> { let virtual_address = header.virtual_address.get(LE); let size = header.size_of_block.get(LE); if size <= 8 || size & 3 != 0 { - return Err(Error("Invalid PE reloc block size")); + return Err(Error::new("Invalid PE reloc block size")); } let count = (size - 8) / 2; let relocs = self diff --git a/src/read/wasm.rs b/src/read/wasm.rs index 9a174be2..1fef2097 100644 --- a/src/read/wasm.rs +++ b/src/read/wasm.rs @@ -116,7 +116,7 @@ impl<'data, R: ReadRef<'data>> WasmFile<'data, R> { match payload { wp::Payload::Version { encoding, .. } => { if encoding != wp::Encoding::Module { - return Err(Error("Unsupported Wasm encoding")); + return Err(Error::new("Unsupported Wasm encoding")); } } wp::Payload::TypeSection(section) => { diff --git a/src/read/xcoff/file.rs b/src/read/xcoff/file.rs index 6d8de8dd..4a5c08b3 100644 --- a/src/read/xcoff/file.rs +++ b/src/read/xcoff/file.rs @@ -293,7 +293,7 @@ pub trait FileHeader: Debug + Pod { .read::(offset) .read_error("Invalid XCOFF header size or alignment")?; if !header.is_supported() { - return Err(Error("Unsupported XCOFF header")); + return Err(Error::new("Unsupported XCOFF header")); } Ok(header) } diff --git a/src/read/xcoff/section.rs b/src/read/xcoff/section.rs index dac3c2a3..5e583854 100644 --- a/src/read/xcoff/section.rs +++ b/src/read/xcoff/section.rs @@ -389,7 +389,7 @@ impl SectionHeader for xcoff::SectionHeader32 { // and an STYP_OVRFLO section header will contain the actual count of relocation entries in // the s_paddr field. if reloc_num == 65535 { - return Err(Error("Overflow section is not supported yet.")); + return Err(Error::new("Overflow section is not supported yet.")); } data.read_slice_at(self.s_relptr().into(), reloc_num) .read_error("Invalid XCOFF relocation offset or number") diff --git a/src/read/xcoff/symbol.rs b/src/read/xcoff/symbol.rs index 248976a6..ead96eca 100644 --- a/src/read/xcoff/symbol.rs +++ b/src/read/xcoff/symbol.rs @@ -131,7 +131,7 @@ where pub fn symbol(&self, index: SymbolIndex) -> Result<&'data Xcoff::Symbol> { let symbol = self.symbol_unchecked(index)?; if symbol.is_null() { - return Err(Error("Invalid XCOFF symbol index")); + return Err(Error::new("Invalid XCOFF symbol index")); } Ok(symbol) } @@ -142,7 +142,7 @@ where let aux_file = self.get::(index, offset)?; if let Some(aux_type) = aux_file.x_auxtype() { if aux_type != xcoff::AUX_FILE { - return Err(Error("Invalid index for file auxiliary symbol.")); + return Err(Error::new("Invalid index for file auxiliary symbol.")); } } Ok(aux_file) @@ -154,7 +154,9 @@ where let aux_csect = self.get::(index, offset)?; if let Some(aux_type) = aux_csect.x_auxtype() { if aux_type != xcoff::AUX_CSECT { - return Err(Error("Invalid index/offset for csect auxiliary symbol.")); + return Err(Error::new( + "Invalid index/offset for csect auxiliary symbol.", + )); } } Ok(aux_csect) diff --git a/src/write/coff/object.rs b/src/write/coff/object.rs index 360dd522..d64928ad 100644 --- a/src/write/coff/object.rs +++ b/src/write/coff/object.rs @@ -108,7 +108,7 @@ impl<'a> Object<'a> { kind = K::Relative; } - let unsupported_reloc = || Err(Error(format!("unimplemented relocation {:?}", reloc))); + let unsupported_reloc = || Err(Error::new(format!("unimplemented relocation {:?}", reloc))); let typ = match self.architecture { Architecture::I386 => match (kind, size) { (K::Absolute, 16) => coff::IMAGE_REL_I386_DIR16, @@ -157,7 +157,7 @@ impl<'a> Object<'a> { _ => return unsupported_reloc(), }, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented architecture {:?}", self.architecture ))); @@ -171,7 +171,10 @@ impl<'a> Object<'a> { let typ = if let RelocationFlags::Coff { typ } = relocation.flags { typ } else { - return Err(Error(format!("invalid relocation flags {:?}", relocation))); + return Err(Error::new(format!( + "invalid relocation flags {:?}", + relocation + ))); }; let offset = match self.architecture { Architecture::Arm => { @@ -204,7 +207,12 @@ impl<'a> Object<'a> { coff::IMAGE_REL_AMD64_REL32_5 => 9, _ => 0, }, - _ => return Err(Error(format!("unimplemented relocation {:?}", relocation))), + _ => { + return Err(Error::new(format!( + "unimplemented relocation {:?}", + relocation + ))) + } }; relocation.addend += offset; Ok(true) @@ -214,7 +222,10 @@ impl<'a> Object<'a> { let typ = if let RelocationFlags::Coff { typ } = reloc.flags { typ } else { - return Err(Error(format!("unexpected relocation for size {:?}", reloc))); + return Err(Error::new(format!( + "unexpected relocation for size {:?}", + reloc + ))); }; let size = match self.architecture { Architecture::I386 => match typ { @@ -264,7 +275,7 @@ impl<'a> Object<'a> { }, _ => None, }; - size.ok_or_else(|| Error(format!("unsupported relocation for size {:?}", reloc))) + size.ok_or_else(|| Error::new(format!("unsupported relocation for size {:?}", reloc))) } fn coff_add_stub_symbol(&mut self, symbol_id: SymbolId) -> Result { @@ -351,7 +362,7 @@ impl<'a> Object<'a> { let comdat_section = match symbol.section { SymbolSection::Section(id) => id.0, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unsupported COMDAT symbol `{}` section {:?}", symbol.name().unwrap_or(""), symbol.section @@ -366,7 +377,7 @@ impl<'a> Object<'a> { ComdatKind::Largest => coff::IMAGE_COMDAT_SELECT_LARGEST, ComdatKind::Newest => coff::IMAGE_COMDAT_SELECT_NEWEST, ComdatKind::Unknown => { - return Err(Error(format!( + return Err(Error::new(format!( "unsupported COMDAT symbol `{}` kind {:?}", symbol.name().unwrap_or(""), comdat.kind @@ -376,7 +387,7 @@ impl<'a> Object<'a> { for id in &comdat.sections { let section = &self.sections[id.0]; if section.symbol.is_none() { - return Err(Error(format!( + return Err(Error::new(format!( "missing symbol for COMDAT section `{}`", section.name().unwrap_or(""), ))); @@ -428,7 +439,7 @@ impl<'a> Object<'a> { (Architecture::I386, None) => coff::IMAGE_FILE_MACHINE_I386, (Architecture::X86_64, None) => coff::IMAGE_FILE_MACHINE_AMD64, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented architecture {:?} with sub-architecture {:?}", self.architecture, self.sub_architecture ))); @@ -487,7 +498,7 @@ impl<'a> Object<'a> { | SectionKind::Unknown | SectionKind::Metadata | SectionKind::Elf(_) => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented section `{}` kind {:?}", section.name().unwrap_or(""), section.kind @@ -517,7 +528,7 @@ impl<'a> Object<'a> { 4096 => coff::IMAGE_SCN_ALIGN_4096BYTES, 8192 => coff::IMAGE_SCN_ALIGN_8192BYTES, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented section `{}` align {}", section.name().unwrap_or(""), section.align @@ -547,7 +558,7 @@ impl<'a> Object<'a> { let typ = if let RelocationFlags::Coff { typ } = reloc.flags { typ } else { - return Err(Error("invalid relocation flags".into())); + return Err(Error::new("invalid relocation flags")); }; writer.write_relocation(writer::Relocation { virtual_address: reloc.offset as u32, @@ -588,7 +599,7 @@ impl<'a> Object<'a> { SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls => { match symbol.section { SymbolSection::None => { - return Err(Error(format!( + return Err(Error::new(format!( "missing section for symbol `{}`", symbol.name().unwrap_or("") ))); @@ -601,7 +612,7 @@ impl<'a> Object<'a> { // TODO: does this need aux symbol records too? _ if symbol.weak => coff::IMAGE_SYM_CLASS_WEAK_EXTERNAL, SymbolScope::Unknown => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented symbol `{}` scope {:?}", symbol.name().unwrap_or(""), symbol.scope @@ -616,7 +627,7 @@ impl<'a> Object<'a> { } } SymbolKind::Unknown => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented symbol `{}` kind {:?}", symbol.name().unwrap_or(""), symbol.kind diff --git a/src/write/coff/writer.rs b/src/write/coff/writer.rs index 9d06dfae..db45070d 100644 --- a/src/write/coff/writer.rs +++ b/src/write/coff/writer.rs @@ -128,7 +128,7 @@ impl<'a> Writer<'a> { // Start writing. self.buffer .reserve(self.len) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; + .map_err(|_| Error::new(String::from("Cannot allocate buffer")))?; // Write file header. let header = pe::ImageFileHeader { diff --git a/src/write/elf/object.rs b/src/write/elf/object.rs index cd6b8ead..da09711f 100644 --- a/src/write/elf/object.rs +++ b/src/write/elf/object.rs @@ -148,7 +148,7 @@ impl<'a> Object<'a> { Architecture::Sparc64 => true, Architecture::Xtensa => true, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented architecture {:?}", self.architecture ))); @@ -171,7 +171,12 @@ impl<'a> Object<'a> { return Ok(()); }; - let unsupported_reloc = || Err(Error(format!("unimplemented ELF relocation {:?}", reloc))); + let unsupported_reloc = || { + Err(Error::new(format!( + "unimplemented ELF relocation {:?}", + reloc + ))) + }; let r_type = match self.architecture { Architecture::Aarch64 => match (kind, encoding, size) { (K::Absolute, E::Generic, 64) => elf::R_AARCH64_ABS64, @@ -346,7 +351,7 @@ impl<'a> Object<'a> { _ => return unsupported_reloc(), }, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented architecture {:?}", self.architecture ))); @@ -366,7 +371,7 @@ impl<'a> Object<'a> { let r_type = if let RelocationFlags::Elf { r_type } = reloc.flags { r_type } else { - return Err(Error("invalid relocation flags".into())); + return Err(Error::new("invalid relocation flags")); }; // This only needs to support architectures that use implicit addends. let size = match self.architecture { @@ -403,13 +408,13 @@ impl<'a> Object<'a> { _ => None, }, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented architecture {:?}", self.architecture ))); } }; - size.ok_or_else(|| Error(format!("unsupported relocation for size {:?}", reloc))) + size.ok_or_else(|| Error::new(format!("unsupported relocation for size {:?}", reloc))) } pub(crate) fn elf_is_64(&self) -> bool { @@ -449,7 +454,7 @@ impl<'a> Object<'a> { let mut comdat_offsets = Vec::with_capacity(self.comdats.len()); for comdat in &self.comdats { if comdat.kind != ComdatKind::Any { - return Err(Error(format!( + return Err(Error::new(format!( "unsupported COMDAT symbol `{}` kind {:?}", self.symbols[comdat.symbol.0].name().unwrap_or(""), comdat.kind @@ -558,7 +563,7 @@ impl<'a> Object<'a> { (Architecture::Sparc64, None) => elf::EM_SPARCV9, (Architecture::Xtensa, None) => elf::EM_XTENSA, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented architecture {:?} with sub-architecture {:?}", self.architecture, self.sub_architecture ))); @@ -627,7 +632,7 @@ impl<'a> Object<'a> { if symbol.is_undefined() { elf::STT_NOTYPE } else { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented symbol `{}` kind {:?}", symbol.name().unwrap_or(""), symbol.kind @@ -696,7 +701,7 @@ impl<'a> Object<'a> { let r_type = if let RelocationFlags::Elf { r_type } = reloc.flags { r_type } else { - return Err(Error("invalid relocation flags".into())); + return Err(Error::new("invalid relocation flags")); }; let r_sym = symbol_offsets[reloc.symbol.0].index.0; writer.write_relocation( @@ -759,7 +764,7 @@ impl<'a> Object<'a> { | SectionKind::Note | SectionKind::Elf(_) => 0, SectionKind::Unknown | SectionKind::Common | SectionKind::TlsVariables => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented section `{}` kind {:?}", section.name().unwrap_or(""), section.kind diff --git a/src/write/elf/writer.rs b/src/write/elf/writer.rs index 756910a0..187bed29 100644 --- a/src/write/elf/writer.rs +++ b/src/write/elf/writer.rs @@ -294,7 +294,7 @@ impl<'a> Writer<'a> { // Start writing. self.buffer .reserve(self.len) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; + .map_err(|_| Error::new(String::from("Cannot allocate buffer")))?; // Write file header. let e_ident = elf::Ident { diff --git a/src/write/macho.rs b/src/write/macho.rs index 9d250cdd..b76e80c1 100644 --- a/src/write/macho.rs +++ b/src/write/macho.rs @@ -267,9 +267,9 @@ impl<'a> Object<'a> { 16 => 1, 32 => 2, 64 => 3, - _ => return Err(Error(format!("unimplemented reloc size {:?}", reloc))), + _ => return Err(Error::new(format!("unimplemented reloc size {:?}", reloc))), }; - let unsupported_reloc = || Err(Error(format!("unimplemented relocation {:?}", reloc))); + let unsupported_reloc = || Err(Error::new(format!("unimplemented relocation {:?}", reloc))); let (r_pcrel, r_type) = match self.architecture { Architecture::I386 => match kind { K::Absolute => (false, macho::GENERIC_RELOC_VANILLA), @@ -291,7 +291,7 @@ impl<'a> Object<'a> { _ => return unsupported_reloc(), }, _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented architecture {:?}", self.architecture ))); @@ -312,7 +312,10 @@ impl<'a> Object<'a> { { (r_type, r_pcrel) } else { - return Err(Error(format!("invalid relocation flags {:?}", relocation))); + return Err(Error::new(format!( + "invalid relocation flags {:?}", + relocation + ))); }; if r_pcrel { // For PC relative relocations on some architectures, the @@ -351,7 +354,7 @@ impl<'a> Object<'a> { if let RelocationFlags::MachO { r_length, .. } = reloc.flags { Ok(8 << r_length) } else { - Err(Error("invalid relocation flags".into())) + Err(Error::new("invalid relocation flags")) } } @@ -444,7 +447,7 @@ impl<'a> Object<'a> { SymbolKind::Text | SymbolKind::Data | SymbolKind::Tls | SymbolKind::Unknown => {} SymbolKind::File | SymbolKind::Section => continue, SymbolKind::Label => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented symbol `{}` kind {:?}", symbol.name().unwrap_or(""), symbol.kind @@ -511,7 +514,7 @@ impl<'a> Object<'a> { // Start writing. buffer .reserve(offset) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; + .map_err(|_| Error::new(String::from("Cannot allocate buffer")))?; // Write file header. let (cputype, mut cpusubtype) = match (self.architecture, self.sub_architecture) { @@ -532,7 +535,7 @@ impl<'a> Object<'a> { (macho::CPU_TYPE_POWERPC64, macho::CPU_SUBTYPE_POWERPC_ALL) } _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented architecture {:?} with sub-architecture {:?}", self.architecture, self.sub_architecture ))); @@ -586,7 +589,7 @@ impl<'a> Object<'a> { sectname .get_mut(..section.name.len()) .ok_or_else(|| { - Error(format!( + Error::new(format!( "section name `{}` is too long", section.name().unwrap_or(""), )) @@ -596,7 +599,7 @@ impl<'a> Object<'a> { segname .get_mut(..section.segment.len()) .ok_or_else(|| { - Error(format!( + Error::new(format!( "segment name `{}` is too long", section.segment().unwrap_or(""), )) @@ -620,7 +623,7 @@ impl<'a> Object<'a> { SectionKind::OtherString => macho::S_CSTRING_LITERALS, SectionKind::Other | SectionKind::Linker | SectionKind::Metadata => 0, SectionKind::Note | SectionKind::Unknown | SectionKind::Elf(_) => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented section `{}` kind {:?}", section.name().unwrap_or(""), section.kind @@ -722,7 +725,7 @@ impl<'a> Object<'a> { { (r_type, r_pcrel, r_length) } else { - return Err(Error("invalid relocation flags".into())); + return Err(Error::new("invalid relocation flags")); }; // Write explicit addend. @@ -732,7 +735,10 @@ impl<'a> Object<'a> { macho::ARM64_RELOC_ADDEND } _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))) + return Err(Error::new(format!( + "unimplemented relocation {:?}", + reloc + ))) } }; @@ -810,7 +816,7 @@ impl<'a> Object<'a> { SymbolSection::Absolute => (macho::N_ABS, 0), SymbolSection::Section(id) => (macho::N_SECT, id.0 + 1), SymbolSection::None | SymbolSection::Common => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented symbol `{}` section {:?}", symbol.name().unwrap_or(""), symbol.section diff --git a/src/write/mod.rs b/src/write/mod.rs index 9a9f2ad6..168d1ee4 100644 --- a/src/write/mod.rs +++ b/src/write/mod.rs @@ -10,7 +10,7 @@ //! and [PE](pe::Writer). use alloc::borrow::Cow; -use alloc::string::String; +use alloc::string::{String, ToString}; use alloc::vec::Vec; use core::{fmt, result, str}; #[cfg(not(feature = "std"))] @@ -49,12 +49,31 @@ pub use util::*; /// The error type used within the write module. #[derive(Debug, Clone, PartialEq, Eq)] -pub struct Error(pub(crate) String); +pub struct Error(#[cfg(feature = "keep-error-msg")] pub(crate) String); + +impl Error { + #[inline(always)] + pub(crate) fn new(#[allow(unused_variables)] message: impl AsRef) -> Self { + Self( + #[cfg(feature = "keep-error-msg")] + message.as_ref().to_string(), + ) + } +} impl fmt::Display for Error { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.0) + f.write_str({ + #[cfg(feature = "keep-error-msg")] + { + &self.0 + } + #[cfg(not(feature = "keep-error-msg"))] + { + "Error" + } + }) } } @@ -625,14 +644,14 @@ impl<'a> Object<'a> { 32 => data.write_at(offset, &U32::new(self.endian, relocation.addend as u32)), 64 => data.write_at(offset, &U64::new(self.endian, relocation.addend as u64)), _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented relocation addend {:?}", relocation ))); } } .map_err(|_| { - Error(format!( + Error::new(format!( "invalid relocation offset {}+{} (max {})", relocation.offset, size, diff --git a/src/write/pe.rs b/src/write/pe.rs index 03f79fa2..bfd4dad5 100644 --- a/src/write/pe.rs +++ b/src/write/pe.rs @@ -194,7 +194,7 @@ impl<'a> Writer<'a> { // Start writing. self.buffer .reserve(self.len as usize) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; + .map_err(|_| Error::new(String::from("Cannot allocate buffer")))?; self.buffer.write(dos_header); Ok(()) diff --git a/src/write/xcoff.rs b/src/write/xcoff.rs index 5aade24d..f311e417 100644 --- a/src/write/xcoff.rs +++ b/src/write/xcoff.rs @@ -83,7 +83,7 @@ impl<'a> Object<'a> { RelocationKind::Relative => xcoff::R_REL, RelocationKind::Got => xcoff::R_TOC, _ => { - return Err(Error(format!("unimplemented relocation {:?}", reloc))); + return Err(Error::new(format!("unimplemented relocation {:?}", reloc))); } }; let r_rsize = size - 1; @@ -95,7 +95,10 @@ impl<'a> Object<'a> { let r_rtype = if let RelocationFlags::Xcoff { r_rtype, .. } = relocation.flags { r_rtype } else { - return Err(Error(format!("invalid relocation flags {:?}", relocation))); + return Err(Error::new(format!( + "invalid relocation flags {:?}", + relocation + ))); }; if r_rtype == xcoff::R_REL { relocation.addend += 4; @@ -107,7 +110,7 @@ impl<'a> Object<'a> { let r_rsize = if let RelocationFlags::Xcoff { r_rsize, .. } = reloc.flags { r_rsize } else { - return Err(Error(format!("unexpected relocation {:?}", reloc))); + return Err(Error::new(format!("unexpected relocation {:?}", reloc))); }; Ok(r_rsize + 1) } @@ -205,7 +208,7 @@ impl<'a> Object<'a> { } } SymbolKind::Section | SymbolKind::Label | SymbolKind::Unknown => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented symbol `{}` kind {:?}", symbol.name().unwrap_or(""), symbol.kind @@ -255,7 +258,7 @@ impl<'a> Object<'a> { // Start writing. buffer .reserve(offset) - .map_err(|_| Error(String::from("Cannot allocate buffer")))?; + .map_err(|_| Error::new(String::from("Cannot allocate buffer")))?; // Write file header. if is_64 { @@ -294,7 +297,7 @@ impl<'a> Object<'a> { sectname .get_mut(..section.name.len()) .ok_or_else(|| { - Error(format!( + Error::new(format!( "section name `{}` is too long", section.name().unwrap_or(""), )) @@ -321,7 +324,7 @@ impl<'a> Object<'a> { | SectionKind::Unknown | SectionKind::TlsVariables | SectionKind::Elf(_) => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented section `{}` kind {:?}", section.name().unwrap_or(""), section.kind @@ -386,7 +389,7 @@ impl<'a> Object<'a> { if let RelocationFlags::Xcoff { r_rtype, r_rsize } = reloc.flags { (r_rtype, r_rsize) } else { - return Err(Error("invalid relocation flags".into())); + return Err(Error::new("invalid relocation flags")); }; if is_64 { let xcoff_rel = xcoff::Rel64 { @@ -533,7 +536,7 @@ impl<'a> Object<'a> { } } _ => { - return Err(Error(format!( + return Err(Error::new(format!( "unimplemented symbol `{}` kind {:?}", symbol.name().unwrap_or(""), symbol.kind