summaryrefslogtreecommitdiffstats
path: root/vendor/object/src/read
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:19:13 +0000
commit218caa410aa38c29984be31a5229b9fa717560ee (patch)
treec54bd55eeb6e4c508940a30e94c0032fbd45d677 /vendor/object/src/read
parentReleasing progress-linux version 1.67.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-218caa410aa38c29984be31a5229b9fa717560ee.tar.xz
rustc-218caa410aa38c29984be31a5229b9fa717560ee.zip
Merging upstream version 1.68.2+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/object/src/read')
-rw-r--r--vendor/object/src/read/any.rs90
-rw-r--r--vendor/object/src/read/archive.rs315
-rw-r--r--vendor/object/src/read/coff/symbol.rs8
-rw-r--r--vendor/object/src/read/elf/comdat.rs2
-rw-r--r--vendor/object/src/read/elf/file.rs5
-rw-r--r--vendor/object/src/read/elf/relocation.rs56
-rw-r--r--vendor/object/src/read/elf/segment.rs2
-rw-r--r--vendor/object/src/read/elf/symbol.rs15
-rw-r--r--vendor/object/src/read/macho/fat.rs2
-rw-r--r--vendor/object/src/read/macho/file.rs2
-rw-r--r--vendor/object/src/read/macho/load_command.rs5
-rw-r--r--vendor/object/src/read/mod.rs25
-rw-r--r--vendor/object/src/read/pe/data_directory.rs28
-rw-r--r--vendor/object/src/read/pe/file.rs83
-rw-r--r--vendor/object/src/read/pe/import.rs114
-rw-r--r--vendor/object/src/read/pe/resource.rs30
-rw-r--r--vendor/object/src/read/xcoff/comdat.rs130
-rw-r--r--vendor/object/src/read/xcoff/file.rs629
-rw-r--r--vendor/object/src/read/xcoff/mod.rs21
-rw-r--r--vendor/object/src/read/xcoff/relocation.rs128
-rw-r--r--vendor/object/src/read/xcoff/section.rs426
-rw-r--r--vendor/object/src/read/xcoff/segment.rs115
-rw-r--r--vendor/object/src/read/xcoff/symbol.rs634
23 files changed, 2753 insertions, 112 deletions
diff --git a/vendor/object/src/read/any.rs b/vendor/object/src/read/any.rs
index 02e76dcdd..c390b21b6 100644
--- a/vendor/object/src/read/any.rs
+++ b/vendor/object/src/read/any.rs
@@ -12,6 +12,8 @@ use crate::read::macho;
use crate::read::pe;
#[cfg(feature = "wasm")]
use crate::read::wasm;
+#[cfg(feature = "xcoff")]
+use crate::read::xcoff;
use crate::read::{
self, Architecture, BinaryFormat, CodeView, ComdatKind, CompressedData, CompressedFileRange,
Error, Export, FileFlags, FileKind, Import, Object, ObjectComdat, ObjectKind, ObjectMap,
@@ -44,6 +46,10 @@ macro_rules! with_inner {
$enum::Pe64(ref $var) => $body,
#[cfg(feature = "wasm")]
$enum::Wasm(ref $var) => $body,
+ #[cfg(feature = "xcoff")]
+ $enum::Xcoff32(ref $var) => $body,
+ #[cfg(feature = "xcoff")]
+ $enum::Xcoff64(ref $var) => $body,
}
};
}
@@ -67,6 +73,10 @@ macro_rules! with_inner_mut {
$enum::Pe64(ref mut $var) => $body,
#[cfg(feature = "wasm")]
$enum::Wasm(ref mut $var) => $body,
+ #[cfg(feature = "xcoff")]
+ $enum::Xcoff32(ref mut $var) => $body,
+ #[cfg(feature = "xcoff")]
+ $enum::Xcoff64(ref mut $var) => $body,
}
};
}
@@ -91,6 +101,10 @@ macro_rules! map_inner {
$from::Pe64(ref $var) => $to::Pe64($body),
#[cfg(feature = "wasm")]
$from::Wasm(ref $var) => $to::Wasm($body),
+ #[cfg(feature = "xcoff")]
+ $from::Xcoff32(ref $var) => $to::Xcoff32($body),
+ #[cfg(feature = "xcoff")]
+ $from::Xcoff64(ref $var) => $to::Xcoff64($body),
}
};
}
@@ -115,6 +129,10 @@ macro_rules! map_inner_option {
$from::Pe64(ref $var) => $body.map($to::Pe64),
#[cfg(feature = "wasm")]
$from::Wasm(ref $var) => $body.map($to::Wasm),
+ #[cfg(feature = "xcoff")]
+ $from::Xcoff32(ref $var) => $body.map($to::Xcoff32),
+ #[cfg(feature = "xcoff")]
+ $from::Xcoff64(ref $var) => $body.map($to::Xcoff64),
}
};
}
@@ -138,6 +156,10 @@ macro_rules! map_inner_option_mut {
$from::Pe64(ref mut $var) => $body.map($to::Pe64),
#[cfg(feature = "wasm")]
$from::Wasm(ref mut $var) => $body.map($to::Wasm),
+ #[cfg(feature = "xcoff")]
+ $from::Xcoff32(ref mut $var) => $body.map($to::Xcoff32),
+ #[cfg(feature = "xcoff")]
+ $from::Xcoff64(ref mut $var) => $body.map($to::Xcoff64),
}
};
}
@@ -162,6 +184,10 @@ macro_rules! next_inner {
$from::Pe64(ref mut iter) => iter.next().map($to::Pe64),
#[cfg(feature = "wasm")]
$from::Wasm(ref mut iter) => iter.next().map($to::Wasm),
+ #[cfg(feature = "xcoff")]
+ $from::Xcoff32(ref mut iter) => iter.next().map($to::Xcoff32),
+ #[cfg(feature = "xcoff")]
+ $from::Xcoff64(ref mut iter) => iter.next().map($to::Xcoff64),
}
};
}
@@ -192,6 +218,10 @@ enum FileInternal<'data, R: ReadRef<'data>> {
Pe64(pe::PeFile64<'data, R>),
#[cfg(feature = "wasm")]
Wasm(wasm::WasmFile<'data, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(xcoff::XcoffFile32<'data, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(xcoff::XcoffFile64<'data, R>),
}
impl<'data, R: ReadRef<'data>> File<'data, R> {
@@ -214,6 +244,10 @@ impl<'data, R: ReadRef<'data>> File<'data, R> {
FileKind::Pe64 => FileInternal::Pe64(pe::PeFile64::parse(data)?),
#[cfg(feature = "coff")]
FileKind::Coff => FileInternal::Coff(coff::CoffFile::parse(data)?),
+ #[cfg(feature = "xcoff")]
+ FileKind::Xcoff32 => FileInternal::Xcoff32(xcoff::XcoffFile32::parse(data)?),
+ #[cfg(feature = "xcoff")]
+ FileKind::Xcoff64 => FileInternal::Xcoff64(xcoff::XcoffFile64::parse(data)?),
#[allow(unreachable_patterns)]
_ => return Err(Error("Unsupported file format")),
};
@@ -250,6 +284,8 @@ impl<'data, R: ReadRef<'data>> File<'data, R> {
FileInternal::Pe32(_) | FileInternal::Pe64(_) => BinaryFormat::Pe,
#[cfg(feature = "wasm")]
FileInternal::Wasm(_) => BinaryFormat::Wasm,
+ #[cfg(feature = "xcoff")]
+ FileInternal::Xcoff32(_) | FileInternal::Xcoff64(_) => BinaryFormat::Xcoff,
}
}
}
@@ -468,6 +504,10 @@ where
Pe64(pe::PeSegmentIterator64<'data, 'file, R>),
#[cfg(feature = "wasm")]
Wasm(wasm::WasmSegmentIterator<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(xcoff::XcoffSegmentIterator32<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(xcoff::XcoffSegmentIterator64<'data, 'file, R>),
}
impl<'data, 'file, R: ReadRef<'data>> Iterator for SegmentIterator<'data, 'file, R> {
@@ -508,6 +548,10 @@ where
Pe64(pe::PeSegment64<'data, 'file, R>),
#[cfg(feature = "wasm")]
Wasm(wasm::WasmSegment<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(xcoff::XcoffSegment32<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(xcoff::XcoffSegment64<'data, 'file, R>),
}
impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Segment<'data, 'file, R> {
@@ -600,6 +644,10 @@ where
Pe64(pe::PeSectionIterator64<'data, 'file, R>),
#[cfg(feature = "wasm")]
Wasm(wasm::WasmSectionIterator<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(xcoff::XcoffSectionIterator32<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(xcoff::XcoffSectionIterator64<'data, 'file, R>),
}
impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionIterator<'data, 'file, R> {
@@ -639,6 +687,10 @@ where
Pe64(pe::PeSection64<'data, 'file, R>),
#[cfg(feature = "wasm")]
Wasm(wasm::WasmSection<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(xcoff::XcoffSection32<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(xcoff::XcoffSection64<'data, 'file, R>),
}
impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Section<'data, 'file, R> {
@@ -771,6 +823,10 @@ where
Pe64(pe::PeComdatIterator64<'data, 'file, R>),
#[cfg(feature = "wasm")]
Wasm(wasm::WasmComdatIterator<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(xcoff::XcoffComdatIterator32<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(xcoff::XcoffComdatIterator64<'data, 'file, R>),
}
impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatIterator<'data, 'file, R> {
@@ -810,6 +866,10 @@ where
Pe64(pe::PeComdat64<'data, 'file, R>),
#[cfg(feature = "wasm")]
Wasm(wasm::WasmComdat<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(xcoff::XcoffComdat32<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(xcoff::XcoffComdat64<'data, 'file, R>),
}
impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Comdat<'data, 'file, R> {
@@ -885,6 +945,10 @@ where
Pe64(pe::PeComdatSectionIterator64<'data, 'file, R>),
#[cfg(feature = "wasm")]
Wasm(wasm::WasmComdatSectionIterator<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(xcoff::XcoffComdatSectionIterator32<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(xcoff::XcoffComdatSectionIterator64<'data, 'file, R>),
}
impl<'data, 'file, R: ReadRef<'data>> Iterator for ComdatSectionIterator<'data, 'file, R> {
@@ -947,6 +1011,10 @@ where
Pe64((coff::CoffSymbolTable<'data, 'file, R>, PhantomData<R>)),
#[cfg(feature = "wasm")]
Wasm((wasm::WasmSymbolTable<'data, 'file>, PhantomData<R>)),
+ #[cfg(feature = "xcoff")]
+ Xcoff32((xcoff::XcoffSymbolTable32<'data, 'file, R>, PhantomData<R>)),
+ #[cfg(feature = "xcoff")]
+ Xcoff64((xcoff::XcoffSymbolTable64<'data, 'file, R>, PhantomData<R>)),
}
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for SymbolTable<'data, 'file, R> {}
@@ -1027,6 +1095,20 @@ where
Pe64((coff::CoffSymbolIterator<'data, 'file, R>, PhantomData<R>)),
#[cfg(feature = "wasm")]
Wasm((wasm::WasmSymbolIterator<'data, 'file>, PhantomData<R>)),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(
+ (
+ xcoff::XcoffSymbolIterator32<'data, 'file, R>,
+ PhantomData<R>,
+ ),
+ ),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(
+ (
+ xcoff::XcoffSymbolIterator64<'data, 'file, R>,
+ PhantomData<R>,
+ ),
+ ),
}
impl<'data, 'file, R: ReadRef<'data>> Iterator for SymbolIterator<'data, 'file, R> {
@@ -1090,6 +1172,10 @@ where
Pe64((coff::CoffSymbol<'data, 'file, R>, PhantomData<R>)),
#[cfg(feature = "wasm")]
Wasm((wasm::WasmSymbol<'data, 'file>, PhantomData<R>)),
+ #[cfg(feature = "xcoff")]
+ Xcoff32((xcoff::XcoffSymbol32<'data, 'file, R>, PhantomData<R>)),
+ #[cfg(feature = "xcoff")]
+ Xcoff64((xcoff::XcoffSymbol64<'data, 'file, R>, PhantomData<R>)),
}
impl<'data, 'file, R: ReadRef<'data>> fmt::Debug for Symbol<'data, 'file, R> {
@@ -1240,6 +1326,10 @@ where
Pe64(pe::PeRelocationIterator<'data, 'file, R>),
#[cfg(feature = "wasm")]
Wasm(wasm::WasmRelocationIterator<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff32(xcoff::XcoffRelocationIterator32<'data, 'file, R>),
+ #[cfg(feature = "xcoff")]
+ Xcoff64(xcoff::XcoffRelocationIterator64<'data, 'file, R>),
}
impl<'data, 'file, R: ReadRef<'data>> Iterator for SectionRelocationIterator<'data, 'file, R> {
diff --git a/vendor/object/src/read/archive.rs b/vendor/object/src/read/archive.rs
index 0208878e4..f5aaa9b19 100644
--- a/vendor/object/src/read/archive.rs
+++ b/vendor/object/src/read/archive.rs
@@ -3,7 +3,7 @@
use core::convert::TryInto;
use crate::archive;
-use crate::read::{self, Error, ReadError, ReadRef};
+use crate::read::{self, Bytes, Error, ReadError, ReadRef};
/// The kind of archive format.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -23,15 +23,28 @@ pub enum ArchiveKind {
Bsd64,
/// The Windows COFF archive format.
Coff,
+ /// The AIX big archive format.
+ AixBig,
+}
+
+/// The list of members in the archive.
+#[derive(Debug, Clone, Copy)]
+enum Members<'data> {
+ Common {
+ offset: u64,
+ end_offset: u64,
+ },
+ AixBig {
+ index: &'data [archive::AixMemberOffset],
+ },
}
/// A partially parsed archive file.
-#[derive(Debug)]
+#[derive(Debug, Clone, Copy)]
pub struct ArchiveFile<'data, R: ReadRef<'data> = &'data [u8]> {
data: R,
- len: u64,
- offset: u64,
kind: ArchiveKind,
+ members: Members<'data>,
symbols: (u64, u64),
names: &'data [u8],
}
@@ -44,15 +57,23 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
let magic = data
.read_bytes(&mut tail, archive::MAGIC.len() as u64)
.read_error("Invalid archive size")?;
- if magic != &archive::MAGIC[..] {
+
+ if magic == archive::AIX_BIG_MAGIC {
+ return Self::parse_aixbig(data);
+ } else if magic != archive::MAGIC {
return Err(Error("Unsupported archive identifier"));
}
+ let mut members_offset = tail;
+ let members_end_offset = len;
+
let mut file = ArchiveFile {
data,
- offset: tail,
- len,
kind: ArchiveKind::Unknown,
+ members: Members::Common {
+ offset: 0,
+ end_offset: 0,
+ },
symbols: (0, 0),
names: &[],
};
@@ -77,7 +98,7 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
// GNU symbol table (unless we later determine this is COFF).
file.kind = ArchiveKind::Gnu;
file.symbols = member.file_range();
- file.offset = tail;
+ members_offset = tail;
if tail < len {
let member = ArchiveMember::parse(data, &mut tail, &[])?;
@@ -85,55 +106,125 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
// COFF linker member.
file.kind = ArchiveKind::Coff;
file.symbols = member.file_range();
- file.offset = tail;
+ members_offset = tail;
if tail < len {
let member = ArchiveMember::parse(data, &mut tail, &[])?;
if member.name == b"//" {
// COFF names table.
file.names = member.data(data)?;
- file.offset = tail;
+ members_offset = tail;
}
}
} else if member.name == b"//" {
// GNU names table.
file.names = member.data(data)?;
- file.offset = tail;
+ members_offset = tail;
}
}
} else if member.name == b"/SYM64/" {
// GNU 64-bit symbol table.
file.kind = ArchiveKind::Gnu64;
file.symbols = member.file_range();
- file.offset = tail;
+ members_offset = tail;
if tail < len {
let member = ArchiveMember::parse(data, &mut tail, &[])?;
if member.name == b"//" {
// GNU names table.
file.names = member.data(data)?;
- file.offset = tail;
+ members_offset = tail;
}
}
} else if member.name == b"//" {
// GNU names table.
file.kind = ArchiveKind::Gnu;
file.names = member.data(data)?;
- file.offset = tail;
+ members_offset = tail;
} else if member.name == b"__.SYMDEF" || member.name == b"__.SYMDEF SORTED" {
// BSD symbol table.
file.kind = ArchiveKind::Bsd;
file.symbols = member.file_range();
- file.offset = tail;
+ members_offset = tail;
} else if member.name == b"__.SYMDEF_64" || member.name == b"__.SYMDEF_64 SORTED" {
// BSD 64-bit symbol table.
file.kind = ArchiveKind::Bsd64;
file.symbols = member.file_range();
- file.offset = tail;
+ members_offset = tail;
} else {
// TODO: This could still be a BSD file. We leave this as unknown for now.
}
}
+ file.members = Members::Common {
+ offset: members_offset,
+ end_offset: members_end_offset,
+ };
+ Ok(file)
+ }
+
+ fn parse_aixbig(data: R) -> read::Result<Self> {
+ let mut tail = 0;
+
+ let file_header = data
+ .read::<archive::AixFileHeader>(&mut tail)
+ .read_error("Invalid AIX big archive file header")?;
+ // Caller already validated this.
+ debug_assert_eq!(file_header.magic, archive::AIX_BIG_MAGIC);
+
+ let mut file = ArchiveFile {
+ data,
+ kind: ArchiveKind::AixBig,
+ members: Members::AixBig { index: &[] },
+ symbols: (0, 0),
+ names: &[],
+ };
+
+ // Read the span of symbol table.
+ let symtbl64 = parse_u64_digits(&file_header.gst64off, 10)
+ .read_error("Invalid offset to 64-bit symbol table in AIX big archive")?;
+ if symtbl64 > 0 {
+ // The symbol table is also a file with header.
+ let member = ArchiveMember::parse_aixbig(data, symtbl64)?;
+ file.symbols = member.file_range();
+ } else {
+ let symtbl = parse_u64_digits(&file_header.gstoff, 10)
+ .read_error("Invalid offset to symbol table in AIX big archive")?;
+ if symtbl > 0 {
+ // The symbol table is also a file with header.
+ let member = ArchiveMember::parse_aixbig(data, symtbl)?;
+ file.symbols = member.file_range();
+ }
+ }
+
+ // Big archive member index table lists file entries with offsets and names.
+ // To avoid potential infinite loop (members are double-linked list), the
+ // iterator goes through the index instead of real members.
+ let member_table_offset = parse_u64_digits(&file_header.memoff, 10)
+ .read_error("Invalid offset for member table of AIX big archive")?;
+ if member_table_offset == 0 {
+ // The offset would be zero if archive contains no file.
+ return Ok(file);
+ }
+
+ // The member index table is also a file with header.
+ let member = ArchiveMember::parse_aixbig(data, member_table_offset)?;
+ let mut member_data = Bytes(member.data(data)?);
+
+ // Structure of member index table:
+ // Number of entries (20 bytes)
+ // Offsets of each entry (20*N bytes)
+ // Names string table (the rest of bytes to fill size defined in header)
+ let members_count_bytes = member_data
+ .read_slice::<u8>(20)
+ .read_error("Missing member count in AIX big archive")?;
+ let members_count = parse_u64_digits(members_count_bytes, 10)
+ .and_then(|size| size.try_into().ok())
+ .read_error("Invalid member count in AIX big archive")?;
+ let index = member_data
+ .read_slice::<archive::AixMemberOffset>(members_count)
+ .read_error("Member count overflow in AIX big archive")?;
+ file.members = Members::AixBig { index };
+
Ok(file)
}
@@ -150,8 +241,7 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
pub fn members(&self) -> ArchiveMemberIterator<'data, R> {
ArchiveMemberIterator {
data: self.data,
- offset: self.offset,
- len: self.len,
+ members: self.members,
names: self.names,
}
}
@@ -161,8 +251,7 @@ impl<'data, R: ReadRef<'data>> ArchiveFile<'data, R> {
#[derive(Debug)]
pub struct ArchiveMemberIterator<'data, R: ReadRef<'data> = &'data [u8]> {
data: R,
- offset: u64,
- len: u64,
+ members: Members<'data>,
names: &'data [u8],
}
@@ -170,28 +259,55 @@ impl<'data, R: ReadRef<'data>> Iterator for ArchiveMemberIterator<'data, R> {
type Item = read::Result<ArchiveMember<'data>>;
fn next(&mut self) -> Option<Self::Item> {
- if self.offset >= self.len {
- return None;
- }
- let member = ArchiveMember::parse(self.data, &mut self.offset, self.names);
- if member.is_err() {
- self.offset = self.len;
+ match &mut self.members {
+ Members::Common {
+ ref mut offset,
+ ref mut end_offset,
+ } => {
+ if *offset >= *end_offset {
+ return None;
+ }
+ let member = ArchiveMember::parse(self.data, offset, self.names);
+ if member.is_err() {
+ *offset = *end_offset;
+ }
+ Some(member)
+ }
+ Members::AixBig { ref mut index } => match **index {
+ [] => None,
+ [ref first, ref rest @ ..] => {
+ *index = rest;
+ let member = ArchiveMember::parse_aixbig_index(self.data, first);
+ if member.is_err() {
+ *index = &[];
+ }
+ Some(member)
+ }
+ },
}
- Some(member)
}
}
+/// An archive member header.
+#[derive(Debug, Clone, Copy)]
+enum MemberHeader<'data> {
+ /// Common header used by many formats.
+ Common(&'data archive::Header),
+ /// AIX big archive header
+ AixBig(&'data archive::AixHeader),
+}
+
/// A partially parsed archive member.
#[derive(Debug)]
pub struct ArchiveMember<'data> {
- header: &'data archive::Header,
+ header: MemberHeader<'data>,
name: &'data [u8],
offset: u64,
size: u64,
}
impl<'data> ArchiveMember<'data> {
- /// Parse the archive member header, name, and file data.
+ /// Parse the member header, name, and file data in an archive with the common format.
///
/// This reads the extended name (if any) and adjusts the file size.
fn parse<R: ReadRef<'data>>(
@@ -217,11 +333,11 @@ impl<'data> ArchiveMember<'data> {
*offset = offset.saturating_add(1);
}
- let name = if header.name[0] == b'/' && (header.name[1] as char).is_digit(10) {
+ let name = if header.name[0] == b'/' && (header.name[1] as char).is_ascii_digit() {
// Read file name from the names table.
parse_sysv_extended_name(&header.name[1..], names)
.read_error("Invalid archive extended name offset")?
- } else if &header.name[..3] == b"#1/" && (header.name[3] as char).is_digit(10) {
+ } else if &header.name[..3] == b"#1/" && (header.name[3] as char).is_ascii_digit() {
// Read file name from the start of the file data.
parse_bsd_extended_name(&header.name[3..], data, &mut file_offset, &mut file_size)
.read_error("Invalid archive extended name length")?
@@ -236,17 +352,81 @@ impl<'data> ArchiveMember<'data> {
};
Ok(ArchiveMember {
- header,
+ header: MemberHeader::Common(header),
name,
offset: file_offset,
size: file_size,
})
}
- /// Return the raw header.
+ /// Parse a member index entry in an AIX big archive,
+ /// and then parse the member header, name, and file data.
+ fn parse_aixbig_index<R: ReadRef<'data>>(
+ data: R,
+ index: &archive::AixMemberOffset,
+ ) -> read::Result<Self> {
+ let offset = parse_u64_digits(&index.0, 10)
+ .read_error("Invalid AIX big archive file member offset")?;
+ Self::parse_aixbig(data, offset)
+ }
+
+ /// Parse the member header, name, and file data in an AIX big archive.
+ fn parse_aixbig<R: ReadRef<'data>>(data: R, mut offset: u64) -> read::Result<Self> {
+ // The format was described at
+ // https://www.ibm.com/docs/en/aix/7.3?topic=formats-ar-file-format-big
+ let header = data
+ .read::<archive::AixHeader>(&mut offset)
+ .read_error("Invalid AIX big archive member header")?;
+ let name_length = parse_u64_digits(&header.namlen, 10)
+ .read_error("Invalid AIX big archive member name length")?;
+ let name = data
+ .read_bytes(&mut offset, name_length)
+ .read_error("Invalid AIX big archive member name")?;
+
+ // The actual data for a file member begins at the first even-byte boundary beyond the
+ // member header and continues for the number of bytes specified by the ar_size field. The
+ // ar command inserts null bytes for padding where necessary.
+ if offset & 1 != 0 {
+ offset = offset.saturating_add(1);
+ }
+ // Because of the even-byte boundary, we have to read and check terminator after header.
+ let terminator = 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"));
+ }
+
+ let size = parse_u64_digits(&header.size, 10)
+ .read_error("Invalid archive member size in AIX big archive")?;
+ Ok(ArchiveMember {
+ header: MemberHeader::AixBig(header),
+ name,
+ offset,
+ size,
+ })
+ }
+
+ /// Return the raw header that is common to many archive formats.
+ ///
+ /// Returns `None` if this archive does not use the common header format.
#[inline]
- pub fn header(&self) -> &'data archive::Header {
- self.header
+ pub fn header(&self) -> Option<&'data archive::Header> {
+ match self.header {
+ MemberHeader::Common(header) => Some(header),
+ _ => None,
+ }
+ }
+
+ /// Return the raw header for AIX big archives.
+ ///
+ /// Returns `None` if this is not an AIX big archive.
+ #[inline]
+ pub fn aix_header(&self) -> Option<&'data archive::AixHeader> {
+ match self.header {
+ MemberHeader::AixBig(header) => Some(header),
+ _ => None,
+ }
}
/// Return the parsed file name.
@@ -260,25 +440,37 @@ impl<'data> ArchiveMember<'data> {
/// Parse the file modification timestamp from the header.
#[inline]
pub fn date(&self) -> Option<u64> {
- parse_u64_digits(&self.header.date, 10)
+ match &self.header {
+ MemberHeader::Common(header) => parse_u64_digits(&header.date, 10),
+ MemberHeader::AixBig(header) => parse_u64_digits(&header.date, 10),
+ }
}
/// Parse the user ID from the header.
#[inline]
pub fn uid(&self) -> Option<u64> {
- parse_u64_digits(&self.header.uid, 10)
+ match &self.header {
+ MemberHeader::Common(header) => parse_u64_digits(&header.uid, 10),
+ MemberHeader::AixBig(header) => parse_u64_digits(&header.uid, 10),
+ }
}
/// Parse the group ID from the header.
#[inline]
pub fn gid(&self) -> Option<u64> {
- parse_u64_digits(&self.header.gid, 10)
+ match &self.header {
+ MemberHeader::Common(header) => parse_u64_digits(&header.gid, 10),
+ MemberHeader::AixBig(header) => parse_u64_digits(&header.gid, 10),
+ }
}
/// Parse the file mode from the header.
#[inline]
pub fn mode(&self) -> Option<u64> {
- parse_u64_digits(&self.header.mode, 8)
+ match &self.header {
+ MemberHeader::Common(header) => parse_u64_digits(&header.mode, 8),
+ MemberHeader::AixBig(header) => parse_u64_digits(&header.mode, 8),
+ }
}
/// Return the offset and size of the file data.
@@ -442,6 +634,19 @@ mod tests {
0000";
let archive = ArchiveFile::parse(&data[..]).unwrap();
assert_eq!(archive.kind(), ArchiveKind::Coff);
+
+ let data = b"\
+ <bigaf>\n\
+ 0 0 \
+ 0 0 \
+ 0 128 \
+ 6 0 \
+ 0 \0\0\0\0\0\0\0\0\0\0\0\0\
+ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\
+ \0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+ let archive = ArchiveFile::parse(&data[..]).unwrap();
+ assert_eq!(archive.kind(), ArchiveKind::AixBig);
}
#[test]
@@ -499,4 +704,36 @@ mod tests {
assert!(members.next().is_none());
}
+
+ #[test]
+ fn aix_names() {
+ let data = b"\
+ <bigaf>\n\
+ 396 0 0 \
+ 128 262 0 \
+ 4 262 0 \
+ 1662610370 223 1 644 16 \
+ 0123456789abcdef`\nord\n\
+ 4 396 128 \
+ 1662610374 223 1 644 16 \
+ fedcba9876543210`\nrev\n\
+ 94 0 262 \
+ 0 0 0 0 0 \
+ `\n2 128 \
+ 262 0123456789abcdef\0fedcba9876543210\0";
+ let data = &data[..];
+ let archive = ArchiveFile::parse(data).unwrap();
+ assert_eq!(archive.kind(), ArchiveKind::AixBig);
+ let mut members = archive.members();
+
+ let member = members.next().unwrap().unwrap();
+ assert_eq!(member.name(), b"0123456789abcdef");
+ assert_eq!(member.data(data).unwrap(), &b"ord\n"[..]);
+
+ let member = members.next().unwrap().unwrap();
+ assert_eq!(member.name(), b"fedcba9876543210");
+ assert_eq!(member.data(data).unwrap(), &b"rev\n"[..]);
+
+ assert!(members.next().is_none());
+ }
}
diff --git a/vendor/object/src/read/coff/symbol.rs b/vendor/object/src/read/coff/symbol.rs
index c954c8a29..217e38fca 100644
--- a/vendor/object/src/read/coff/symbol.rs
+++ b/vendor/object/src/read/coff/symbol.rs
@@ -325,6 +325,14 @@ where
pub(crate) symbol: &'data pe::ImageSymbol,
}
+impl<'data, 'file, R: ReadRef<'data>> CoffSymbol<'data, 'file, R> {
+ #[inline]
+ /// Get the raw `ImageSymbol` struct.
+ pub fn raw_symbol(&self) -> &'data pe::ImageSymbol {
+ self.symbol
+ }
+}
+
impl<'data, 'file, R: ReadRef<'data>> read::private::Sealed for CoffSymbol<'data, 'file, R> {}
impl<'data, 'file, R: ReadRef<'data>> ObjectSymbol<'data> for CoffSymbol<'data, 'file, R> {
diff --git a/vendor/object/src/read/elf/comdat.rs b/vendor/object/src/read/elf/comdat.rs
index c9f0076f9..7cee85bb4 100644
--- a/vendor/object/src/read/elf/comdat.rs
+++ b/vendor/object/src/read/elf/comdat.rs
@@ -34,7 +34,7 @@ where
type Item = ElfComdat<'data, 'file, Elf, R>;
fn next(&mut self) -> Option<Self::Item> {
- while let Some((_index, section)) = self.iter.next() {
+ for (_index, section) in self.iter.by_ref() {
if let Some(comdat) = ElfComdat::parse(self.file, section) {
return Some(comdat);
}
diff --git a/vendor/object/src/read/elf/file.rs b/vendor/object/src/read/elf/file.rs
index e1f76a38c..259da7906 100644
--- a/vendor/object/src/read/elf/file.rs
+++ b/vendor/object/src/read/elf/file.rs
@@ -156,7 +156,8 @@ where
self.header.e_machine(self.endian),
self.header.is_class_64(),
) {
- (elf::EM_AARCH64, _) => Architecture::Aarch64,
+ (elf::EM_AARCH64, true) => Architecture::Aarch64,
+ (elf::EM_AARCH64, false) => Architecture::Aarch64_Ilp32,
(elf::EM_ARM, _) => Architecture::Arm,
(elf::EM_AVR, _) => Architecture::Avr,
(elf::EM_BPF, _) => Architecture::Bpf,
@@ -175,7 +176,9 @@ where
// This is either s390 or s390x, depending on the ELF class.
// We only support the 64-bit variant s390x here.
(elf::EM_S390, true) => Architecture::S390x,
+ (elf::EM_SBF, _) => Architecture::Sbf,
(elf::EM_SPARCV9, true) => Architecture::Sparc64,
+ (elf::EM_XTENSA, false) => Architecture::Xtensa,
_ => Architecture::Unknown,
}
}
diff --git a/vendor/object/src/read/elf/relocation.rs b/vendor/object/src/read/elf/relocation.rs
index 557b80efc..8443dbc75 100644
--- a/vendor/object/src/read/elf/relocation.rs
+++ b/vendor/object/src/read/elf/relocation.rs
@@ -240,19 +240,28 @@ fn parse_relocation<Elf: FileHeader>(
let mut encoding = RelocationEncoding::Generic;
let is_mips64el = header.is_mips64el(endian);
let (kind, size) = match header.e_machine(endian) {
- elf::EM_AARCH64 => match reloc.r_type(endian, false) {
- elf::R_AARCH64_ABS64 => (RelocationKind::Absolute, 64),
- elf::R_AARCH64_ABS32 => (RelocationKind::Absolute, 32),
- elf::R_AARCH64_ABS16 => (RelocationKind::Absolute, 16),
- elf::R_AARCH64_PREL64 => (RelocationKind::Relative, 64),
- elf::R_AARCH64_PREL32 => (RelocationKind::Relative, 32),
- elf::R_AARCH64_PREL16 => (RelocationKind::Relative, 16),
- elf::R_AARCH64_CALL26 => {
- encoding = RelocationEncoding::AArch64Call;
- (RelocationKind::PltRelative, 26)
+ elf::EM_AARCH64 => {
+ if header.is_type_64() {
+ match reloc.r_type(endian, false) {
+ elf::R_AARCH64_ABS64 => (RelocationKind::Absolute, 64),
+ elf::R_AARCH64_ABS32 => (RelocationKind::Absolute, 32),
+ elf::R_AARCH64_ABS16 => (RelocationKind::Absolute, 16),
+ elf::R_AARCH64_PREL64 => (RelocationKind::Relative, 64),
+ elf::R_AARCH64_PREL32 => (RelocationKind::Relative, 32),
+ elf::R_AARCH64_PREL16 => (RelocationKind::Relative, 16),
+ elf::R_AARCH64_CALL26 => {
+ encoding = RelocationEncoding::AArch64Call;
+ (RelocationKind::PltRelative, 26)
+ }
+ r_type => (RelocationKind::Elf(r_type), 0),
+ }
+ } else {
+ match reloc.r_type(endian, false) {
+ elf::R_AARCH64_P32_ABS32 => (RelocationKind::Absolute, 32),
+ r_type => (RelocationKind::Elf(r_type), 0),
+ }
}
- r_type => (RelocationKind::Elf(r_type), 0),
- },
+ }
elf::EM_ARM => match reloc.r_type(endian, false) {
elf::R_ARM_ABS32 => (RelocationKind::Absolute, 32),
r_type => (RelocationKind::Elf(r_type), 0),
@@ -304,6 +313,19 @@ fn parse_relocation<Elf: FileHeader>(
elf::EM_LOONGARCH => match reloc.r_type(endian, false) {
elf::R_LARCH_32 => (RelocationKind::Absolute, 32),
elf::R_LARCH_64 => (RelocationKind::Absolute, 64),
+ elf::R_LARCH_32_PCREL => (RelocationKind::Relative, 32),
+ elf::R_LARCH_B16 => {
+ encoding = RelocationEncoding::LoongArchBranch;
+ (RelocationKind::Relative, 16)
+ }
+ elf::R_LARCH_B21 => {
+ encoding = RelocationEncoding::LoongArchBranch;
+ (RelocationKind::Relative, 21)
+ }
+ elf::R_LARCH_B26 => {
+ encoding = RelocationEncoding::LoongArchBranch;
+ (RelocationKind::Relative, 26)
+ }
r_type => (RelocationKind::Elf(r_type), 0),
},
elf::EM_MIPS => match reloc.r_type(endian, is_mips64el) {
@@ -372,6 +394,11 @@ fn parse_relocation<Elf: FileHeader>(
}
r_type => (RelocationKind::Elf(r_type), 0),
},
+ elf::EM_SBF => match reloc.r_type(endian, false) {
+ elf::R_SBF_64_64 => (RelocationKind::Absolute, 64),
+ elf::R_SBF_64_32 => (RelocationKind::Absolute, 32),
+ r_type => (RelocationKind::Elf(r_type), 0),
+ },
elf::EM_SPARC | elf::EM_SPARC32PLUS | elf::EM_SPARCV9 => {
match reloc.r_type(endian, false) {
elf::R_SPARC_32 | elf::R_SPARC_UA32 => (RelocationKind::Absolute, 32),
@@ -379,6 +406,11 @@ fn parse_relocation<Elf: FileHeader>(
r_type => (RelocationKind::Elf(r_type), 0),
}
}
+ elf::EM_XTENSA => match reloc.r_type(endian, false) {
+ elf::R_XTENSA_32 => (RelocationKind::Absolute, 32),
+ elf::R_XTENSA_32_PCREL => (RelocationKind::Relative, 32),
+ r_type => (RelocationKind::Elf(r_type), 0),
+ },
_ => (RelocationKind::Elf(reloc.r_type(endian, false)), 0),
};
let sym = reloc.r_sym(endian, is_mips64el) as usize;
diff --git a/vendor/object/src/read/elf/segment.rs b/vendor/object/src/read/elf/segment.rs
index 874ea92b8..445893c8d 100644
--- a/vendor/object/src/read/elf/segment.rs
+++ b/vendor/object/src/read/elf/segment.rs
@@ -34,7 +34,7 @@ where
type Item = ElfSegment<'data, 'file, Elf, R>;
fn next(&mut self) -> Option<Self::Item> {
- while let Some(segment) = self.iter.next() {
+ for segment in self.iter.by_ref() {
if segment.p_type(self.file.endian) == elf::PT_LOAD {
return Some(ElfSegment {
file: self.file,
diff --git a/vendor/object/src/read/elf/symbol.rs b/vendor/object/src/read/elf/symbol.rs
index f52eff20e..5d8d29f27 100644
--- a/vendor/object/src/read/elf/symbol.rs
+++ b/vendor/object/src/read/elf/symbol.rs
@@ -4,7 +4,6 @@ use core::fmt::Debug;
use core::slice;
use core::str;
-use crate::elf;
use crate::endian::{self, Endianness};
use crate::pod::Pod;
use crate::read::util::StringTable;
@@ -12,6 +11,7 @@ use crate::read::{
self, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, SectionIndex, SymbolFlags,
SymbolIndex, SymbolKind, SymbolMap, SymbolMapEntry, SymbolScope, SymbolSection,
};
+use crate::{elf, U32};
use super::{FileHeader, SectionHeader, SectionTable};
@@ -28,7 +28,7 @@ where
shndx_section: SectionIndex,
symbols: &'data [Elf::Sym],
strings: StringTable<'data, R>,
- shndx: &'data [u32],
+ shndx: &'data [U32<Elf::Endian>],
}
impl<'data, Elf: FileHeader, R: ReadRef<'data>> Default for SymbolTable<'data, Elf, R> {
@@ -145,8 +145,8 @@ impl<'data, Elf: FileHeader, R: ReadRef<'data>> SymbolTable<'data, Elf, R> {
/// Return the extended section index for the given symbol if present.
#[inline]
- pub fn shndx(&self, index: usize) -> Option<u32> {
- self.shndx.get(index).copied()
+ pub fn shndx(&self, endian: Elf::Endian, index: usize) -> Option<u32> {
+ self.shndx.get(index).map(|x| x.get(endian))
}
/// Return the section index for the given symbol.
@@ -161,7 +161,7 @@ impl<'data, Elf: FileHeader, R: ReadRef<'data>> SymbolTable<'data, Elf, R> {
match symbol.st_shndx(endian) {
elf::SHN_UNDEF => Ok(None),
elf::SHN_XINDEX => self
- .shndx(index)
+ .shndx(endian, index)
.read_error("Missing ELF symbol extended index")
.map(|index| Some(SectionIndex(index as usize))),
shndx if shndx < elf::SHN_LORESERVE => Ok(Some(SectionIndex(shndx.into()))),
@@ -349,8 +349,9 @@ impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data>
fn kind(&self) -> SymbolKind {
match self.symbol.st_type() {
elf::STT_NOTYPE if self.index.0 == 0 => SymbolKind::Null,
+ elf::STT_NOTYPE => SymbolKind::Label,
elf::STT_OBJECT | elf::STT_COMMON => SymbolKind::Data,
- elf::STT_FUNC => SymbolKind::Text,
+ elf::STT_FUNC | elf::STT_GNU_IFUNC => SymbolKind::Text,
elf::STT_SECTION => SymbolKind::Section,
elf::STT_FILE => SymbolKind::File,
elf::STT_TLS => SymbolKind::Tls,
@@ -369,7 +370,7 @@ impl<'data, 'file, Elf: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data>
}
}
elf::SHN_COMMON => SymbolSection::Common,
- elf::SHN_XINDEX => match self.symbols.shndx(self.index.0) {
+ elf::SHN_XINDEX => match self.symbols.shndx(self.endian, self.index.0) {
Some(index) => SymbolSection::Section(SectionIndex(index as usize)),
None => SymbolSection::Unknown,
},
diff --git a/vendor/object/src/read/macho/fat.rs b/vendor/object/src/read/macho/fat.rs
index 6fc649f31..d4301b7e1 100644
--- a/vendor/object/src/read/macho/fat.rs
+++ b/vendor/object/src/read/macho/fat.rs
@@ -57,6 +57,8 @@ pub trait FatArch: Pod {
macho::CPU_TYPE_X86 => Architecture::I386,
macho::CPU_TYPE_X86_64 => Architecture::X86_64,
macho::CPU_TYPE_MIPS => Architecture::Mips,
+ macho::CPU_TYPE_POWERPC => Architecture::PowerPc,
+ macho::CPU_TYPE_POWERPC64 => Architecture::PowerPc64,
_ => Architecture::Unknown,
}
}
diff --git a/vendor/object/src/read/macho/file.rs b/vendor/object/src/read/macho/file.rs
index e028de3b9..ab8c05757 100644
--- a/vendor/object/src/read/macho/file.rs
+++ b/vendor/object/src/read/macho/file.rs
@@ -195,6 +195,8 @@ where
macho::CPU_TYPE_X86 => Architecture::I386,
macho::CPU_TYPE_X86_64 => Architecture::X86_64,
macho::CPU_TYPE_MIPS => Architecture::Mips,
+ macho::CPU_TYPE_POWERPC => Architecture::PowerPc,
+ macho::CPU_TYPE_POWERPC64 => Architecture::PowerPc64,
_ => Architecture::Unknown,
}
}
diff --git a/vendor/object/src/read/macho/load_command.rs b/vendor/object/src/read/macho/load_command.rs
index 29fab6e0e..10daf4ed1 100644
--- a/vendor/object/src/read/macho/load_command.rs
+++ b/vendor/object/src/read/macho/load_command.rs
@@ -77,6 +77,11 @@ impl<'data, E: Endian> LoadCommandData<'data, E> {
.read_error("Invalid Mach-O command size")
}
+ /// Raw bytes of this LoadCommand structure.
+ pub fn raw_data(&self) -> &'data [u8] {
+ self.data.0
+ }
+
/// Parse a load command string value.
///
/// Strings used by load commands are specified by offsets that are
diff --git a/vendor/object/src/read/mod.rs b/vendor/object/src/read/mod.rs
index 41d344111..91a5c05a5 100644
--- a/vendor/object/src/read/mod.rs
+++ b/vendor/object/src/read/mod.rs
@@ -22,7 +22,8 @@ pub use util::*;
feature = "elf",
feature = "macho",
feature = "pe",
- feature = "wasm"
+ feature = "wasm",
+ feature = "xcoff"
))]
mod any;
#[cfg(any(
@@ -30,7 +31,8 @@ mod any;
feature = "elf",
feature = "macho",
feature = "pe",
- feature = "wasm"
+ feature = "wasm",
+ feature = "xcoff"
))]
pub use any::*;
@@ -49,12 +51,15 @@ pub mod macho;
#[cfg(feature = "pe")]
pub mod pe;
-mod traits;
-pub use traits::*;
-
#[cfg(feature = "wasm")]
pub mod wasm;
+#[cfg(feature = "xcoff")]
+pub mod xcoff;
+
+mod traits;
+pub use traits::*;
+
mod private {
pub trait Sealed {}
}
@@ -176,6 +181,12 @@ pub enum FileKind {
/// A Wasm file.
#[cfg(feature = "wasm")]
Wasm,
+ /// A 32-bit XCOFF file.
+ #[cfg(feature = "xcoff")]
+ Xcoff32,
+ /// A 64-bit XCOFF file.
+ #[cfg(feature = "xcoff")]
+ Xcoff64,
}
impl FileKind {
@@ -236,6 +247,10 @@ impl FileKind {
| [0x4c, 0x01, ..]
// COFF x86-64
| [0x64, 0x86, ..] => FileKind::Coff,
+ #[cfg(feature = "xcoff")]
+ [0x01, 0xDF, ..] => FileKind::Xcoff32,
+ #[cfg(feature = "xcoff")]
+ [0x01, 0xF7, ..] => FileKind::Xcoff64,
_ => return Err(Error("Unknown file magic")),
};
Ok(kind)
diff --git a/vendor/object/src/read/pe/data_directory.rs b/vendor/object/src/read/pe/data_directory.rs
index 8c1955355..f5d98774e 100644
--- a/vendor/object/src/read/pe/data_directory.rs
+++ b/vendor/object/src/read/pe/data_directory.rs
@@ -3,7 +3,10 @@ use core::slice;
use crate::read::{Error, ReadError, ReadRef, Result};
use crate::{pe, LittleEndian as LE};
-use super::{ExportTable, ImportTable, RelocationBlockIterator, ResourceDirectory, SectionTable};
+use super::{
+ DelayLoadImportTable, ExportTable, ImportTable, RelocationBlockIterator, ResourceDirectory,
+ SectionTable,
+};
/// The table of data directories in a PE file.
#[derive(Debug, Clone, Copy)]
@@ -105,6 +108,29 @@ impl<'data> DataDirectories<'data> {
Ok(Some(ImportTable::new(section_data, section_va, import_va)))
}
+ /// Returns the partially parsed delay-load import directory.
+ ///
+ /// `data` must be the entire file data.
+ pub fn delay_load_import_table<R: ReadRef<'data>>(
+ &self,
+ data: R,
+ sections: &SectionTable<'data>,
+ ) -> Result<Option<DelayLoadImportTable<'data>>> {
+ let data_dir = match self.get(pe::IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT) {
+ Some(data_dir) => data_dir,
+ None => return Ok(None),
+ };
+ let import_va = data_dir.virtual_address.get(LE);
+ let (section_data, section_va) = sections
+ .pe_data_containing(data, import_va)
+ .read_error("Invalid import data dir virtual address")?;
+ Ok(Some(DelayLoadImportTable::new(
+ section_data,
+ section_va,
+ import_va,
+ )))
+ }
+
/// Returns the blocks in the base relocation directory.
///
/// `data` must be the entire file data.
diff --git a/vendor/object/src/read/pe/file.rs b/vendor/object/src/read/pe/file.rs
index 15b42074a..8dd85131a 100644
--- a/vendor/object/src/read/pe/file.rs
+++ b/vendor/object/src/read/pe/file.rs
@@ -304,49 +304,60 @@ where
None => return Ok(None),
};
let debug_data = data_dir.data(self.data, &self.common.sections).map(Bytes)?;
- let debug_dir = debug_data
- .read_at::<pe::ImageDebugDirectory>(0)
- .read_error("Invalid PE debug dir size")?;
+ let debug_data_size = data_dir.size.get(LE) as usize;
- if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW {
- return Ok(None);
+ let count = debug_data_size / mem::size_of::<pe::ImageDebugDirectory>();
+ let rem = debug_data_size % mem::size_of::<pe::ImageDebugDirectory>();
+ if rem != 0 || count < 1 {
+ return Err(Error("Invalid PE debug dir size"));
}
- let info = self
- .data
- .read_slice_at::<u8>(
- debug_dir.pointer_to_raw_data.get(LE) as u64,
- debug_dir.size_of_data.get(LE) as usize,
- )
- .read_error("Invalid CodeView Info address")?;
-
- let mut info = Bytes(info);
-
- let sig = info
- .read_bytes(4)
- .read_error("Invalid CodeView signature")?;
- if sig.0 != b"RSDS" {
- return Ok(None);
- }
+ let debug_dirs = debug_data
+ .read_slice_at::<pe::ImageDebugDirectory>(0, count)
+ .read_error("Invalid PE debug dir size")?;
+
+ for debug_dir in debug_dirs {
+ if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW {
+ continue;
+ }
+
+ let info = self
+ .data
+ .read_slice_at::<u8>(
+ debug_dir.pointer_to_raw_data.get(LE) as u64,
+ debug_dir.size_of_data.get(LE) as usize,
+ )
+ .read_error("Invalid CodeView Info address")?;
+
+ let mut info = Bytes(info);
+
+ let sig = info
+ .read_bytes(4)
+ .read_error("Invalid CodeView signature")?;
+ if sig.0 != b"RSDS" {
+ continue;
+ }
- let guid: [u8; 16] = info
- .read_bytes(16)
- .read_error("Invalid CodeView GUID")?
- .0
- .try_into()
- .unwrap();
+ let guid: [u8; 16] = info
+ .read_bytes(16)
+ .read_error("Invalid CodeView GUID")?
+ .0
+ .try_into()
+ .unwrap();
- let age = info.read::<U32<LE>>().read_error("Invalid CodeView Age")?;
+ let age = info.read::<U32<LE>>().read_error("Invalid CodeView Age")?;
- let path = info
- .read_string()
- .read_error("Invalid CodeView file path")?;
+ let path = info
+ .read_string()
+ .read_error("Invalid CodeView file path")?;
- Ok(Some(CodeView {
- path: ByteString(path),
- guid,
- age: age.get(LE),
- }))
+ return Ok(Some(CodeView {
+ path: ByteString(path),
+ guid,
+ age: age.get(LE),
+ }));
+ }
+ Ok(None)
}
fn has_debug_symbols(&self) -> bool {
diff --git a/vendor/object/src/read/pe/import.rs b/vendor/object/src/read/pe/import.rs
index 809a96286..a5535dc36 100644
--- a/vendor/object/src/read/pe/import.rs
+++ b/vendor/object/src/read/pe/import.rs
@@ -216,3 +216,117 @@ impl ImageThunkData for pe::ImageThunkData32 {
self.0.get(LE) & 0x7fff_ffff
}
}
+
+/// Information for parsing a PE delay-load import table.
+#[derive(Debug, Clone)]
+pub struct DelayLoadImportTable<'data> {
+ section_data: Bytes<'data>,
+ section_address: u32,
+ import_address: u32,
+}
+
+impl<'data> DelayLoadImportTable<'data> {
+ /// Create a new delay load import table parser.
+ ///
+ /// The import descriptors start at `import_address`.
+ /// This table works in the same way the import table does: descriptors will be
+ /// parsed until a null entry.
+ ///
+ /// `section_data` should be from the section containing `import_address`, and
+ /// `section_address` should be the address of that section. Pointers within the
+ /// descriptors and thunks may point to anywhere within the section data.
+ pub fn new(section_data: &'data [u8], section_address: u32, import_address: u32) -> Self {
+ DelayLoadImportTable {
+ section_data: Bytes(section_data),
+ section_address,
+ import_address,
+ }
+ }
+
+ /// Return an iterator for the import descriptors.
+ pub fn descriptors(&self) -> Result<DelayLoadDescriptorIterator<'data>> {
+ let offset = self.import_address.wrapping_sub(self.section_address);
+ let mut data = self.section_data;
+ data.skip(offset as usize)
+ .read_error("Invalid PE delay-load import descriptor address")?;
+ Ok(DelayLoadDescriptorIterator { data })
+ }
+
+ /// Return a library name given its address.
+ ///
+ /// This address may be from [`pe::ImageDelayloadDescriptor::dll_name_rva`].
+ pub fn name(&self, address: u32) -> Result<&'data [u8]> {
+ self.section_data
+ .read_string_at(address.wrapping_sub(self.section_address) as usize)
+ .read_error("Invalid PE import descriptor name")
+ }
+
+ /// Return a list of thunks given its address.
+ ///
+ /// This address may be from the INT, i.e. from
+ /// [`pe::ImageDelayloadDescriptor::import_name_table_rva`].
+ ///
+ /// Please note that others RVA values from [`pe::ImageDelayloadDescriptor`] are used
+ /// by the delay loader at runtime to store values, and thus do not point inside the same
+ /// section as the INT. Calling this function on those addresses will fail.
+ pub fn thunks(&self, address: u32) -> Result<ImportThunkList<'data>> {
+ let offset = address.wrapping_sub(self.section_address);
+ let mut data = self.section_data;
+ data.skip(offset as usize)
+ .read_error("Invalid PE delay load import thunk table address")?;
+ Ok(ImportThunkList { data })
+ }
+
+ /// Parse a thunk.
+ pub fn import<Pe: ImageNtHeaders>(&self, thunk: Pe::ImageThunkData) -> Result<Import<'data>> {
+ if thunk.is_ordinal() {
+ Ok(Import::Ordinal(thunk.ordinal()))
+ } else {
+ let (hint, name) = self.hint_name(thunk.address())?;
+ Ok(Import::Name(hint, name))
+ }
+ }
+
+ /// Return the hint and name at the given address.
+ ///
+ /// This address may be from [`pe::ImageThunkData32`] or [`pe::ImageThunkData64`].
+ ///
+ /// The hint is an index into the export name pointer table in the target library.
+ pub fn hint_name(&self, address: u32) -> Result<(u16, &'data [u8])> {
+ let offset = address.wrapping_sub(self.section_address);
+ let mut data = self.section_data;
+ data.skip(offset as usize)
+ .read_error("Invalid PE delay load import thunk address")?;
+ let hint = data
+ .read::<U16Bytes<LE>>()
+ .read_error("Missing PE delay load import thunk hint")?
+ .get(LE);
+ let name = data
+ .read_string()
+ .read_error("Missing PE delay load import thunk name")?;
+ Ok((hint, name))
+ }
+}
+
+/// A fallible iterator for the descriptors in the delay-load data directory.
+#[derive(Debug, Clone)]
+pub struct DelayLoadDescriptorIterator<'data> {
+ data: Bytes<'data>,
+}
+
+impl<'data> DelayLoadDescriptorIterator<'data> {
+ /// Return the next descriptor.
+ ///
+ /// Returns `Ok(None)` when a null descriptor is found.
+ pub fn next(&mut self) -> Result<Option<&'data pe::ImageDelayloadDescriptor>> {
+ let import_desc = self
+ .data
+ .read::<pe::ImageDelayloadDescriptor>()
+ .read_error("Missing PE null delay-load import descriptor")?;
+ if import_desc.is_null() {
+ Ok(None)
+ } else {
+ Ok(Some(import_desc))
+ }
+ }
+}
diff --git a/vendor/object/src/read/pe/resource.rs b/vendor/object/src/read/pe/resource.rs
index bfbb609f5..e667f0d98 100644
--- a/vendor/object/src/read/pe/resource.rs
+++ b/vendor/object/src/read/pe/resource.rs
@@ -1,7 +1,8 @@
use alloc::string::String;
+use core::char;
use crate::read::{ReadError, ReadRef, Result};
-use crate::{pe, LittleEndian as LE, U16};
+use crate::{pe, LittleEndian as LE, U16Bytes};
/// The `.rsrc` section of a PE file.
#[derive(Debug, Clone, Copy)]
@@ -17,7 +18,7 @@ impl<'data> ResourceDirectory<'data> {
/// Parses the root resource directory.
pub fn root(&self) -> Result<ResourceDirectoryTable<'data>> {
- ResourceDirectoryTable::parse(&self.data, 0)
+ ResourceDirectoryTable::parse(self.data, 0)
}
}
@@ -92,13 +93,13 @@ impl pe::ImageResourceDirectoryEntry {
) -> Result<ResourceDirectoryEntryData<'data>> {
if self.is_table() {
ResourceDirectoryTable::parse(section.data, self.data_offset())
- .map(|t| ResourceDirectoryEntryData::Table(t))
+ .map(ResourceDirectoryEntryData::Table)
} else {
section
.data
.read_at::<pe::ImageResourceDataEntry>(self.data_offset().into())
.read_error("Invalid resource entry")
- .map(|d| ResourceDirectoryEntryData::Data(d))
+ .map(ResourceDirectoryEntryData::Data)
}
}
}
@@ -143,22 +144,33 @@ pub struct ResourceName {
impl ResourceName {
/// Converts to a `String`.
pub fn to_string_lossy(&self, directory: ResourceDirectory) -> Result<String> {
- let d = self.data(directory)?;
- Ok(String::from_utf16_lossy(d))
+ let d = self.data(directory)?.iter().map(|c| c.get(LE));
+
+ Ok(char::decode_utf16(d)
+ .map(|r| r.unwrap_or(char::REPLACEMENT_CHARACTER))
+ .collect::<String>())
}
/// Returns the string unicode buffer.
- pub fn data<'data>(&self, directory: ResourceDirectory<'data>) -> Result<&'data [u16]> {
+ pub fn data<'data>(
+ &self,
+ directory: ResourceDirectory<'data>,
+ ) -> Result<&'data [U16Bytes<LE>]> {
let mut offset = u64::from(self.offset);
let len = directory
.data
- .read::<U16<LE>>(&mut offset)
+ .read::<U16Bytes<LE>>(&mut offset)
.read_error("Invalid resource name offset")?;
directory
.data
- .read_slice::<u16>(&mut offset, len.get(LE).into())
+ .read_slice::<U16Bytes<LE>>(&mut offset, len.get(LE).into())
.read_error("Invalid resource name length")
}
+
+ /// Returns the string buffer as raw bytes.
+ pub fn raw_data<'data>(&self, directory: ResourceDirectory<'data>) -> Result<&'data [u8]> {
+ self.data(directory).map(crate::pod::bytes_of_slice)
+ }
}
/// A resource name or ID.
diff --git a/vendor/object/src/read/xcoff/comdat.rs b/vendor/object/src/read/xcoff/comdat.rs
new file mode 100644
index 000000000..eeed2f54d
--- /dev/null
+++ b/vendor/object/src/read/xcoff/comdat.rs
@@ -0,0 +1,130 @@
+//! XCOFF doesn't support the COMDAT section.
+
+use core::fmt::Debug;
+
+use crate::xcoff;
+
+use crate::read::{self, ComdatKind, ObjectComdat, ReadRef, Result, SectionIndex, SymbolIndex};
+
+use super::{FileHeader, XcoffFile};
+
+/// An iterator over the COMDAT section groups of a `XcoffFile32`.
+pub type XcoffComdatIterator32<'data, 'file, R = &'data [u8]> =
+ XcoffComdatIterator<'data, 'file, xcoff::FileHeader32, R>;
+/// An iterator over the COMDAT section groups of a `XcoffFile64`.
+pub type XcoffComdatIterator64<'data, 'file, R = &'data [u8]> =
+ XcoffComdatIterator<'data, 'file, xcoff::FileHeader64, R>;
+
+/// An iterator over the COMDAT section groups of a `XcoffFile`.
+#[derive(Debug)]
+pub struct XcoffComdatIterator<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ #[allow(unused)]
+ pub(crate) file: &'file XcoffFile<'data, Xcoff, R>,
+}
+
+impl<'data, 'file, Xcoff, R> Iterator for XcoffComdatIterator<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ type Item = XcoffComdat<'data, 'file, Xcoff, R>;
+
+ #[inline]
+ fn next(&mut self) -> Option<Self::Item> {
+ None
+ }
+}
+
+/// A COMDAT section group of a `XcoffFile32`.
+pub type XcoffComdat32<'data, 'file, R = &'data [u8]> =
+ XcoffComdat<'data, 'file, xcoff::FileHeader32, R>;
+
+/// A COMDAT section group of a `XcoffFile64`.
+pub type XcoffComdat64<'data, 'file, R = &'data [u8]> =
+ XcoffComdat<'data, 'file, xcoff::FileHeader64, R>;
+
+/// A COMDAT section group of a `XcoffFile`.
+#[derive(Debug)]
+pub struct XcoffComdat<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ #[allow(unused)]
+ file: &'file XcoffFile<'data, Xcoff, R>,
+}
+
+impl<'data, 'file, Xcoff, R> read::private::Sealed for XcoffComdat<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+}
+
+impl<'data, 'file, Xcoff, R> ObjectComdat<'data> for XcoffComdat<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ type SectionIterator = XcoffComdatSectionIterator<'data, 'file, Xcoff, R>;
+
+ #[inline]
+ fn kind(&self) -> ComdatKind {
+ unreachable!();
+ }
+
+ #[inline]
+ fn symbol(&self) -> SymbolIndex {
+ unreachable!();
+ }
+
+ #[inline]
+ fn name_bytes(&self) -> Result<&[u8]> {
+ unreachable!();
+ }
+
+ #[inline]
+ fn name(&self) -> Result<&str> {
+ unreachable!();
+ }
+
+ #[inline]
+ fn sections(&self) -> Self::SectionIterator {
+ unreachable!();
+ }
+}
+
+/// An iterator over the sections in a COMDAT section group of a `XcoffFile32`.
+pub type XcoffComdatSectionIterator32<'data, 'file, R = &'data [u8]> =
+ XcoffComdatSectionIterator<'data, 'file, xcoff::FileHeader32, R>;
+/// An iterator over the sections in a COMDAT section group of a `XcoffFile64`.
+pub type XcoffComdatSectionIterator64<'data, 'file, R = &'data [u8]> =
+ XcoffComdatSectionIterator<'data, 'file, xcoff::FileHeader64, R>;
+
+/// An iterator over the sections in a COMDAT section group of a `XcoffFile`.
+#[derive(Debug)]
+pub struct XcoffComdatSectionIterator<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ 'data: 'file,
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ #[allow(unused)]
+ file: &'file XcoffFile<'data, Xcoff, R>,
+}
+
+impl<'data, 'file, Xcoff, R> Iterator for XcoffComdatSectionIterator<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ type Item = SectionIndex;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ None
+ }
+}
diff --git a/vendor/object/src/read/xcoff/file.rs b/vendor/object/src/read/xcoff/file.rs
new file mode 100644
index 000000000..bac9e7075
--- /dev/null
+++ b/vendor/object/src/read/xcoff/file.rs
@@ -0,0 +1,629 @@
+use core::fmt::Debug;
+use core::mem;
+
+use alloc::vec::Vec;
+
+use crate::read::{self, Error, NoDynamicRelocationIterator, Object, ReadError, ReadRef, Result};
+
+use crate::{
+ xcoff, Architecture, BigEndian as BE, FileFlags, ObjectKind, ObjectSection, Pod, SectionIndex,
+ SymbolIndex,
+};
+
+use super::{
+ CsectAux, FileAux, SectionHeader, SectionTable, Symbol, SymbolTable, XcoffComdat,
+ XcoffComdatIterator, XcoffSection, XcoffSectionIterator, XcoffSegment, XcoffSegmentIterator,
+ XcoffSymbol, XcoffSymbolIterator, XcoffSymbolTable,
+};
+
+/// A 32-bit XCOFF object file.
+pub type XcoffFile32<'data, R = &'data [u8]> = XcoffFile<'data, xcoff::FileHeader32, R>;
+/// A 64-bit XCOFF object file.
+pub type XcoffFile64<'data, R = &'data [u8]> = XcoffFile<'data, xcoff::FileHeader64, R>;
+
+/// A partially parsed XCOFF file.
+///
+/// Most of the functionality of this type is provided by the `Object` trait implementation.
+#[derive(Debug)]
+pub struct XcoffFile<'data, Xcoff, R = &'data [u8]>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ pub(super) data: R,
+ pub(super) header: &'data Xcoff,
+ pub(super) aux_header: Option<&'data Xcoff::AuxHeader>,
+ pub(super) sections: SectionTable<'data, Xcoff>,
+ pub(super) symbols: SymbolTable<'data, Xcoff, R>,
+}
+
+impl<'data, Xcoff, R> XcoffFile<'data, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ /// Parse the raw XCOFF file data.
+ pub fn parse(data: R) -> Result<Self> {
+ let mut offset = 0;
+ let header = Xcoff::parse(data, &mut offset)?;
+ let aux_header = header.aux_header(data, &mut offset)?;
+ let sections = header.sections(data, &mut offset)?;
+ let symbols = header.symbols(data)?;
+
+ Ok(XcoffFile {
+ data,
+ header,
+ aux_header,
+ sections,
+ symbols,
+ })
+ }
+
+ /// Returns the raw data.
+ pub fn data(&self) -> R {
+ self.data
+ }
+
+ /// Returns the raw XCOFF file header.
+ pub fn raw_header(&self) -> &'data Xcoff {
+ self.header
+ }
+}
+
+impl<'data, Xcoff, R> read::private::Sealed for XcoffFile<'data, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+}
+
+impl<'data, 'file, Xcoff, R> Object<'data, 'file> for XcoffFile<'data, Xcoff, R>
+where
+ 'data: 'file,
+ Xcoff: FileHeader,
+ R: 'file + ReadRef<'data>,
+{
+ type Segment = XcoffSegment<'data, 'file, Xcoff, R>;
+ type SegmentIterator = XcoffSegmentIterator<'data, 'file, Xcoff, R>;
+ type Section = XcoffSection<'data, 'file, Xcoff, R>;
+ type SectionIterator = XcoffSectionIterator<'data, 'file, Xcoff, R>;
+ type Comdat = XcoffComdat<'data, 'file, Xcoff, R>;
+ type ComdatIterator = XcoffComdatIterator<'data, 'file, Xcoff, R>;
+ type Symbol = XcoffSymbol<'data, 'file, Xcoff, R>;
+ type SymbolIterator = XcoffSymbolIterator<'data, 'file, Xcoff, R>;
+ type SymbolTable = XcoffSymbolTable<'data, 'file, Xcoff, R>;
+ type DynamicRelocationIterator = NoDynamicRelocationIterator;
+
+ fn architecture(&self) -> crate::Architecture {
+ if self.is_64() {
+ Architecture::PowerPc64
+ } else {
+ Architecture::PowerPc
+ }
+ }
+
+ fn is_little_endian(&self) -> bool {
+ false
+ }
+
+ fn is_64(&self) -> bool {
+ self.header.is_type_64()
+ }
+
+ fn kind(&self) -> ObjectKind {
+ let flags = self.header.f_flags();
+ if flags & xcoff::F_EXEC != 0 {
+ ObjectKind::Executable
+ } else if flags & xcoff::F_SHROBJ != 0 {
+ ObjectKind::Dynamic
+ } else if flags & xcoff::F_RELFLG == 0 {
+ ObjectKind::Relocatable
+ } else {
+ ObjectKind::Unknown
+ }
+ }
+
+ fn segments(&'file self) -> XcoffSegmentIterator<'data, 'file, Xcoff, R> {
+ XcoffSegmentIterator { file: self }
+ }
+
+ fn section_by_name_bytes(
+ &'file self,
+ section_name: &[u8],
+ ) -> Option<XcoffSection<'data, 'file, Xcoff, R>> {
+ self.sections()
+ .find(|section| section.name_bytes() == Ok(section_name))
+ }
+
+ fn section_by_index(
+ &'file self,
+ index: SectionIndex,
+ ) -> Result<XcoffSection<'data, 'file, Xcoff, R>> {
+ let section = self.sections.section(index)?;
+ Ok(XcoffSection {
+ file: self,
+ section,
+ index,
+ })
+ }
+
+ fn sections(&'file self) -> XcoffSectionIterator<'data, 'file, Xcoff, R> {
+ XcoffSectionIterator {
+ file: self,
+ iter: self.sections.iter().enumerate(),
+ }
+ }
+
+ fn comdats(&'file self) -> XcoffComdatIterator<'data, 'file, Xcoff, R> {
+ XcoffComdatIterator { file: self }
+ }
+
+ fn symbol_table(&'file self) -> Option<XcoffSymbolTable<'data, 'file, Xcoff, R>> {
+ if self.symbols.is_empty() {
+ return None;
+ }
+ Some(XcoffSymbolTable {
+ symbols: &self.symbols,
+ file: self,
+ })
+ }
+
+ fn symbol_by_index(
+ &'file self,
+ index: SymbolIndex,
+ ) -> Result<XcoffSymbol<'data, 'file, Xcoff, R>> {
+ let symbol = self.symbols.symbol(index.0)?;
+ Ok(XcoffSymbol {
+ symbols: &self.symbols,
+ index,
+ symbol,
+ file: self,
+ })
+ }
+
+ fn symbols(&'file self) -> XcoffSymbolIterator<'data, 'file, Xcoff, R> {
+ XcoffSymbolIterator {
+ symbols: &self.symbols,
+ index: 0,
+ file: self,
+ }
+ }
+
+ fn dynamic_symbol_table(&'file self) -> Option<XcoffSymbolTable<'data, 'file, Xcoff, R>> {
+ None
+ }
+
+ fn dynamic_symbols(&'file self) -> XcoffSymbolIterator<'data, 'file, Xcoff, R> {
+ // TODO: return the symbols in the STYP_LOADER section.
+ XcoffSymbolIterator {
+ file: self,
+ symbols: &self.symbols,
+ // Hack: don't return any.
+ index: self.symbols.len(),
+ }
+ }
+
+ fn dynamic_relocations(&'file self) -> Option<Self::DynamicRelocationIterator> {
+ // TODO: return the relocations in the STYP_LOADER section.
+ None
+ }
+
+ fn imports(&self) -> Result<alloc::vec::Vec<crate::Import<'data>>> {
+ // TODO: return the imports in the STYP_LOADER section.
+ Ok(Vec::new())
+ }
+
+ fn exports(&self) -> Result<alloc::vec::Vec<crate::Export<'data>>> {
+ // TODO: return the exports in the STYP_LOADER section.
+ Ok(Vec::new())
+ }
+
+ fn has_debug_symbols(&self) -> bool {
+ self.section_by_name(".debug").is_some() || self.section_by_name(".dwinfo").is_some()
+ }
+
+ fn relative_address_base(&'file self) -> u64 {
+ 0
+ }
+
+ fn entry(&'file self) -> u64 {
+ if let Some(aux_header) = self.aux_header {
+ aux_header.o_entry().into()
+ } else {
+ 0
+ }
+ }
+
+ fn flags(&self) -> FileFlags {
+ FileFlags::Xcoff {
+ f_flags: self.header.f_flags(),
+ }
+ }
+}
+
+/// A trait for generic access to `FileHeader32` and `FileHeader64`.
+#[allow(missing_docs)]
+pub trait FileHeader: Debug + Pod {
+ type Word: Into<u64>;
+ type AuxHeader: AuxHeader<Word = Self::Word>;
+ type SectionHeader: SectionHeader<Word = Self::Word>;
+ type Symbol: Symbol<Word = Self::Word>;
+ type FileAux: FileAux;
+ type CsectAux: CsectAux;
+
+ /// Return true if this type is a 64-bit header.
+ fn is_type_64(&self) -> bool;
+
+ fn f_magic(&self) -> u16;
+ fn f_nscns(&self) -> u16;
+ fn f_timdat(&self) -> u32;
+ fn f_symptr(&self) -> Self::Word;
+ fn f_nsyms(&self) -> u32;
+ fn f_opthdr(&self) -> u16;
+ fn f_flags(&self) -> u16;
+
+ // Provided methods.
+
+ /// Read the file header.
+ ///
+ /// Also checks that the magic field in the file header is a supported format.
+ fn parse<'data, R: ReadRef<'data>>(data: R, offset: &mut u64) -> Result<&'data Self> {
+ let header = data
+ .read::<Self>(offset)
+ .read_error("Invalid XCOFF header size or alignment")?;
+ if !header.is_supported() {
+ return Err(Error("Unsupported XCOFF header"));
+ }
+ Ok(header)
+ }
+
+ fn is_supported(&self) -> bool {
+ (self.is_type_64() && self.f_magic() == xcoff::MAGIC_64)
+ || (!self.is_type_64() && self.f_magic() == xcoff::MAGIC_32)
+ }
+
+ /// Read the auxiliary file header.
+ fn aux_header<'data, R: ReadRef<'data>>(
+ &self,
+ data: R,
+ offset: &mut u64,
+ ) -> Result<Option<&'data Self::AuxHeader>> {
+ let aux_header_size = self.f_opthdr();
+ if self.f_flags() & xcoff::F_EXEC == 0 {
+ // No auxiliary header is required for an object file that is not an executable.
+ // TODO: Some AIX programs generate auxiliary headers for 32-bit object files
+ // that end after the data_start field.
+ *offset += u64::from(aux_header_size);
+ return Ok(None);
+ }
+ // Executables, however, must have auxiliary headers that include the
+ // full structure definitions.
+ if aux_header_size != mem::size_of::<Self::AuxHeader>() as u16 {
+ *offset += u64::from(aux_header_size);
+ return Ok(None);
+ }
+ let aux_header = data
+ .read::<Self::AuxHeader>(offset)
+ .read_error("Invalid XCOFF auxiliary header size")?;
+ Ok(Some(aux_header))
+ }
+
+ /// Read the section table.
+ #[inline]
+ fn sections<'data, R: ReadRef<'data>>(
+ &self,
+ data: R,
+ offset: &mut u64,
+ ) -> Result<SectionTable<'data, Self>> {
+ SectionTable::parse(self, data, offset)
+ }
+
+ /// Return the symbol table.
+ #[inline]
+ fn symbols<'data, R: ReadRef<'data>>(&self, data: R) -> Result<SymbolTable<'data, Self, R>> {
+ SymbolTable::parse(*self, data)
+ }
+}
+
+impl FileHeader for xcoff::FileHeader32 {
+ type Word = u32;
+ type AuxHeader = xcoff::AuxHeader32;
+ type SectionHeader = xcoff::SectionHeader32;
+ type Symbol = xcoff::Symbol32;
+ type FileAux = xcoff::FileAux32;
+ type CsectAux = xcoff::CsectAux32;
+
+ fn is_type_64(&self) -> bool {
+ false
+ }
+
+ fn f_magic(&self) -> u16 {
+ self.f_magic.get(BE)
+ }
+
+ fn f_nscns(&self) -> u16 {
+ self.f_nscns.get(BE)
+ }
+
+ fn f_timdat(&self) -> u32 {
+ self.f_timdat.get(BE)
+ }
+
+ fn f_symptr(&self) -> Self::Word {
+ self.f_symptr.get(BE)
+ }
+
+ fn f_nsyms(&self) -> u32 {
+ self.f_nsyms.get(BE)
+ }
+
+ fn f_opthdr(&self) -> u16 {
+ self.f_opthdr.get(BE)
+ }
+
+ fn f_flags(&self) -> u16 {
+ self.f_flags.get(BE)
+ }
+}
+
+impl FileHeader for xcoff::FileHeader64 {
+ type Word = u64;
+ type AuxHeader = xcoff::AuxHeader64;
+ type SectionHeader = xcoff::SectionHeader64;
+ type Symbol = xcoff::Symbol64;
+ type FileAux = xcoff::FileAux64;
+ type CsectAux = xcoff::CsectAux64;
+
+ fn is_type_64(&self) -> bool {
+ true
+ }
+
+ fn f_magic(&self) -> u16 {
+ self.f_magic.get(BE)
+ }
+
+ fn f_nscns(&self) -> u16 {
+ self.f_nscns.get(BE)
+ }
+
+ fn f_timdat(&self) -> u32 {
+ self.f_timdat.get(BE)
+ }
+
+ fn f_symptr(&self) -> Self::Word {
+ self.f_symptr.get(BE)
+ }
+
+ fn f_nsyms(&self) -> u32 {
+ self.f_nsyms.get(BE)
+ }
+
+ fn f_opthdr(&self) -> u16 {
+ self.f_opthdr.get(BE)
+ }
+
+ fn f_flags(&self) -> u16 {
+ self.f_flags.get(BE)
+ }
+}
+
+#[allow(missing_docs)]
+pub trait AuxHeader: Debug + Pod {
+ type Word: Into<u64>;
+
+ fn o_vstamp(&self) -> u16;
+ fn o_tsize(&self) -> Self::Word;
+ fn o_dsize(&self) -> Self::Word;
+ fn o_bsize(&self) -> Self::Word;
+ fn o_entry(&self) -> Self::Word;
+ fn o_text_start(&self) -> Self::Word;
+ fn o_data_start(&self) -> Self::Word;
+ fn o_toc(&self) -> Self::Word;
+ fn o_snentry(&self) -> u16;
+ fn o_sntext(&self) -> u16;
+ fn o_sndata(&self) -> u16;
+ fn o_sntoc(&self) -> u16;
+ fn o_snloader(&self) -> u16;
+ fn o_snbss(&self) -> u16;
+ fn o_sntdata(&self) -> u16;
+ fn o_sntbss(&self) -> u16;
+ fn o_algntext(&self) -> u16;
+ fn o_algndata(&self) -> u16;
+ fn o_maxstack(&self) -> Self::Word;
+ fn o_maxdata(&self) -> Self::Word;
+ fn o_textpsize(&self) -> u8;
+ fn o_datapsize(&self) -> u8;
+ fn o_stackpsize(&self) -> u8;
+}
+
+impl AuxHeader for xcoff::AuxHeader32 {
+ type Word = u32;
+
+ fn o_vstamp(&self) -> u16 {
+ self.o_vstamp.get(BE)
+ }
+
+ fn o_tsize(&self) -> Self::Word {
+ self.o_tsize.get(BE)
+ }
+
+ fn o_dsize(&self) -> Self::Word {
+ self.o_dsize.get(BE)
+ }
+
+ fn o_bsize(&self) -> Self::Word {
+ self.o_bsize.get(BE)
+ }
+
+ fn o_entry(&self) -> Self::Word {
+ self.o_entry.get(BE)
+ }
+
+ fn o_text_start(&self) -> Self::Word {
+ self.o_text_start.get(BE)
+ }
+
+ fn o_data_start(&self) -> Self::Word {
+ self.o_data_start.get(BE)
+ }
+
+ fn o_toc(&self) -> Self::Word {
+ self.o_toc.get(BE)
+ }
+
+ fn o_snentry(&self) -> u16 {
+ self.o_snentry.get(BE)
+ }
+
+ fn o_sntext(&self) -> u16 {
+ self.o_sntext.get(BE)
+ }
+
+ fn o_sndata(&self) -> u16 {
+ self.o_sndata.get(BE)
+ }
+
+ fn o_sntoc(&self) -> u16 {
+ self.o_sntoc.get(BE)
+ }
+
+ fn o_snloader(&self) -> u16 {
+ self.o_snloader.get(BE)
+ }
+
+ fn o_snbss(&self) -> u16 {
+ self.o_snbss.get(BE)
+ }
+
+ fn o_sntdata(&self) -> u16 {
+ self.o_sntdata.get(BE)
+ }
+
+ fn o_sntbss(&self) -> u16 {
+ self.o_sntbss.get(BE)
+ }
+
+ fn o_algntext(&self) -> u16 {
+ self.o_algntext.get(BE)
+ }
+
+ fn o_algndata(&self) -> u16 {
+ self.o_algndata.get(BE)
+ }
+
+ fn o_maxstack(&self) -> Self::Word {
+ self.o_maxstack.get(BE)
+ }
+
+ fn o_maxdata(&self) -> Self::Word {
+ self.o_maxdata.get(BE)
+ }
+
+ fn o_textpsize(&self) -> u8 {
+ self.o_textpsize
+ }
+
+ fn o_datapsize(&self) -> u8 {
+ self.o_datapsize
+ }
+
+ fn o_stackpsize(&self) -> u8 {
+ self.o_stackpsize
+ }
+}
+
+impl AuxHeader for xcoff::AuxHeader64 {
+ type Word = u64;
+
+ fn o_vstamp(&self) -> u16 {
+ self.o_vstamp.get(BE)
+ }
+
+ fn o_tsize(&self) -> Self::Word {
+ self.o_tsize.get(BE)
+ }
+
+ fn o_dsize(&self) -> Self::Word {
+ self.o_dsize.get(BE)
+ }
+
+ fn o_bsize(&self) -> Self::Word {
+ self.o_bsize.get(BE)
+ }
+
+ fn o_entry(&self) -> Self::Word {
+ self.o_entry.get(BE)
+ }
+
+ fn o_text_start(&self) -> Self::Word {
+ self.o_text_start.get(BE)
+ }
+
+ fn o_data_start(&self) -> Self::Word {
+ self.o_data_start.get(BE)
+ }
+
+ fn o_toc(&self) -> Self::Word {
+ self.o_toc.get(BE)
+ }
+
+ fn o_snentry(&self) -> u16 {
+ self.o_snentry.get(BE)
+ }
+
+ fn o_sntext(&self) -> u16 {
+ self.o_sntext.get(BE)
+ }
+
+ fn o_sndata(&self) -> u16 {
+ self.o_sndata.get(BE)
+ }
+
+ fn o_sntoc(&self) -> u16 {
+ self.o_sntoc.get(BE)
+ }
+
+ fn o_snloader(&self) -> u16 {
+ self.o_snloader.get(BE)
+ }
+
+ fn o_snbss(&self) -> u16 {
+ self.o_snbss.get(BE)
+ }
+
+ fn o_sntdata(&self) -> u16 {
+ self.o_sntdata.get(BE)
+ }
+
+ fn o_sntbss(&self) -> u16 {
+ self.o_sntbss.get(BE)
+ }
+
+ fn o_algntext(&self) -> u16 {
+ self.o_algntext.get(BE)
+ }
+
+ fn o_algndata(&self) -> u16 {
+ self.o_algndata.get(BE)
+ }
+
+ fn o_maxstack(&self) -> Self::Word {
+ self.o_maxstack.get(BE)
+ }
+
+ fn o_maxdata(&self) -> Self::Word {
+ self.o_maxdata.get(BE)
+ }
+
+ fn o_textpsize(&self) -> u8 {
+ self.o_textpsize
+ }
+
+ fn o_datapsize(&self) -> u8 {
+ self.o_datapsize
+ }
+
+ fn o_stackpsize(&self) -> u8 {
+ self.o_stackpsize
+ }
+}
diff --git a/vendor/object/src/read/xcoff/mod.rs b/vendor/object/src/read/xcoff/mod.rs
new file mode 100644
index 000000000..136e31073
--- /dev/null
+++ b/vendor/object/src/read/xcoff/mod.rs
@@ -0,0 +1,21 @@
+//! Support for reading AIX XCOFF files.
+//!
+//! Provides `XcoffFile` and related types which implement the `Object` trait.
+
+mod file;
+pub use file::*;
+
+mod section;
+pub use section::*;
+
+mod symbol;
+pub use symbol::*;
+
+mod relocation;
+pub use relocation::*;
+
+mod comdat;
+pub use comdat::*;
+
+mod segment;
+pub use segment::*;
diff --git a/vendor/object/src/read/xcoff/relocation.rs b/vendor/object/src/read/xcoff/relocation.rs
new file mode 100644
index 000000000..8107a2e82
--- /dev/null
+++ b/vendor/object/src/read/xcoff/relocation.rs
@@ -0,0 +1,128 @@
+use alloc::fmt;
+use core::fmt::Debug;
+use core::slice;
+
+use crate::pod::Pod;
+use crate::{xcoff, BigEndian as BE, Relocation};
+
+use crate::read::{ReadRef, RelocationEncoding, RelocationKind, RelocationTarget, SymbolIndex};
+
+use super::{FileHeader, SectionHeader, XcoffFile};
+
+/// An iterator over the relocations in a `XcoffSection32`.
+pub type XcoffRelocationIterator32<'data, 'file, R = &'data [u8]> =
+ XcoffRelocationIterator<'data, 'file, xcoff::FileHeader32, R>;
+/// An iterator over the relocations in a `XcoffSection64`.
+pub type XcoffRelocationIterator64<'data, 'file, R = &'data [u8]> =
+ XcoffRelocationIterator<'data, 'file, xcoff::FileHeader64, R>;
+
+/// An iterator over the relocations in a `XcoffSection`.
+pub struct XcoffRelocationIterator<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ 'data: 'file,
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ #[allow(unused)]
+ pub(super) file: &'file XcoffFile<'data, Xcoff, R>,
+ pub(super) relocations:
+ slice::Iter<'data, <<Xcoff as FileHeader>::SectionHeader as SectionHeader>::Rel>,
+}
+
+impl<'data, 'file, Xcoff, R> Iterator for XcoffRelocationIterator<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ type Item = (u64, Relocation);
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.relocations.next().map(|relocation| {
+ let encoding = RelocationEncoding::Generic;
+ let (kind, addend) = match relocation.r_rtype() {
+ xcoff::R_POS
+ | xcoff::R_RL
+ | xcoff::R_RLA
+ | xcoff::R_BA
+ | xcoff::R_RBA
+ | xcoff::R_TLS => (RelocationKind::Absolute, 0),
+ xcoff::R_REL | xcoff::R_BR | xcoff::R_RBR => (RelocationKind::Relative, -4),
+ xcoff::R_TOC | xcoff::R_TOCL | xcoff::R_TOCU => (RelocationKind::Got, 0),
+ r_type => (RelocationKind::Xcoff(r_type), 0),
+ };
+ let size = (relocation.r_rsize() & 0x3F) + 1;
+ let target = RelocationTarget::Symbol(SymbolIndex(relocation.r_symndx() as usize));
+ (
+ relocation.r_vaddr().into(),
+ Relocation {
+ kind,
+ encoding,
+ size,
+ target,
+ addend,
+ implicit_addend: true,
+ },
+ )
+ })
+ }
+}
+
+impl<'data, 'file, Xcoff, R> fmt::Debug for XcoffRelocationIterator<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("XcoffRelocationIterator").finish()
+ }
+}
+
+/// A trait for generic access to `Rel32` and `Rel64`.
+#[allow(missing_docs)]
+pub trait Rel: Debug + Pod {
+ type Word: Into<u64>;
+ fn r_vaddr(&self) -> Self::Word;
+ fn r_symndx(&self) -> u32;
+ fn r_rsize(&self) -> u8;
+ fn r_rtype(&self) -> u8;
+}
+
+impl Rel for xcoff::Rel32 {
+ type Word = u32;
+
+ fn r_vaddr(&self) -> Self::Word {
+ self.r_vaddr.get(BE)
+ }
+
+ fn r_symndx(&self) -> u32 {
+ self.r_symndx.get(BE)
+ }
+
+ fn r_rsize(&self) -> u8 {
+ self.r_rsize
+ }
+
+ fn r_rtype(&self) -> u8 {
+ self.r_rtype
+ }
+}
+
+impl Rel for xcoff::Rel64 {
+ type Word = u64;
+
+ fn r_vaddr(&self) -> Self::Word {
+ self.r_vaddr.get(BE)
+ }
+
+ fn r_symndx(&self) -> u32 {
+ self.r_symndx.get(BE)
+ }
+
+ fn r_rsize(&self) -> u8 {
+ self.r_rsize
+ }
+
+ fn r_rtype(&self) -> u8 {
+ self.r_rtype
+ }
+}
diff --git a/vendor/object/src/read/xcoff/section.rs b/vendor/object/src/read/xcoff/section.rs
new file mode 100644
index 000000000..0944e10c8
--- /dev/null
+++ b/vendor/object/src/read/xcoff/section.rs
@@ -0,0 +1,426 @@
+use core::fmt::Debug;
+use core::{iter, result, slice, str};
+
+use crate::{
+ xcoff, BigEndian as BE, CompressedData, CompressedFileRange, Pod, SectionFlags, SectionKind,
+};
+
+use crate::read::{self, Error, ObjectSection, ReadError, ReadRef, Result, SectionIndex};
+
+use super::{AuxHeader, FileHeader, Rel, XcoffFile, XcoffRelocationIterator};
+
+/// An iterator over the sections of an `XcoffFile32`.
+pub type XcoffSectionIterator32<'data, 'file, R = &'data [u8]> =
+ XcoffSectionIterator<'data, 'file, xcoff::FileHeader32, R>;
+/// An iterator over the sections of an `XcoffFile64`.
+pub type XcoffSectionIterator64<'data, 'file, R = &'data [u8]> =
+ XcoffSectionIterator<'data, 'file, xcoff::FileHeader64, R>;
+
+/// An iterator over the sections of an `XcoffFile`.
+#[derive(Debug)]
+pub struct XcoffSectionIterator<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ pub(super) file: &'file XcoffFile<'data, Xcoff, R>,
+ pub(super) iter: iter::Enumerate<slice::Iter<'data, Xcoff::SectionHeader>>,
+}
+
+impl<'data, 'file, Xcoff, R> Iterator for XcoffSectionIterator<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ type Item = XcoffSection<'data, 'file, Xcoff, R>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ self.iter.next().map(|(index, section)| XcoffSection {
+ index: SectionIndex(index),
+ file: self.file,
+ section,
+ })
+ }
+}
+
+/// A section of an `XcoffFile32`.
+pub type XcoffSection32<'data, 'file, R = &'data [u8]> =
+ XcoffSection<'data, 'file, xcoff::FileHeader32, R>;
+/// A section of an `XcoffFile64`.
+pub type XcoffSection64<'data, 'file, R = &'data [u8]> =
+ XcoffSection<'data, 'file, xcoff::FileHeader64, R>;
+
+/// A section of an `XcoffFile`.
+#[derive(Debug)]
+pub struct XcoffSection<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ 'data: 'file,
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ pub(super) file: &'file XcoffFile<'data, Xcoff, R>,
+ pub(super) section: &'data Xcoff::SectionHeader,
+ pub(super) index: SectionIndex,
+}
+
+impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> XcoffSection<'data, 'file, Xcoff, R> {
+ fn bytes(&self) -> Result<&'data [u8]> {
+ self.section
+ .data(self.file.data)
+ .read_error("Invalid XCOFF section offset or size")
+ }
+}
+
+impl<'data, 'file, Xcoff, R> read::private::Sealed for XcoffSection<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+}
+
+impl<'data, 'file, Xcoff, R> ObjectSection<'data> for XcoffSection<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ type RelocationIterator = XcoffRelocationIterator<'data, 'file, Xcoff, R>;
+
+ fn index(&self) -> SectionIndex {
+ self.index
+ }
+
+ fn address(&self) -> u64 {
+ self.section.s_paddr().into()
+ }
+
+ fn size(&self) -> u64 {
+ self.section.s_size().into()
+ }
+
+ fn align(&self) -> u64 {
+ // The default section alignment is 4.
+ if let Some(aux_header) = self.file.aux_header {
+ match self.kind() {
+ SectionKind::Text => aux_header.o_algntext().into(),
+ SectionKind::Data => aux_header.o_algndata().into(),
+ _ => 4,
+ }
+ } else {
+ 4
+ }
+ }
+
+ fn file_range(&self) -> Option<(u64, u64)> {
+ self.section.file_range()
+ }
+
+ fn data(&self) -> Result<&'data [u8]> {
+ self.bytes()
+ }
+
+ fn data_range(&self, address: u64, size: u64) -> Result<Option<&'data [u8]>> {
+ Ok(read::util::data_range(
+ self.bytes()?,
+ self.address(),
+ address,
+ size,
+ ))
+ }
+
+ fn compressed_file_range(&self) -> Result<CompressedFileRange> {
+ Ok(CompressedFileRange::none(self.file_range()))
+ }
+
+ fn compressed_data(&self) -> Result<CompressedData<'data>> {
+ self.data().map(CompressedData::none)
+ }
+
+ fn name_bytes(&self) -> read::Result<&[u8]> {
+ Ok(self.section.name())
+ }
+
+ fn name(&self) -> read::Result<&str> {
+ let name = self.name_bytes()?;
+ str::from_utf8(name)
+ .ok()
+ .read_error("Non UTF-8 XCOFF section name")
+ }
+
+ fn segment_name_bytes(&self) -> Result<Option<&[u8]>> {
+ Ok(None)
+ }
+
+ fn segment_name(&self) -> Result<Option<&str>> {
+ Ok(None)
+ }
+
+ fn kind(&self) -> SectionKind {
+ let section_type = self.section.s_flags() as u16;
+ if section_type & xcoff::STYP_TEXT != 0 {
+ SectionKind::Text
+ } else if section_type & xcoff::STYP_DATA != 0 {
+ SectionKind::Data
+ } else if section_type & xcoff::STYP_TDATA != 0 {
+ SectionKind::Tls
+ } else if section_type & xcoff::STYP_BSS != 0 {
+ SectionKind::UninitializedData
+ } else if section_type & xcoff::STYP_TBSS != 0 {
+ SectionKind::UninitializedTls
+ } else if section_type & (xcoff::STYP_DEBUG | xcoff::STYP_DWARF) != 0 {
+ SectionKind::Debug
+ } else if section_type & (xcoff::STYP_LOADER | xcoff::STYP_OVRFLO) != 0 {
+ SectionKind::Metadata
+ } else if section_type
+ & (xcoff::STYP_INFO | xcoff::STYP_EXCEPT | xcoff::STYP_PAD | xcoff::STYP_TYPCHK)
+ != 0
+ {
+ SectionKind::Other
+ } else {
+ SectionKind::Unknown
+ }
+ }
+
+ fn relocations(&self) -> Self::RelocationIterator {
+ let rel = self.section.relocations(self.file.data).unwrap_or(&[]);
+ XcoffRelocationIterator {
+ file: self.file,
+ relocations: rel.iter(),
+ }
+ }
+
+ fn flags(&self) -> SectionFlags {
+ SectionFlags::Xcoff {
+ s_flags: self.section.s_flags(),
+ }
+ }
+
+ fn uncompressed_data(&self) -> Result<alloc::borrow::Cow<'data, [u8]>> {
+ self.compressed_data()?.decompress()
+ }
+}
+
+/// The table of section headers in an XCOFF file.
+#[derive(Debug, Clone, Copy)]
+pub struct SectionTable<'data, Xcoff: FileHeader> {
+ sections: &'data [Xcoff::SectionHeader],
+}
+
+impl<'data, Xcoff> Default for SectionTable<'data, Xcoff>
+where
+ Xcoff: FileHeader,
+{
+ fn default() -> Self {
+ Self { sections: &[] }
+ }
+}
+
+impl<'data, Xcoff> SectionTable<'data, Xcoff>
+where
+ Xcoff: FileHeader,
+{
+ /// Parse the section table.
+ ///
+ /// `data` must be the entire file data.
+ /// `offset` must be after the optional file header.
+ pub fn parse<R: ReadRef<'data>>(header: &Xcoff, data: R, offset: &mut u64) -> Result<Self> {
+ let section_num = header.f_nscns();
+ if section_num == 0 {
+ return Ok(SectionTable::default());
+ }
+ let sections = data
+ .read_slice(offset, section_num as usize)
+ .read_error("Invalid XCOFF section headers")?;
+ Ok(SectionTable { sections })
+ }
+
+ /// Iterate over the section headers.
+ #[inline]
+ pub fn iter(&self) -> slice::Iter<'data, Xcoff::SectionHeader> {
+ self.sections.iter()
+ }
+
+ /// Return true if the section table is empty.
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.sections.is_empty()
+ }
+
+ /// The number of section headers.
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.sections.len()
+ }
+
+ /// Return the section header at the given index.
+ pub fn section(&self, index: SectionIndex) -> read::Result<&'data Xcoff::SectionHeader> {
+ self.sections
+ .get(index.0)
+ .read_error("Invalid XCOFF section index")
+ }
+}
+
+/// A trait for generic access to `SectionHeader32` and `SectionHeader64`.
+#[allow(missing_docs)]
+pub trait SectionHeader: Debug + Pod {
+ type Word: Into<u64>;
+ type HalfWord: Into<u32>;
+ type Xcoff: FileHeader<SectionHeader = Self, Word = Self::Word>;
+ type Rel: Rel<Word = Self::Word>;
+
+ fn s_name(&self) -> &[u8; 8];
+ fn s_paddr(&self) -> Self::Word;
+ fn s_vaddr(&self) -> Self::Word;
+ fn s_size(&self) -> Self::Word;
+ fn s_scnptr(&self) -> Self::Word;
+ fn s_relptr(&self) -> Self::Word;
+ fn s_lnnoptr(&self) -> Self::Word;
+ fn s_nreloc(&self) -> Self::HalfWord;
+ fn s_nlnno(&self) -> Self::HalfWord;
+ fn s_flags(&self) -> u32;
+
+ /// Return the section name.
+ fn name(&self) -> &[u8] {
+ let sectname = &self.s_name()[..];
+ match memchr::memchr(b'\0', sectname) {
+ Some(end) => &sectname[..end],
+ None => sectname,
+ }
+ }
+
+ /// Return the offset and size of the section in the file.
+ fn file_range(&self) -> Option<(u64, u64)> {
+ Some((self.s_scnptr().into(), self.s_size().into()))
+ }
+
+ /// Return the section data.
+ ///
+ /// Returns `Ok(&[])` if the section has no data.
+ /// Returns `Err` for invalid values.
+ fn data<'data, R: ReadRef<'data>>(&self, data: R) -> result::Result<&'data [u8], ()> {
+ if let Some((offset, size)) = self.file_range() {
+ data.read_bytes_at(offset, size)
+ } else {
+ Ok(&[])
+ }
+ }
+
+ /// Read the relocations.
+ fn relocations<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<&'data [Self::Rel]>;
+}
+
+impl SectionHeader for xcoff::SectionHeader32 {
+ type Word = u32;
+ type HalfWord = u16;
+ type Xcoff = xcoff::FileHeader32;
+ type Rel = xcoff::Rel32;
+
+ fn s_name(&self) -> &[u8; 8] {
+ &self.s_name
+ }
+
+ fn s_paddr(&self) -> Self::Word {
+ self.s_paddr.get(BE)
+ }
+
+ fn s_vaddr(&self) -> Self::Word {
+ self.s_vaddr.get(BE)
+ }
+
+ fn s_size(&self) -> Self::Word {
+ self.s_size.get(BE)
+ }
+
+ fn s_scnptr(&self) -> Self::Word {
+ self.s_scnptr.get(BE)
+ }
+
+ fn s_relptr(&self) -> Self::Word {
+ self.s_relptr.get(BE)
+ }
+
+ fn s_lnnoptr(&self) -> Self::Word {
+ self.s_lnnoptr.get(BE)
+ }
+
+ fn s_nreloc(&self) -> Self::HalfWord {
+ self.s_nreloc.get(BE)
+ }
+
+ fn s_nlnno(&self) -> Self::HalfWord {
+ self.s_nlnno.get(BE)
+ }
+
+ fn s_flags(&self) -> u32 {
+ self.s_flags.get(BE)
+ }
+
+ /// Read the relocations in a XCOFF32 file.
+ ///
+ /// `data` must be the entire file data.
+ fn relocations<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<&'data [Self::Rel]> {
+ let reloc_num = self.s_nreloc() as usize;
+ // TODO: If more than 65,534 relocation entries are required, the field value will be 65535,
+ // 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."));
+ }
+ data.read_slice_at(self.s_relptr().into(), reloc_num)
+ .read_error("Invalid XCOFF relocation offset or number")
+ }
+}
+
+impl SectionHeader for xcoff::SectionHeader64 {
+ type Word = u64;
+ type HalfWord = u32;
+ type Xcoff = xcoff::FileHeader64;
+ type Rel = xcoff::Rel64;
+
+ fn s_name(&self) -> &[u8; 8] {
+ &self.s_name
+ }
+
+ fn s_paddr(&self) -> Self::Word {
+ self.s_paddr.get(BE)
+ }
+
+ fn s_vaddr(&self) -> Self::Word {
+ self.s_vaddr.get(BE)
+ }
+
+ fn s_size(&self) -> Self::Word {
+ self.s_size.get(BE)
+ }
+
+ fn s_scnptr(&self) -> Self::Word {
+ self.s_scnptr.get(BE)
+ }
+
+ fn s_relptr(&self) -> Self::Word {
+ self.s_relptr.get(BE)
+ }
+
+ fn s_lnnoptr(&self) -> Self::Word {
+ self.s_lnnoptr.get(BE)
+ }
+
+ fn s_nreloc(&self) -> Self::HalfWord {
+ self.s_nreloc.get(BE)
+ }
+
+ fn s_nlnno(&self) -> Self::HalfWord {
+ self.s_nlnno.get(BE)
+ }
+
+ fn s_flags(&self) -> u32 {
+ self.s_flags.get(BE)
+ }
+
+ /// Read the relocations in a XCOFF64 file.
+ ///
+ /// `data` must be the entire file data.
+ fn relocations<'data, R: ReadRef<'data>>(&self, data: R) -> read::Result<&'data [Self::Rel]> {
+ data.read_slice_at(self.s_relptr(), self.s_nreloc() as usize)
+ .read_error("Invalid XCOFF relocation offset or number")
+ }
+}
diff --git a/vendor/object/src/read/xcoff/segment.rs b/vendor/object/src/read/xcoff/segment.rs
new file mode 100644
index 000000000..49969438d
--- /dev/null
+++ b/vendor/object/src/read/xcoff/segment.rs
@@ -0,0 +1,115 @@
+//! TODO: Support the segment for XCOFF when auxiliary file header and loader section is ready.
+
+use core::fmt::Debug;
+use core::str;
+
+use crate::read::{self, ObjectSegment, ReadRef, Result};
+use crate::xcoff;
+
+use super::{FileHeader, XcoffFile};
+
+/// An iterator over the segments of an `XcoffFile32`.
+pub type XcoffSegmentIterator32<'data, 'file, R = &'data [u8]> =
+ XcoffSegmentIterator<'data, 'file, xcoff::FileHeader32, R>;
+/// An iterator over the segments of an `XcoffFile64`.
+pub type XcoffSegmentIterator64<'data, 'file, R = &'data [u8]> =
+ XcoffSegmentIterator<'data, 'file, xcoff::FileHeader64, R>;
+
+/// An iterator over the segments of an `XcoffFile`.
+#[derive(Debug)]
+pub struct XcoffSegmentIterator<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ 'data: 'file,
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ #[allow(unused)]
+ pub(super) file: &'file XcoffFile<'data, Xcoff, R>,
+}
+
+impl<'data, 'file, Xcoff, R> Iterator for XcoffSegmentIterator<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ type Item = XcoffSegment<'data, 'file, Xcoff, R>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ None
+ }
+}
+
+/// A segment of an `XcoffFile32`.
+pub type XcoffSegment32<'data, 'file, R = &'data [u8]> =
+ XcoffSegment<'data, 'file, xcoff::FileHeader32, R>;
+/// A segment of an `XcoffFile64`.
+pub type XcoffSegment64<'data, 'file, R = &'data [u8]> =
+ XcoffSegment<'data, 'file, xcoff::FileHeader64, R>;
+
+/// A loadable section of an `XcoffFile`.
+#[derive(Debug)]
+pub struct XcoffSegment<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ 'data: 'file,
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ #[allow(unused)]
+ pub(super) file: &'file XcoffFile<'data, Xcoff, R>,
+}
+
+impl<'data, 'file, Xcoff, R> XcoffSegment<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+}
+
+impl<'data, 'file, Xcoff, R> read::private::Sealed for XcoffSegment<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+}
+
+impl<'data, 'file, Xcoff, R> ObjectSegment<'data> for XcoffSegment<'data, 'file, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ fn address(&self) -> u64 {
+ unreachable!();
+ }
+
+ fn size(&self) -> u64 {
+ unreachable!();
+ }
+
+ fn align(&self) -> u64 {
+ unreachable!();
+ }
+
+ fn file_range(&self) -> (u64, u64) {
+ unreachable!();
+ }
+
+ fn data(&self) -> Result<&'data [u8]> {
+ unreachable!();
+ }
+
+ fn data_range(&self, _address: u64, _size: u64) -> Result<Option<&'data [u8]>> {
+ unreachable!();
+ }
+
+ fn name_bytes(&self) -> Result<Option<&[u8]>> {
+ unreachable!();
+ }
+
+ fn name(&self) -> Result<Option<&str>> {
+ unreachable!();
+ }
+
+ fn flags(&self) -> crate::SegmentFlags {
+ unreachable!();
+ }
+}
diff --git a/vendor/object/src/read/xcoff/symbol.rs b/vendor/object/src/read/xcoff/symbol.rs
new file mode 100644
index 000000000..6738ad171
--- /dev/null
+++ b/vendor/object/src/read/xcoff/symbol.rs
@@ -0,0 +1,634 @@
+use alloc::fmt;
+use core::convert::TryInto;
+use core::fmt::Debug;
+use core::marker::PhantomData;
+use core::str;
+
+use crate::endian::{BigEndian as BE, U32Bytes};
+use crate::pod::Pod;
+use crate::read::util::StringTable;
+use crate::{bytes_of, xcoff, Object, ObjectSection, SectionKind};
+
+use crate::read::{
+ self, Bytes, Error, ObjectSymbol, ObjectSymbolTable, ReadError, ReadRef, Result, SectionIndex,
+ SymbolFlags, SymbolIndex, SymbolKind, SymbolScope, SymbolSection,
+};
+
+use super::{FileHeader, XcoffFile};
+
+/// A table of symbol entries in an XCOFF file.
+///
+/// Also includes the string table used for the symbol names.
+#[derive(Debug)]
+pub struct SymbolTable<'data, Xcoff, R = &'data [u8]>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ symbols: &'data [xcoff::SymbolBytes],
+ strings: StringTable<'data, R>,
+ header: PhantomData<Xcoff>,
+}
+
+impl<'data, Xcoff, R> Default for SymbolTable<'data, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ fn default() -> Self {
+ Self {
+ symbols: &[],
+ strings: StringTable::default(),
+ header: PhantomData,
+ }
+ }
+}
+
+impl<'data, Xcoff, R> SymbolTable<'data, Xcoff, R>
+where
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ /// Parse the symbol table.
+ pub fn parse(header: Xcoff, data: R) -> Result<Self> {
+ let mut offset = header.f_symptr().into();
+ let (symbols, strings) = if offset != 0 {
+ let symbols = data
+ .read_slice(&mut offset, header.f_nsyms() as usize)
+ .read_error("Invalid XCOFF symbol table offset or size")?;
+
+ // Parse the string table.
+ // Note: don't update data when reading length; the length includes itself.
+ let length = data
+ .read_at::<U32Bytes<_>>(offset)
+ .read_error("Missing XCOFF string table")?
+ .get(BE);
+ let str_end = offset
+ .checked_add(length as u64)
+ .read_error("Invalid XCOFF string table length")?;
+ let strings = StringTable::new(data, offset, str_end);
+
+ (symbols, strings)
+ } else {
+ (&[][..], StringTable::default())
+ };
+
+ Ok(SymbolTable {
+ symbols,
+ strings,
+ header: PhantomData,
+ })
+ }
+
+ /// Return the symbol entry at the given index and offset.
+ pub fn get<T: Pod>(&self, index: usize, offset: usize) -> Result<&'data T> {
+ let entry = index
+ .checked_add(offset)
+ .and_then(|x| self.symbols.get(x))
+ .read_error("Invalid XCOFF symbol index")?;
+ let bytes = bytes_of(entry);
+ Bytes(bytes).read().read_error("Invalid XCOFF symbol data")
+ }
+
+ /// Return the symbol at the given index.
+ pub fn symbol(&self, index: usize) -> Result<&'data Xcoff::Symbol> {
+ self.get::<Xcoff::Symbol>(index, 0)
+ }
+
+ /// Return the file auxiliary symbol.
+ pub fn aux_file(&self, index: usize) -> Result<&'data Xcoff::FileAux> {
+ debug_assert!(self.symbol(index)?.has_aux_file());
+ let aux_file = self.get::<Xcoff::FileAux>(index, 1)?;
+ if let Some(aux_type) = aux_file.x_auxtype() {
+ if aux_type != xcoff::AUX_FILE {
+ return Err(Error("Invalid index for file auxiliary symbol."));
+ }
+ }
+ Ok(aux_file)
+ }
+
+ /// Return the csect auxiliary symbol.
+ pub fn aux_csect(&self, index: usize, offset: usize) -> Result<&'data Xcoff::CsectAux> {
+ debug_assert!(self.symbol(index)?.has_aux_csect());
+ let aux_csect = self.get::<Xcoff::CsectAux>(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."));
+ }
+ }
+ Ok(aux_csect)
+ }
+
+ /// Return true if the symbol table is empty.
+ #[inline]
+ pub fn is_empty(&self) -> bool {
+ self.symbols.is_empty()
+ }
+
+ /// The number of symbol table entries.
+ ///
+ /// This includes auxiliary symbol table entries.
+ #[inline]
+ pub fn len(&self) -> usize {
+ self.symbols.len()
+ }
+}
+
+/// A symbol table of an `XcoffFile32`.
+pub type XcoffSymbolTable32<'data, 'file, R = &'data [u8]> =
+ XcoffSymbolTable<'data, 'file, xcoff::FileHeader32, R>;
+/// A symbol table of an `XcoffFile64`.
+pub type XcoffSymbolTable64<'data, 'file, R = &'data [u8]> =
+ XcoffSymbolTable<'data, 'file, xcoff::FileHeader64, R>;
+
+/// A symbol table of an `XcoffFile`.
+#[derive(Debug, Clone, Copy)]
+pub struct XcoffSymbolTable<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ 'data: 'file,
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ pub(crate) file: &'file XcoffFile<'data, Xcoff, R>,
+ pub(super) symbols: &'file SymbolTable<'data, Xcoff, R>,
+}
+
+impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> read::private::Sealed
+ for XcoffSymbolTable<'data, 'file, Xcoff, R>
+{
+}
+
+impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> ObjectSymbolTable<'data>
+ for XcoffSymbolTable<'data, 'file, Xcoff, R>
+{
+ type Symbol = XcoffSymbol<'data, 'file, Xcoff, R>;
+ type SymbolIterator = XcoffSymbolIterator<'data, 'file, Xcoff, R>;
+
+ fn symbols(&self) -> Self::SymbolIterator {
+ XcoffSymbolIterator {
+ file: self.file,
+ symbols: self.symbols,
+ index: 0,
+ }
+ }
+
+ fn symbol_by_index(&self, index: SymbolIndex) -> read::Result<Self::Symbol> {
+ let symbol = self.symbols.symbol(index.0)?;
+ Ok(XcoffSymbol {
+ file: self.file,
+ symbols: self.symbols,
+ index,
+ symbol,
+ })
+ }
+}
+
+/// An iterator over the symbols of an `XcoffFile32`.
+pub type XcoffSymbolIterator32<'data, 'file, R = &'data [u8]> =
+ XcoffSymbolIterator<'data, 'file, xcoff::FileHeader32, R>;
+/// An iterator over the symbols of an `XcoffFile64`.
+pub type XcoffSymbolIterator64<'data, 'file, R = &'data [u8]> =
+ XcoffSymbolIterator<'data, 'file, xcoff::FileHeader64, R>;
+
+/// An iterator over the symbols of an `XcoffFile`.
+pub struct XcoffSymbolIterator<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ 'data: 'file,
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ pub(crate) file: &'file XcoffFile<'data, Xcoff, R>,
+ pub(super) symbols: &'file SymbolTable<'data, Xcoff, R>,
+ pub(super) index: usize,
+}
+
+impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> fmt::Debug
+ for XcoffSymbolIterator<'data, 'file, Xcoff, R>
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ f.debug_struct("XcoffSymbolIterator").finish()
+ }
+}
+
+impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> Iterator
+ for XcoffSymbolIterator<'data, 'file, Xcoff, R>
+{
+ type Item = XcoffSymbol<'data, 'file, Xcoff, R>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let index = self.index;
+ let symbol = self.symbols.symbol(index).ok()?;
+ // TODO: skip over the auxiliary symbols for now.
+ self.index += 1 + symbol.n_numaux() as usize;
+ Some(XcoffSymbol {
+ file: self.file,
+ symbols: self.symbols,
+ index: SymbolIndex(index),
+ symbol,
+ })
+ }
+}
+
+/// A symbol of an `XcoffFile32`.
+pub type XcoffSymbol32<'data, 'file, R = &'data [u8]> =
+ XcoffSymbol<'data, 'file, xcoff::FileHeader32, R>;
+/// A symbol of an `XcoffFile64`.
+pub type XcoffSymbol64<'data, 'file, R = &'data [u8]> =
+ XcoffSymbol<'data, 'file, xcoff::FileHeader64, R>;
+
+/// A symbol of an `XcoffFile`.
+#[derive(Debug, Clone, Copy)]
+pub struct XcoffSymbol<'data, 'file, Xcoff, R = &'data [u8]>
+where
+ 'data: 'file,
+ Xcoff: FileHeader,
+ R: ReadRef<'data>,
+{
+ pub(crate) file: &'file XcoffFile<'data, Xcoff, R>,
+ pub(super) symbols: &'file SymbolTable<'data, Xcoff, R>,
+ pub(super) index: SymbolIndex,
+ pub(super) symbol: &'data Xcoff::Symbol,
+}
+
+impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> read::private::Sealed
+ for XcoffSymbol<'data, 'file, Xcoff, R>
+{
+}
+
+impl<'data, 'file, Xcoff: FileHeader, R: ReadRef<'data>> ObjectSymbol<'data>
+ for XcoffSymbol<'data, 'file, Xcoff, R>
+{
+ #[inline]
+ fn index(&self) -> SymbolIndex {
+ self.index
+ }
+
+ fn name_bytes(&self) -> Result<&'data [u8]> {
+ self.symbol.name(self.symbols.strings)
+ }
+
+ fn name(&self) -> Result<&'data str> {
+ let name = self.name_bytes()?;
+ str::from_utf8(name)
+ .ok()
+ .read_error("Non UTF-8 XCOFF symbol name")
+ }
+
+ #[inline]
+ fn address(&self) -> u64 {
+ match self.symbol.n_sclass() {
+ // Relocatable address.
+ xcoff::C_EXT
+ | xcoff::C_WEAKEXT
+ | xcoff::C_HIDEXT
+ | xcoff::C_FCN
+ | xcoff::C_BLOCK
+ | xcoff::C_STAT => self.symbol.n_value().into(),
+ _ => 0,
+ }
+ }
+
+ #[inline]
+ fn size(&self) -> u64 {
+ if self.symbol.has_aux_csect() {
+ // XCOFF32 must have the csect auxiliary entry as the last auxiliary entry.
+ // XCOFF64 doesn't require this, but conventionally does.
+ if let Ok(aux_csect) = self
+ .file
+ .symbols
+ .aux_csect(self.index.0, self.symbol.n_numaux() as usize)
+ {
+ let sym_type = aux_csect.sym_type() & 0x07;
+ if sym_type == xcoff::XTY_SD || sym_type == xcoff::XTY_CM {
+ aux_csect.x_scnlen()
+ } else {
+ 0
+ }
+ } else {
+ 0
+ }
+ } else {
+ 0
+ }
+ }
+
+ fn kind(&self) -> SymbolKind {
+ match self.symbol.n_sclass() {
+ xcoff::C_FILE => SymbolKind::File,
+ xcoff::C_NULL => SymbolKind::Null,
+ _ => self
+ .file
+ .section_by_index(SectionIndex((self.symbol.n_scnum() - 1) as usize))
+ .map(|section| match section.kind() {
+ SectionKind::Data | SectionKind::UninitializedData => SymbolKind::Data,
+ SectionKind::UninitializedTls | SectionKind::Tls => SymbolKind::Tls,
+ SectionKind::Text => SymbolKind::Text,
+ _ => SymbolKind::Unknown,
+ })
+ .unwrap_or(SymbolKind::Unknown),
+ }
+ }
+
+ fn section(&self) -> SymbolSection {
+ match self.symbol.n_scnum() {
+ xcoff::N_ABS => SymbolSection::Absolute,
+ xcoff::N_UNDEF => SymbolSection::Undefined,
+ xcoff::N_DEBUG => SymbolSection::None,
+ index if index > 0 => SymbolSection::Section(SectionIndex(index as usize)),
+ _ => SymbolSection::Unknown,
+ }
+ }
+
+ #[inline]
+ fn is_undefined(&self) -> bool {
+ self.symbol.is_undefined()
+ }
+
+ /// Return true if the symbol is a definition of a function or data object.
+ #[inline]
+ fn is_definition(&self) -> bool {
+ if self.symbol.has_aux_csect() {
+ if let Ok(aux_csect) = self
+ .symbols
+ .aux_csect(self.index.0, self.symbol.n_numaux() as usize)
+ {
+ let smclas = aux_csect.x_smclas();
+ self.symbol.n_scnum() != xcoff::N_UNDEF
+ && (smclas == xcoff::XMC_PR
+ || smclas == xcoff::XMC_RW
+ || smclas == xcoff::XMC_RO)
+ } else {
+ false
+ }
+ } else {
+ false
+ }
+ }
+
+ #[inline]
+ fn is_common(&self) -> bool {
+ self.symbol.n_sclass() == xcoff::C_EXT && self.symbol.n_scnum() == xcoff::N_UNDEF
+ }
+
+ #[inline]
+ fn is_weak(&self) -> bool {
+ self.symbol.n_sclass() == xcoff::C_WEAKEXT
+ }
+
+ fn scope(&self) -> SymbolScope {
+ if self.symbol.n_scnum() == xcoff::N_UNDEF {
+ SymbolScope::Unknown
+ } else {
+ match self.symbol.n_sclass() {
+ xcoff::C_EXT | xcoff::C_WEAKEXT | xcoff::C_HIDEXT => {
+ let visibility = self.symbol.n_type() & xcoff::SYM_V_MASK;
+ if visibility == xcoff::SYM_V_HIDDEN {
+ SymbolScope::Linkage
+ } else {
+ SymbolScope::Dynamic
+ }
+ }
+ _ => SymbolScope::Compilation,
+ }
+ }
+ }
+
+ #[inline]
+ fn is_global(&self) -> bool {
+ match self.symbol.n_sclass() {
+ xcoff::C_EXT | xcoff::C_WEAKEXT => true,
+ _ => false,
+ }
+ }
+
+ #[inline]
+ fn is_local(&self) -> bool {
+ !self.is_global()
+ }
+
+ #[inline]
+ fn flags(&self) -> SymbolFlags<SectionIndex> {
+ SymbolFlags::None
+ }
+}
+
+/// A trait for generic access to `Symbol32` and `Symbol64`.
+#[allow(missing_docs)]
+pub trait Symbol: Debug + Pod {
+ type Word: Into<u64>;
+
+ fn n_value(&self) -> Self::Word;
+ fn n_scnum(&self) -> i16;
+ fn n_type(&self) -> u16;
+ fn n_sclass(&self) -> u8;
+ fn n_numaux(&self) -> u8;
+
+ fn name<'data, R: ReadRef<'data>>(
+ &'data self,
+ strings: StringTable<'data, R>,
+ ) -> Result<&'data [u8]>;
+
+ /// Return true if the symbol is undefined.
+ #[inline]
+ fn is_undefined(&self) -> bool {
+ let n_sclass = self.n_sclass();
+ (n_sclass == xcoff::C_EXT || n_sclass == xcoff::C_WEAKEXT)
+ && self.n_scnum() == xcoff::N_UNDEF
+ }
+
+ /// Return true if the symbol has file auxiliary entry.
+ fn has_aux_file(&self) -> bool {
+ self.n_numaux() > 0 && self.n_sclass() == xcoff::C_FILE
+ }
+
+ /// Return true if the symbol has csect auxiliary entry.
+ ///
+ /// A csect auxiliary entry is required for each symbol table entry that has
+ /// a storage class value of C_EXT, C_WEAKEXT, or C_HIDEXT.
+ fn has_aux_csect(&self) -> bool {
+ let sclass = self.n_sclass();
+ self.n_numaux() > 0
+ && (sclass == xcoff::C_EXT || sclass == xcoff::C_WEAKEXT || sclass == xcoff::C_HIDEXT)
+ }
+}
+
+impl Symbol for xcoff::Symbol64 {
+ type Word = u64;
+
+ fn n_value(&self) -> Self::Word {
+ self.n_value.get(BE)
+ }
+
+ fn n_scnum(&self) -> i16 {
+ self.n_scnum.get(BE)
+ }
+
+ fn n_type(&self) -> u16 {
+ self.n_type.get(BE)
+ }
+
+ fn n_sclass(&self) -> u8 {
+ self.n_sclass
+ }
+
+ fn n_numaux(&self) -> u8 {
+ self.n_numaux
+ }
+
+ /// Parse the symbol name for XCOFF64.
+ fn name<'data, R: ReadRef<'data>>(
+ &'data self,
+ strings: StringTable<'data, R>,
+ ) -> Result<&'data [u8]> {
+ strings
+ .get(self.n_offset.get(BE))
+ .read_error("Invalid XCOFF symbol name offset")
+ }
+}
+
+impl Symbol for xcoff::Symbol32 {
+ type Word = u32;
+
+ fn n_value(&self) -> Self::Word {
+ self.n_value.get(BE)
+ }
+
+ fn n_scnum(&self) -> i16 {
+ self.n_scnum.get(BE)
+ }
+
+ fn n_type(&self) -> u16 {
+ self.n_type.get(BE)
+ }
+
+ fn n_sclass(&self) -> u8 {
+ self.n_sclass
+ }
+
+ fn n_numaux(&self) -> u8 {
+ self.n_numaux
+ }
+
+ /// Parse the symbol name for XCOFF32.
+ fn name<'data, R: ReadRef<'data>>(
+ &'data self,
+ strings: StringTable<'data, R>,
+ ) -> Result<&'data [u8]> {
+ if self.n_name[0] == 0 {
+ // If the name starts with 0 then the last 4 bytes are a string table offset.
+ let offset = u32::from_be_bytes(self.n_name[4..8].try_into().unwrap());
+ strings
+ .get(offset)
+ .read_error("Invalid XCOFF symbol name offset")
+ } else {
+ // The name is inline and padded with nulls.
+ Ok(match memchr::memchr(b'\0', &self.n_name) {
+ Some(end) => &self.n_name[..end],
+ None => &self.n_name,
+ })
+ }
+ }
+}
+
+/// A trait for generic access to `FileAux32` and `FileAux64`.
+#[allow(missing_docs)]
+pub trait FileAux: Debug + Pod {
+ fn x_fname(&self) -> &[u8; 8];
+ fn x_ftype(&self) -> u8;
+ fn x_auxtype(&self) -> Option<u8>;
+}
+
+impl FileAux for xcoff::FileAux64 {
+ fn x_fname(&self) -> &[u8; 8] {
+ &self.x_fname
+ }
+
+ fn x_ftype(&self) -> u8 {
+ self.x_ftype
+ }
+
+ fn x_auxtype(&self) -> Option<u8> {
+ Some(self.x_auxtype)
+ }
+}
+
+impl FileAux for xcoff::FileAux32 {
+ fn x_fname(&self) -> &[u8; 8] {
+ &self.x_fname
+ }
+
+ fn x_ftype(&self) -> u8 {
+ self.x_ftype
+ }
+
+ fn x_auxtype(&self) -> Option<u8> {
+ None
+ }
+}
+
+/// A trait for generic access to `CsectAux32` and `CsectAux64`.
+#[allow(missing_docs)]
+pub trait CsectAux: Debug + Pod {
+ fn x_scnlen(&self) -> u64;
+ fn x_parmhash(&self) -> u32;
+ fn x_snhash(&self) -> u16;
+ fn x_smtyp(&self) -> u8;
+ fn x_smclas(&self) -> u8;
+ fn x_auxtype(&self) -> Option<u8>;
+
+ fn sym_type(&self) -> u8 {
+ self.x_smtyp() & 0x07
+ }
+}
+
+impl CsectAux for xcoff::CsectAux64 {
+ fn x_scnlen(&self) -> u64 {
+ self.x_scnlen_lo.get(BE) as u64 | ((self.x_scnlen_hi.get(BE) as u64) << 32)
+ }
+
+ fn x_parmhash(&self) -> u32 {
+ self.x_parmhash.get(BE)
+ }
+
+ fn x_snhash(&self) -> u16 {
+ self.x_snhash.get(BE)
+ }
+
+ fn x_smtyp(&self) -> u8 {
+ self.x_smtyp
+ }
+
+ fn x_smclas(&self) -> u8 {
+ self.x_smclas
+ }
+
+ fn x_auxtype(&self) -> Option<u8> {
+ Some(self.x_auxtype)
+ }
+}
+
+impl CsectAux for xcoff::CsectAux32 {
+ fn x_scnlen(&self) -> u64 {
+ self.x_scnlen.get(BE) as u64
+ }
+
+ fn x_parmhash(&self) -> u32 {
+ self.x_parmhash.get(BE)
+ }
+
+ fn x_snhash(&self) -> u16 {
+ self.x_snhash.get(BE)
+ }
+
+ fn x_smtyp(&self) -> u8 {
+ self.x_smtyp
+ }
+
+ fn x_smclas(&self) -> u8 {
+ self.x_smclas
+ }
+
+ fn x_auxtype(&self) -> Option<u8> {
+ None
+ }
+}