From dc0db358abe19481e475e10c32149b53370f1a1c Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:57:31 +0200 Subject: Merging upstream version 1.72.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/object/src/common.rs | 2 + vendor/object/src/elf.rs | 18 ++- vendor/object/src/pe.rs | 4 + vendor/object/src/read/any.rs | 125 +++++++++--------- vendor/object/src/read/coff/import.rs | 209 +++++++++++++++++++++++++++++++ vendor/object/src/read/coff/mod.rs | 3 + vendor/object/src/read/elf/file.rs | 1 + vendor/object/src/read/elf/note.rs | 23 ++-- vendor/object/src/read/elf/relocation.rs | 5 + vendor/object/src/read/elf/symbol.rs | 8 ++ vendor/object/src/read/mod.rs | 11 +- vendor/object/src/write/elf/object.rs | 12 ++ vendor/object/src/write/macho.rs | 30 ++--- 13 files changed, 347 insertions(+), 104 deletions(-) create mode 100644 vendor/object/src/read/coff/import.rs (limited to 'vendor/object/src') diff --git a/vendor/object/src/common.rs b/vendor/object/src/common.rs index 7d789a71d..0e6af091c 100644 --- a/vendor/object/src/common.rs +++ b/vendor/object/src/common.rs @@ -10,6 +10,7 @@ pub enum Architecture { Arm, Avr, Bpf, + Csky, I386, X86_64, #[allow(non_camel_case_types)] @@ -43,6 +44,7 @@ impl Architecture { Architecture::Arm => Some(AddressSize::U32), Architecture::Avr => Some(AddressSize::U8), Architecture::Bpf => Some(AddressSize::U64), + Architecture::Csky => Some(AddressSize::U32), Architecture::I386 => Some(AddressSize::U32), Architecture::X86_64 => Some(AddressSize::U64), Architecture::X86_64_X32 => Some(AddressSize::U32), diff --git a/vendor/object/src/elf.rs b/vendor/object/src/elf.rs index 202b3a2cc..da68ec2d4 100644 --- a/vendor/object/src/elf.rs +++ b/vendor/object/src/elf.rs @@ -1308,11 +1308,11 @@ pub const PF_MASKOS: u32 = 0x0ff0_0000; pub const PF_MASKPROC: u32 = 0xf000_0000; /// Note name for core files. -pub static ELF_NOTE_CORE: &[u8] = b"CORE"; +pub const ELF_NOTE_CORE: &[u8] = b"CORE"; /// Note name for linux core files. /// /// Notes in linux core files may also use `ELF_NOTE_CORE`. -pub static ELF_NOTE_LINUX: &[u8] = b"LINUX"; +pub const ELF_NOTE_LINUX: &[u8] = b"LINUX"; // Values for `NoteHeader*::n_type` in core files. // @@ -1826,14 +1826,18 @@ pub struct NoteHeader64 { } /// Solaris entries in the note section have this name. -pub static ELF_NOTE_SOLARIS: &[u8] = b"SUNW Solaris"; +pub const ELF_NOTE_SOLARIS: &[u8] = b"SUNW Solaris"; // Values for `n_type` when the name is `ELF_NOTE_SOLARIS`. /// Desired pagesize for the binary. pub const NT_SOLARIS_PAGESIZE_HINT: u32 = 1; /// GNU entries in the note section have this name. -pub static ELF_NOTE_GNU: &[u8] = b"GNU"; +pub const ELF_NOTE_GNU: &[u8] = b"GNU"; + +/// Go entries in the note section have this name. +// See https://go-review.googlesource.com/9520 and https://go-review.googlesource.com/10704. +pub const ELF_NOTE_GO: &[u8] = b"Go"; // Note types for `ELF_NOTE_GNU`. @@ -1870,6 +1874,12 @@ pub const NT_GNU_HWCAP: u32 = 2; /// The descriptor consists of any nonzero number of bytes. pub const NT_GNU_BUILD_ID: u32 = 3; +/// Build ID bits as generated by Go's gc compiler. +/// +/// The descriptor consists of any nonzero number of bytes. +// See https://go-review.googlesource.com/10707. +pub const NT_GO_BUILD_ID: u32 = 4; + /// Version note generated by GNU gold containing a version string. pub const NT_GNU_GOLD_VERSION: u32 = 4; diff --git a/vendor/object/src/pe.rs b/vendor/object/src/pe.rs index bac101ea0..f274d2270 100644 --- a/vendor/object/src/pe.rs +++ b/vendor/object/src/pe.rs @@ -2873,10 +2873,14 @@ pub struct ImportObjectHeader { pub name_type: U16, } +pub const IMPORT_OBJECT_TYPE_MASK: u16 = 0b11; +pub const IMPORT_OBJECT_TYPE_SHIFT: u16 = 0; pub const IMPORT_OBJECT_CODE: u16 = 0; pub const IMPORT_OBJECT_DATA: u16 = 1; pub const IMPORT_OBJECT_CONST: u16 = 2; +pub const IMPORT_OBJECT_NAME_MASK: u16 = 0b111; +pub const IMPORT_OBJECT_NAME_SHIFT: u16 = 2; /// Import by ordinal pub const IMPORT_OBJECT_ORDINAL: u16 = 0; /// Import name == public symbol name. diff --git a/vendor/object/src/read/any.rs b/vendor/object/src/read/any.rs index 342ad75fd..2e147c672 100644 --- a/vendor/object/src/read/any.rs +++ b/vendor/object/src/read/any.rs @@ -208,12 +208,9 @@ macro_rules! next_inner { /// /// Most functionality is provided by the `Object` trait implementation. #[derive(Debug)] -pub struct File<'data, R: ReadRef<'data> = &'data [u8]> { - inner: FileInternal<'data, R>, -} - -#[derive(Debug)] -enum FileInternal<'data, R: ReadRef<'data>> { +#[non_exhaustive] +#[allow(missing_docs)] +pub enum File<'data, R: ReadRef<'data> = &'data [u8]> { #[cfg(feature = "coff")] Coff(coff::CoffFile<'data, R>), #[cfg(feature = "coff")] @@ -241,33 +238,32 @@ enum FileInternal<'data, R: ReadRef<'data>> { impl<'data, R: ReadRef<'data>> File<'data, R> { /// Parse the raw file data. pub fn parse(data: R) -> Result { - let inner = match FileKind::parse(data)? { + Ok(match FileKind::parse(data)? { #[cfg(feature = "elf")] - FileKind::Elf32 => FileInternal::Elf32(elf::ElfFile32::parse(data)?), + FileKind::Elf32 => File::Elf32(elf::ElfFile32::parse(data)?), #[cfg(feature = "elf")] - FileKind::Elf64 => FileInternal::Elf64(elf::ElfFile64::parse(data)?), + FileKind::Elf64 => File::Elf64(elf::ElfFile64::parse(data)?), #[cfg(feature = "macho")] - FileKind::MachO32 => FileInternal::MachO32(macho::MachOFile32::parse(data)?), + FileKind::MachO32 => File::MachO32(macho::MachOFile32::parse(data)?), #[cfg(feature = "macho")] - FileKind::MachO64 => FileInternal::MachO64(macho::MachOFile64::parse(data)?), + FileKind::MachO64 => File::MachO64(macho::MachOFile64::parse(data)?), #[cfg(feature = "wasm")] - FileKind::Wasm => FileInternal::Wasm(wasm::WasmFile::parse(data)?), + FileKind::Wasm => File::Wasm(wasm::WasmFile::parse(data)?), #[cfg(feature = "pe")] - FileKind::Pe32 => FileInternal::Pe32(pe::PeFile32::parse(data)?), + FileKind::Pe32 => File::Pe32(pe::PeFile32::parse(data)?), #[cfg(feature = "pe")] - FileKind::Pe64 => FileInternal::Pe64(pe::PeFile64::parse(data)?), + FileKind::Pe64 => File::Pe64(pe::PeFile64::parse(data)?), #[cfg(feature = "coff")] - FileKind::Coff => FileInternal::Coff(coff::CoffFile::parse(data)?), + FileKind::Coff => File::Coff(coff::CoffFile::parse(data)?), #[cfg(feature = "coff")] - FileKind::CoffBig => FileInternal::CoffBig(coff::CoffBigFile::parse(data)?), + FileKind::CoffBig => File::CoffBig(coff::CoffBigFile::parse(data)?), #[cfg(feature = "xcoff")] - FileKind::Xcoff32 => FileInternal::Xcoff32(xcoff::XcoffFile32::parse(data)?), + FileKind::Xcoff32 => File::Xcoff32(xcoff::XcoffFile32::parse(data)?), #[cfg(feature = "xcoff")] - FileKind::Xcoff64 => FileInternal::Xcoff64(xcoff::XcoffFile64::parse(data)?), + FileKind::Xcoff64 => File::Xcoff64(xcoff::XcoffFile64::parse(data)?), #[allow(unreachable_patterns)] _ => return Err(Error("Unsupported file format")), - }; - Ok(File { inner }) + }) } /// Parse a Mach-O image from the dyld shared cache. @@ -275,33 +271,32 @@ impl<'data, R: ReadRef<'data>> File<'data, R> { pub fn parse_dyld_cache_image<'cache, E: Endian>( image: &macho::DyldCacheImage<'data, 'cache, E, R>, ) -> Result { - let inner = match image.cache.architecture().address_size() { + Ok(match image.cache.architecture().address_size() { Some(AddressSize::U64) => { - FileInternal::MachO64(macho::MachOFile64::parse_dyld_cache_image(image)?) + File::MachO64(macho::MachOFile64::parse_dyld_cache_image(image)?) } Some(AddressSize::U32) => { - FileInternal::MachO32(macho::MachOFile32::parse_dyld_cache_image(image)?) + File::MachO32(macho::MachOFile32::parse_dyld_cache_image(image)?) } _ => return Err(Error("Unsupported file format")), - }; - Ok(File { inner }) + }) } /// Return the file format. pub fn format(&self) -> BinaryFormat { - match self.inner { + match self { #[cfg(feature = "coff")] - FileInternal::Coff(_) | FileInternal::CoffBig(_) => BinaryFormat::Coff, + File::Coff(_) | File::CoffBig(_) => BinaryFormat::Coff, #[cfg(feature = "elf")] - FileInternal::Elf32(_) | FileInternal::Elf64(_) => BinaryFormat::Elf, + File::Elf32(_) | File::Elf64(_) => BinaryFormat::Elf, #[cfg(feature = "macho")] - FileInternal::MachO32(_) | FileInternal::MachO64(_) => BinaryFormat::MachO, + File::MachO32(_) | File::MachO64(_) => BinaryFormat::MachO, #[cfg(feature = "pe")] - FileInternal::Pe32(_) | FileInternal::Pe64(_) => BinaryFormat::Pe, + File::Pe32(_) | File::Pe64(_) => BinaryFormat::Pe, #[cfg(feature = "wasm")] - FileInternal::Wasm(_) => BinaryFormat::Wasm, + File::Wasm(_) => BinaryFormat::Wasm, #[cfg(feature = "xcoff")] - FileInternal::Xcoff32(_) | FileInternal::Xcoff64(_) => BinaryFormat::Xcoff, + File::Xcoff32(_) | File::Xcoff64(_) => BinaryFormat::Xcoff, } } } @@ -325,56 +320,52 @@ where type DynamicRelocationIterator = DynamicRelocationIterator<'data, 'file, R>; fn architecture(&self) -> Architecture { - with_inner!(self.inner, FileInternal, |x| x.architecture()) + with_inner!(self, File, |x| x.architecture()) } fn is_little_endian(&self) -> bool { - with_inner!(self.inner, FileInternal, |x| x.is_little_endian()) + with_inner!(self, File, |x| x.is_little_endian()) } fn is_64(&self) -> bool { - with_inner!(self.inner, FileInternal, |x| x.is_64()) + with_inner!(self, File, |x| x.is_64()) } fn kind(&self) -> ObjectKind { - with_inner!(self.inner, FileInternal, |x| x.kind()) + with_inner!(self, File, |x| x.kind()) } fn segments(&'file self) -> SegmentIterator<'data, 'file, R> { SegmentIterator { - inner: map_inner!(self.inner, FileInternal, SegmentIteratorInternal, |x| x - .segments()), + inner: map_inner!(self, File, SegmentIteratorInternal, |x| x.segments()), } } fn section_by_name_bytes(&'file self, section_name: &[u8]) -> Option> { - map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x + map_inner_option!(self, File, SectionInternal, |x| x .section_by_name_bytes(section_name)) .map(|inner| Section { inner }) } fn section_by_index(&'file self, index: SectionIndex) -> Result> { - map_inner_option!(self.inner, FileInternal, SectionInternal, |x| x - .section_by_index(index)) - .map(|inner| Section { inner }) + map_inner_option!(self, File, SectionInternal, |x| x.section_by_index(index)) + .map(|inner| Section { inner }) } fn sections(&'file self) -> SectionIterator<'data, 'file, R> { SectionIterator { - inner: map_inner!(self.inner, FileInternal, SectionIteratorInternal, |x| x - .sections()), + inner: map_inner!(self, File, SectionIteratorInternal, |x| x.sections()), } } fn comdats(&'file self) -> ComdatIterator<'data, 'file, R> { ComdatIterator { - inner: map_inner!(self.inner, FileInternal, ComdatIteratorInternal, |x| x - .comdats()), + inner: map_inner!(self, File, ComdatIteratorInternal, |x| x.comdats()), } } fn symbol_by_index(&'file self, index: SymbolIndex) -> Result> { - map_inner_option!(self.inner, FileInternal, SymbolInternal, |x| x + map_inner_option!(self, File, SymbolInternal, |x| x .symbol_by_index(index) .map(|x| (x, PhantomData))) .map(|inner| Symbol { inner }) @@ -382,7 +373,7 @@ where fn symbols(&'file self) -> SymbolIterator<'data, 'file, R> { SymbolIterator { - inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| ( + inner: map_inner!(self, File, SymbolIteratorInternal, |x| ( x.symbols(), PhantomData )), @@ -390,7 +381,7 @@ where } fn symbol_table(&'file self) -> Option> { - map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x + map_inner_option!(self, File, SymbolTableInternal, |x| x .symbol_table() .map(|x| (x, PhantomData))) .map(|inner| SymbolTable { inner }) @@ -398,7 +389,7 @@ where fn dynamic_symbols(&'file self) -> SymbolIterator<'data, 'file, R> { SymbolIterator { - inner: map_inner!(self.inner, FileInternal, SymbolIteratorInternal, |x| ( + inner: map_inner!(self, File, SymbolIteratorInternal, |x| ( x.dynamic_symbols(), PhantomData )), @@ -406,7 +397,7 @@ where } fn dynamic_symbol_table(&'file self) -> Option> { - map_inner_option!(self.inner, FileInternal, SymbolTableInternal, |x| x + map_inner_option!(self, File, SymbolTableInternal, |x| x .dynamic_symbol_table() .map(|x| (x, PhantomData))) .map(|inner| SymbolTable { inner }) @@ -414,11 +405,11 @@ where #[cfg(feature = "elf")] fn dynamic_relocations(&'file self) -> Option> { - let inner = match self.inner { - FileInternal::Elf32(ref elf) => { + let inner = match self { + File::Elf32(ref elf) => { DynamicRelocationIteratorInternal::Elf32(elf.dynamic_relocations()?) } - FileInternal::Elf64(ref elf) => { + File::Elf64(ref elf) => { DynamicRelocationIteratorInternal::Elf64(elf.dynamic_relocations()?) } #[allow(unreachable_patterns)] @@ -433,60 +424,60 @@ where } fn symbol_map(&self) -> SymbolMap> { - with_inner!(self.inner, FileInternal, |x| x.symbol_map()) + with_inner!(self, File, |x| x.symbol_map()) } fn object_map(&self) -> ObjectMap<'data> { - with_inner!(self.inner, FileInternal, |x| x.object_map()) + with_inner!(self, File, |x| x.object_map()) } fn imports(&self) -> Result>> { - with_inner!(self.inner, FileInternal, |x| x.imports()) + with_inner!(self, File, |x| x.imports()) } fn exports(&self) -> Result>> { - with_inner!(self.inner, FileInternal, |x| x.exports()) + with_inner!(self, File, |x| x.exports()) } fn has_debug_symbols(&self) -> bool { - with_inner!(self.inner, FileInternal, |x| x.has_debug_symbols()) + with_inner!(self, File, |x| x.has_debug_symbols()) } #[inline] fn mach_uuid(&self) -> Result> { - with_inner!(self.inner, FileInternal, |x| x.mach_uuid()) + with_inner!(self, File, |x| x.mach_uuid()) } #[inline] fn build_id(&self) -> Result> { - with_inner!(self.inner, FileInternal, |x| x.build_id()) + with_inner!(self, File, |x| x.build_id()) } #[inline] fn gnu_debuglink(&self) -> Result> { - with_inner!(self.inner, FileInternal, |x| x.gnu_debuglink()) + with_inner!(self, File, |x| x.gnu_debuglink()) } #[inline] fn gnu_debugaltlink(&self) -> Result> { - with_inner!(self.inner, FileInternal, |x| x.gnu_debugaltlink()) + with_inner!(self, File, |x| x.gnu_debugaltlink()) } #[inline] fn pdb_info(&self) -> Result>> { - with_inner!(self.inner, FileInternal, |x| x.pdb_info()) + with_inner!(self, File, |x| x.pdb_info()) } fn relative_address_base(&self) -> u64 { - with_inner!(self.inner, FileInternal, |x| x.relative_address_base()) + with_inner!(self, File, |x| x.relative_address_base()) } fn entry(&self) -> u64 { - with_inner!(self.inner, FileInternal, |x| x.entry()) + with_inner!(self, File, |x| x.entry()) } fn flags(&self) -> FileFlags { - with_inner!(self.inner, FileInternal, |x| x.flags()) + with_inner!(self, File, |x| x.flags()) } } diff --git a/vendor/object/src/read/coff/import.rs b/vendor/object/src/read/coff/import.rs new file mode 100644 index 000000000..d635e7592 --- /dev/null +++ b/vendor/object/src/read/coff/import.rs @@ -0,0 +1,209 @@ +//! Support for reading short import files. +//! +//! These are used by some Windows linkers as a more compact way to describe +//! dynamically imported symbols. + +use crate::read::{Architecture, Error, ReadError, ReadRef, Result}; +use crate::{pe, ByteString, Bytes, LittleEndian as LE}; + +/// A Windows short form description of a symbol to import. +/// +/// Used in Windows import libraries to provide a mapping from +/// a symbol name to a DLL export. This is not an object file. +#[derive(Debug, Clone)] +pub struct ImportFile<'data> { + header: &'data pe::ImportObjectHeader, + kind: ImportType, + dll: ByteString<'data>, + symbol: ByteString<'data>, + import: Option>, +} + +impl<'data> ImportFile<'data> { + /// Parse it. + pub fn parse>(data: R) -> Result { + let mut offset = 0; + let header = pe::ImportObjectHeader::parse(data, &mut offset)?; + let data = header.parse_data(data, &mut offset)?; + + // Unmangles a name by removing a `?`, `@` or `_` prefix. + fn strip_prefix(s: &[u8]) -> &[u8] { + match s.split_first() { + Some((b, rest)) if [b'?', b'@', b'_'].contains(b) => rest, + _ => s, + } + } + Ok(Self { + header, + dll: data.dll, + symbol: data.symbol, + kind: match header.import_type() { + 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")), + }, + import: match header.name_type() { + pe::IMPORT_OBJECT_ORDINAL => None, + pe::IMPORT_OBJECT_NAME => Some(data.symbol()), + pe::IMPORT_OBJECT_NAME_NO_PREFIX => Some(strip_prefix(data.symbol())), + pe::IMPORT_OBJECT_NAME_UNDECORATE => Some( + strip_prefix(data.symbol()) + .split(|&b| b == b'@') + .next() + .unwrap(), + ), + pe::IMPORT_OBJECT_NAME_EXPORTAS => data.export(), + _ => return Err(Error("Unknown COFF import library name type")), + } + .map(ByteString), + }) + } + + /// Get the machine type. + pub fn architecture(&self) -> Architecture { + match self.header.machine.get(LE) { + pe::IMAGE_FILE_MACHINE_ARMNT => Architecture::Arm, + pe::IMAGE_FILE_MACHINE_ARM64 => Architecture::Aarch64, + pe::IMAGE_FILE_MACHINE_I386 => Architecture::I386, + pe::IMAGE_FILE_MACHINE_AMD64 => Architecture::X86_64, + _ => Architecture::Unknown, + } + } + + /// The public symbol name. + pub fn symbol(&self) -> &'data [u8] { + self.symbol.0 + } + + /// The name of the DLL to import the symbol from. + pub fn dll(&self) -> &'data [u8] { + self.dll.0 + } + + /// The name exported from the DLL. + pub fn import(&self) -> ImportName<'data> { + match self.import { + Some(name) => ImportName::Name(name.0), + None => ImportName::Ordinal(self.header.ordinal_or_hint.get(LE)), + } + } + + /// The type of import. Usually either a function or data. + pub fn import_type(&self) -> ImportType { + self.kind + } +} + +/// The name or ordinal to import from a DLL. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum ImportName<'data> { + /// Import by ordinal. Ordinarily this is a 1-based index. + Ordinal(u16), + /// Import by name. + Name(&'data [u8]), +} + +/// The kind of import symbol. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum ImportType { + /// An executable code symbol. + Code, + /// A data symbol. + Data, + /// A constant value. + Const, +} + +impl pe::ImportObjectHeader { + /// Read the short import header. + /// + /// Also checks that the signature and version are valid. + /// Directly following this header will be the string data. + pub fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> Result<&'data Self> { + let header = data + .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")) + } else if header.version.get(LE) != 0 { + Err(Error("Unknown COFF import library header version")) + } else { + Ok(header) + } + } + + /// Parse the data following the header. + pub fn parse_data<'data, R: ReadRef<'data>>( + &self, + data: R, + offset: &mut u64, + ) -> Result> { + let mut data = Bytes( + data.read_bytes(offset, u64::from(self.size_of_data.get(LE))) + .read_error("Invalid COFF import library data size")?, + ); + let symbol = data + .read_string() + .map(ByteString) + .read_error("Could not read COFF import library symbol name")?; + let dll = data + .read_string() + .map(ByteString) + .read_error("Could not read COFF import library DLL name")?; + let export = if self.name_type() == pe::IMPORT_OBJECT_NAME_EXPORTAS { + data.read_string() + .map(ByteString) + .map(Some) + .read_error("Could not read COFF import library export name")? + } else { + None + }; + Ok(ImportObjectData { + symbol, + dll, + export, + }) + } + + /// The type of import. + /// + /// This is one of the `IMPORT_OBJECT_*` constants. + pub fn import_type(&self) -> u16 { + self.name_type.get(LE) & pe::IMPORT_OBJECT_TYPE_MASK + } + + /// The type of import name. + /// + /// This is one of the `IMPORT_OBJECT_*` constants. + pub fn name_type(&self) -> u16 { + (self.name_type.get(LE) >> pe::IMPORT_OBJECT_NAME_SHIFT) & pe::IMPORT_OBJECT_NAME_MASK + } +} + +/// The data following `ImportObjectHeader`. +#[derive(Debug, Clone)] +pub struct ImportObjectData<'data> { + symbol: ByteString<'data>, + dll: ByteString<'data>, + export: Option>, +} + +impl<'data> ImportObjectData<'data> { + /// The public symbol name. + pub fn symbol(&self) -> &'data [u8] { + self.symbol.0 + } + + /// The name of the DLL to import the symbol from. + pub fn dll(&self) -> &'data [u8] { + self.dll.0 + } + + /// The name exported from the DLL. + /// + /// This is only set if the name is not derived from the symbol name. + pub fn export(&self) -> Option<&'data [u8]> { + self.export.map(|export| export.0) + } +} diff --git a/vendor/object/src/read/coff/mod.rs b/vendor/object/src/read/coff/mod.rs index d5b3caf32..26020d797 100644 --- a/vendor/object/src/read/coff/mod.rs +++ b/vendor/object/src/read/coff/mod.rs @@ -16,3 +16,6 @@ pub use relocation::*; mod comdat; pub use comdat::*; + +mod import; +pub use import::*; diff --git a/vendor/object/src/read/elf/file.rs b/vendor/object/src/read/elf/file.rs index aac66e7cc..67be37e21 100644 --- a/vendor/object/src/read/elf/file.rs +++ b/vendor/object/src/read/elf/file.rs @@ -161,6 +161,7 @@ where (elf::EM_ARM, _) => Architecture::Arm, (elf::EM_AVR, _) => Architecture::Avr, (elf::EM_BPF, _) => Architecture::Bpf, + (elf::EM_CSKY, _) => Architecture::Csky, (elf::EM_386, _) => Architecture::I386, (elf::EM_X86_64, false) => Architecture::X86_64_X32, (elf::EM_X86_64, true) => Architecture::X86_64, diff --git a/vendor/object/src/read/elf/note.rs b/vendor/object/src/read/elf/note.rs index fc5aa7753..84d4179de 100644 --- a/vendor/object/src/read/elf/note.rs +++ b/vendor/object/src/read/elf/note.rs @@ -113,21 +113,24 @@ impl<'data, Elf: FileHeader> Note<'data, Elf> { self.header.n_descsz(endian) } - /// Return the bytes for the name field following the `NoteHeader`, - /// excluding any null terminator. + /// Return the bytes for the name field following the `NoteHeader`. /// - /// This field is usually a string including a null terminator + /// This field is usually a string including one or more trailing null bytes /// (but it is not required to be). /// - /// The length of this field (including any null terminator) is given by - /// `n_namesz`. + /// The length of this field is given by `n_namesz`. + pub fn name_bytes(&self) -> &'data [u8] { + self.name + } + + /// Return the bytes for the name field following the `NoteHeader`, + /// excluding all trailing null bytes. pub fn name(&self) -> &'data [u8] { - if let Some((last, name)) = self.name.split_last() { - if *last == 0 { - return name; - } + let mut name = self.name; + while let [rest @ .., 0] = name { + name = rest; } - self.name + name } /// Return the bytes for the desc field following the `NoteHeader`. diff --git a/vendor/object/src/read/elf/relocation.rs b/vendor/object/src/read/elf/relocation.rs index 8443dbc75..78032dfdb 100644 --- a/vendor/object/src/read/elf/relocation.rs +++ b/vendor/object/src/read/elf/relocation.rs @@ -276,6 +276,11 @@ fn parse_relocation( elf::R_BPF_64_32 => (RelocationKind::Absolute, 32), r_type => (RelocationKind::Elf(r_type), 0), }, + elf::EM_CSKY => match reloc.r_type(endian, false) { + elf::R_CKCORE_ADDR32 => (RelocationKind::Absolute, 32), + elf::R_CKCORE_PCREL32 => (RelocationKind::Relative, 32), + r_type => (RelocationKind::Elf(r_type), 0), + }, elf::EM_386 => match reloc.r_type(endian, false) { elf::R_386_32 => (RelocationKind::Absolute, 32), elf::R_386_PC32 => (RelocationKind::Relative, 32), diff --git a/vendor/object/src/read/elf/symbol.rs b/vendor/object/src/read/elf/symbol.rs index ac1095705..ee5aa37f1 100644 --- a/vendor/object/src/read/elf/symbol.rs +++ b/vendor/object/src/read/elf/symbol.rs @@ -309,6 +309,14 @@ where pub(super) symbol: &'data Elf::Sym, } +impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ElfSymbol<'data, 'file, Elf, R> { + /// Return a reference to the raw symbol structure. + #[inline] + pub fn raw_symbol(&self) -> &'data Elf::Sym { + self.symbol + } +} + impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> read::private::Sealed for ElfSymbol<'data, 'file, Elf, R> { diff --git a/vendor/object/src/read/mod.rs b/vendor/object/src/read/mod.rs index 0a450359f..8230d43ba 100644 --- a/vendor/object/src/read/mod.rs +++ b/vendor/object/src/read/mod.rs @@ -156,6 +156,9 @@ pub enum FileKind { /// This supports a larger number of sections. #[cfg(feature = "coff")] CoffBig, + /// A Windows short import file. + #[cfg(feature = "coff")] + CoffImport, /// A dyld cache file containing Mach-O images. #[cfg(feature = "macho")] DyldCache, @@ -232,6 +235,7 @@ impl FileKind { [0x00, b'a', b's', b'm', ..] => FileKind::Wasm, #[cfg(feature = "pe")] [b'M', b'Z', ..] if offset == 0 => { + // offset == 0 restriction is because optional_header_magic only looks at offset 0 match pe::optional_header_magic(data) { Ok(crate::pe::IMAGE_NT_OPTIONAL_HDR32_MAGIC) => { FileKind::Pe32 @@ -253,16 +257,19 @@ impl FileKind { // COFF x86-64 | [0x64, 0x86, ..] => FileKind::Coff, #[cfg(feature = "coff")] + [0x00, 0x00, 0xff, 0xff, 0x00, 0x00, ..] => FileKind::CoffImport, + #[cfg(feature = "coff")] [0x00, 0x00, 0xff, 0xff, 0x02, 0x00, ..] if offset == 0 => { + // 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")), } } #[cfg(feature = "xcoff")] - [0x01, 0xDF, ..] => FileKind::Xcoff32, + [0x01, 0xdf, ..] => FileKind::Xcoff32, #[cfg(feature = "xcoff")] - [0x01, 0xF7, ..] => FileKind::Xcoff64, + [0x01, 0xf7, ..] => FileKind::Xcoff64, _ => return Err(Error("Unknown file magic")), }; Ok(kind) diff --git a/vendor/object/src/write/elf/object.rs b/vendor/object/src/write/elf/object.rs index 8b9eadaf8..acc820c9e 100644 --- a/vendor/object/src/write/elf/object.rs +++ b/vendor/object/src/write/elf/object.rs @@ -126,6 +126,7 @@ impl<'a> Object<'a> { Architecture::Arm => false, Architecture::Avr => true, Architecture::Bpf => false, + Architecture::Csky => true, Architecture::I386 => false, Architecture::X86_64 => true, Architecture::X86_64_X32 => true, @@ -329,6 +330,7 @@ impl<'a> Object<'a> { Architecture::Arm => elf::EM_ARM, Architecture::Avr => elf::EM_AVR, Architecture::Bpf => elf::EM_BPF, + Architecture::Csky => elf::EM_CSKY, Architecture::I386 => elf::EM_386, Architecture::X86_64 => elf::EM_X86_64, Architecture::X86_64_X32 => elf::EM_X86_64, @@ -548,6 +550,16 @@ impl<'a> Object<'a> { return Err(Error(format!("unimplemented relocation {:?}", reloc))); } }, + Architecture::Csky => match (reloc.kind, reloc.encoding, reloc.size) { + (RelocationKind::Absolute, _, 32) => elf::R_CKCORE_ADDR32, + (RelocationKind::Relative, RelocationEncoding::Generic, 32) => { + elf::R_CKCORE_PCREL32 + } + (RelocationKind::Elf(x), _, _) => x, + _ => { + return Err(Error(format!("unimplemented relocation {:?}", reloc))); + } + }, Architecture::I386 => match (reloc.kind, reloc.size) { (RelocationKind::Absolute, 32) => elf::R_386_32, (RelocationKind::Relative, 32) => elf::R_386_PC32, diff --git a/vendor/object/src/write/macho.rs b/vendor/object/src/write/macho.rs index 0e082b69d..e3ce55bb4 100644 --- a/vendor/object/src/write/macho.rs +++ b/vendor/object/src/write/macho.rs @@ -303,39 +303,29 @@ impl<'a> Object<'a> { let sizeofcmds = offset - command_offset; // Calculate size of section data. - let mut segment_file_offset = None; + // Section data can immediately follow the load commands without any alignment padding. + let segment_file_offset = offset; let mut section_offsets = vec![SectionOffsets::default(); self.sections.len()]; let mut address = 0; for (index, section) in self.sections.iter().enumerate() { section_offsets[index].index = 1 + index; if !section.is_bss() { - let len = section.data.len(); - if len != 0 { - offset = align(offset, section.align as usize); - section_offsets[index].offset = offset; - if segment_file_offset.is_none() { - segment_file_offset = Some(offset); - } - offset += len; - } else { - section_offsets[index].offset = offset; - } address = align_u64(address, section.align); section_offsets[index].address = address; + section_offsets[index].offset = segment_file_offset + address as usize; address += section.size; } } + let segment_file_size = address as usize; + offset += address as usize; for (index, section) in self.sections.iter().enumerate() { - if section.kind.is_bss() { - assert!(section.data.is_empty()); + if section.is_bss() { + debug_assert!(section.data.is_empty()); address = align_u64(address, section.align); section_offsets[index].address = address; address += section.size; } } - let segment_file_offset = segment_file_offset.unwrap_or(offset); - let segment_file_size = offset - segment_file_offset; - debug_assert!(segment_file_size as u64 <= address); // Count symbols and add symbol strings to strtab. let mut strtab = StringTable::default(); @@ -537,10 +527,8 @@ impl<'a> Object<'a> { // Write section data. for (index, section) in self.sections.iter().enumerate() { - let len = section.data.len(); - if len != 0 { - write_align(buffer, section.align as usize); - debug_assert_eq!(section_offsets[index].offset, buffer.len()); + if !section.is_bss() { + buffer.resize(section_offsets[index].offset); buffer.write_bytes(§ion.data); } } -- cgit v1.2.3