summaryrefslogtreecommitdiffstats
path: root/vendor/object/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--vendor/object/src/archive.rs54
-rw-r--r--vendor/object/src/common.rs25
-rw-r--r--vendor/object/src/elf.rs255
-rw-r--r--vendor/object/src/lib.rs5
-rw-r--r--vendor/object/src/pe.rs15
-rw-r--r--vendor/object/src/pod.rs1
-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
-rw-r--r--vendor/object/src/write/coff.rs3
-rw-r--r--vendor/object/src/write/elf/object.rs60
-rw-r--r--vendor/object/src/write/macho.rs30
-rw-r--r--vendor/object/src/xcoff.rs893
33 files changed, 4078 insertions, 128 deletions
diff --git a/vendor/object/src/archive.rs b/vendor/object/src/archive.rs
index d4b419beb..6271d0736 100644
--- a/vendor/object/src/archive.rs
+++ b/vendor/object/src/archive.rs
@@ -8,6 +8,9 @@ use crate::pod::Pod;
/// File identification bytes stored at the beginning of the file.
pub const MAGIC: [u8; 8] = *b"!<arch>\n";
+/// File identification bytes at the beginning of AIX big archive.
+pub const AIX_BIG_MAGIC: [u8; 8] = *b"<bigaf>\n";
+
/// File identification bytes stored at the beginning of a thin archive.
///
/// A thin archive only contains a symbol table and file names.
@@ -36,4 +39,53 @@ pub struct Header {
pub terminator: [u8; 2],
}
-unsafe_impl_pod!(Header);
+/// The header at the start of an AIX big archive member, without name.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct AixHeader {
+ /// File member size in decimal.
+ pub size: [u8; 20],
+ /// Next member offset in decimal.
+ pub nxtmem: [u8; 20],
+ /// Previous member offset in decimal.
+ pub prvmem: [u8; 20],
+ /// File member date in decimal.
+ pub date: [u8; 12],
+ /// File member user id in decimal.
+ pub uid: [u8; 12],
+ /// File member group id in decimal.
+ pub gid: [u8; 12],
+ /// File member mode in octal.
+ pub mode: [u8; 12],
+ /// File member name length in decimal.
+ pub namlen: [u8; 4],
+}
+
+/// The AIX big archive's fixed length header at file beginning.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct AixFileHeader {
+ /// Archive magic string.
+ pub magic: [u8; 8],
+ /// Offset of member table.
+ pub memoff: [u8; 20],
+ /// Offset of global symbol table.
+ pub gstoff: [u8; 20],
+ /// Offset of global symbol table for 64-bit objects.
+ pub gst64off: [u8; 20],
+ /// Offset of first member.
+ pub fstmoff: [u8; 20],
+ /// Offset of last member.
+ pub lstmoff: [u8; 20],
+ /// Offset of first member on free list.
+ pub freeoff: [u8; 20],
+}
+
+/// Offset of a member in an AIX big archive.
+///
+/// This is used in the member index.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct AixMemberOffset(pub [u8; 20]);
+
+unsafe_impl_pod!(Header, AixHeader, AixFileHeader, AixMemberOffset,);
diff --git a/vendor/object/src/common.rs b/vendor/object/src/common.rs
index 20dde991a..cb009c0f9 100644
--- a/vendor/object/src/common.rs
+++ b/vendor/object/src/common.rs
@@ -5,6 +5,8 @@
pub enum Architecture {
Unknown,
Aarch64,
+ #[allow(non_camel_case_types)]
+ Aarch64_Ilp32,
Arm,
Avr,
Bpf,
@@ -22,8 +24,10 @@ pub enum Architecture {
Riscv32,
Riscv64,
S390x,
+ Sbf,
Sparc64,
Wasm32,
+ Xtensa,
}
impl Architecture {
@@ -34,6 +38,7 @@ impl Architecture {
match self {
Architecture::Unknown => None,
Architecture::Aarch64 => Some(AddressSize::U64),
+ Architecture::Aarch64_Ilp32 => Some(AddressSize::U32),
Architecture::Arm => Some(AddressSize::U32),
Architecture::Avr => Some(AddressSize::U8),
Architecture::Bpf => Some(AddressSize::U64),
@@ -50,8 +55,10 @@ impl Architecture {
Architecture::Riscv32 => Some(AddressSize::U32),
Architecture::Riscv64 => Some(AddressSize::U64),
Architecture::S390x => Some(AddressSize::U64),
+ Architecture::Sbf => Some(AddressSize::U64),
Architecture::Sparc64 => Some(AddressSize::U64),
Architecture::Wasm32 => Some(AddressSize::U32),
+ Architecture::Xtensa => Some(AddressSize::U32),
}
}
}
@@ -88,6 +95,7 @@ pub enum BinaryFormat {
MachO,
Pe,
Wasm,
+ Xcoff,
}
/// The kind of a section.
@@ -305,6 +313,8 @@ pub enum RelocationKind {
},
/// Some other COFF relocation. The value is dependent on the architecture.
Coff(u16),
+ /// Some other XCOFF relocation.
+ Xcoff(u8),
}
/// Information about how the result of the relocation operation is encoded in the place.
@@ -343,6 +353,11 @@ pub enum RelocationEncoding {
///
/// The `RelocationKind` must be PC relative.
AArch64Call,
+
+ /// LoongArch branch offset with two trailing zeros.
+ ///
+ /// The `RelocationKind` must be PC relative.
+ LoongArchBranch,
}
/// File flags that are specific to each file format.
@@ -370,6 +385,11 @@ pub enum FileFlags {
/// `Characteristics` field in the COFF file header.
characteristics: u16,
},
+ /// XCOFF file flags.
+ Xcoff {
+ /// `f_flags` field in the XCOFF file header.
+ f_flags: u16,
+ },
}
/// Segment flags that are specific to each file format.
@@ -420,6 +440,11 @@ pub enum SectionFlags {
/// `Characteristics` field in the section header.
characteristics: u32,
},
+ /// XCOFF section flags.
+ Xcoff {
+ /// `s_flags` field in the section header.
+ s_flags: u32,
+ },
}
/// Symbol flags that are specific to each file format.
diff --git a/vendor/object/src/elf.rs b/vendor/object/src/elf.rs
index 9f6577269..ac9742080 100644
--- a/vendor/object/src/elf.rs
+++ b/vendor/object/src/elf.rs
@@ -576,6 +576,8 @@ pub const EM_BPF: u16 = 247;
pub const EM_CSKY: u16 = 252;
/// Loongson LoongArch
pub const EM_LOONGARCH: u16 = 258;
+/// Solana Binary Format
+pub const EM_SBF: u16 = 263;
/// Digital Alpha
pub const EM_ALPHA: u16 = 0x9026;
@@ -6122,6 +6124,14 @@ pub const R_BPF_64_64: u32 = 1;
#[allow(missing_docs)]
pub const R_BPF_64_32: u32 = 10;
+// SBF values `Rel*::r_type`.
+/// No reloc
+pub const R_SBF_NONE: u32 = 0;
+#[allow(missing_docs)]
+pub const R_SBF_64_64: u32 = 1;
+#[allow(missing_docs)]
+pub const R_SBF_64_32: u32 = 10;
+
// Imagination Meta values `Rel*::r_type`.
#[allow(missing_docs)]
@@ -6251,18 +6261,17 @@ pub const R_NDS32_TLS_TPOFF: u32 = 102;
pub const R_NDS32_TLS_DESC: u32 = 119;
// LoongArch values `FileHeader*::e_flags`.
-/// Uses 64-bit GPRs and the stack for parameter passing
-pub const EF_LARCH_ABI_LP64S: u32 = 0x1;
-/// Uses 64-bit GPRs, 32-bit FPRs and the stack for parameter passing
-pub const EF_LARCH_ABI_LP64F: u32 = 0x2;
-/// Uses 64-bit GPRs, 64-bit FPRs and the stack for parameter passing
-pub const EF_LARCH_ABI_LP64D: u32 = 0x3;
-/// Uses 32-bit GPRs and the stack for parameter passing
-pub const EF_LARCH_ABI_ILP32S: u32 = 0x5;
-/// Uses 32-bit GPRs, 32-bit FPRs and the stack for parameter passing
-pub const EF_LARCH_ABI_ILP32F: u32 = 0x6;
-/// Uses 32-bit GPRs, 64-bit FPRs and the stack for parameter passing
-pub const EF_LARCH_ABI_ILP32D: u32 = 0x7;
+/// Additional properties of the base ABI type, including the FP calling
+/// convention.
+pub const EF_LARCH_ABI_MODIFIER_MASK: u32 = 0x7;
+/// Uses GPRs and the stack for parameter passing
+pub const EF_LARCH_ABI_SOFT_FLOAT: u32 = 0x1;
+/// Uses GPRs, 32-bit FPRs and the stack for parameter passing
+pub const EF_LARCH_ABI_SINGLE_FLOAT: u32 = 0x2;
+/// Uses GPRs, 64-bit FPRs and the stack for parameter passing
+pub const EF_LARCH_ABI_DOUBLE_FLOAT: u32 = 0x3;
+/// Uses relocation types directly writing to immediate slots
+pub const EF_LARCH_OBJABI_V1: u32 = 0x40;
// LoongArch values `Rel*::r_type`.
/// No reloc
@@ -6372,6 +6381,228 @@ pub const R_LARCH_SUB64: u32 = 56;
pub const R_LARCH_GNU_VTINHERIT: u32 = 57;
/// GNU C++ vtable member usage
pub const R_LARCH_GNU_VTENTRY: u32 = 58;
+/// 18-bit PC-relative jump offset with two trailing zeros
+pub const R_LARCH_B16: u32 = 64;
+/// 23-bit PC-relative jump offset with two trailing zeros
+pub const R_LARCH_B21: u32 = 65;
+/// 28-bit PC-relative jump offset with two trailing zeros
+pub const R_LARCH_B26: u32 = 66;
+/// 12..=31 bits of 32/64-bit absolute address
+pub const R_LARCH_ABS_HI20: u32 = 67;
+/// 0..=11 bits of 32/64-bit absolute address
+pub const R_LARCH_ABS_LO12: u32 = 68;
+/// 32..=51 bits of 64-bit absolute address
+pub const R_LARCH_ABS64_LO20: u32 = 69;
+/// 52..=63 bits of 64-bit absolute address
+pub const R_LARCH_ABS64_HI12: u32 = 70;
+/// The signed 32-bit offset `offs` from `PC & 0xfffff000` to
+/// `(S + A + 0x800) & 0xfffff000`, with 12 trailing zeros removed.
+///
+/// We define the *PC relative anchor* for `S + A` as `PC + offs` (`offs`
+/// is sign-extended to VA bits).
+pub const R_LARCH_PCALA_HI20: u32 = 71;
+/// Same as R_LARCH_ABS_LO12. 0..=11 bits of the 32/64-bit offset from the
+/// [PC relative anchor][R_LARCH_PCALA_HI20].
+pub const R_LARCH_PCALA_LO12: u32 = 72;
+/// 32..=51 bits of the 64-bit offset from the
+/// [PC relative anchor][R_LARCH_PCALA_HI20].
+pub const R_LARCH_PCALA64_LO20: u32 = 73;
+/// 52..=63 bits of the 64-bit offset from the
+/// [PC relative anchor][R_LARCH_PCALA_HI20].
+pub const R_LARCH_PCALA64_HI12: u32 = 74;
+/// The signed 32-bit offset `offs` from `PC & 0xfffff000` to
+/// `(GP + G + 0x800) & 0xfffff000`, with 12 trailing zeros removed.
+///
+/// We define the *PC relative anchor* for the GOT entry at `GP + G` as
+/// `PC + offs` (`offs` is sign-extended to VA bits).
+pub const R_LARCH_GOT_PC_HI20: u32 = 75;
+/// 0..=11 bits of the 32/64-bit offset from the
+/// [PC relative anchor][R_LARCH_GOT_PC_HI20] to the GOT entry.
+pub const R_LARCH_GOT_PC_LO12: u32 = 76;
+/// 32..=51 bits of the 64-bit offset from the
+/// [PC relative anchor][R_LARCH_GOT_PC_HI20] to the GOT entry.
+pub const R_LARCH_GOT64_PC_LO20: u32 = 77;
+/// 52..=63 bits of the 64-bit offset from the
+/// [PC relative anchor][R_LARCH_GOT_PC_HI20] to the GOT entry.
+pub const R_LARCH_GOT64_PC_HI12: u32 = 78;
+/// 12..=31 bits of 32/64-bit GOT entry absolute address
+pub const R_LARCH_GOT_HI20: u32 = 79;
+/// 0..=11 bits of 32/64-bit GOT entry absolute address
+pub const R_LARCH_GOT_LO12: u32 = 80;
+/// 32..=51 bits of 64-bit GOT entry absolute address
+pub const R_LARCH_GOT64_LO20: u32 = 81;
+/// 52..=63 bits of 64-bit GOT entry absolute address
+pub const R_LARCH_GOT64_HI12: u32 = 82;
+/// 12..=31 bits of TLS LE 32/64-bit offset from thread pointer
+pub const R_LARCH_TLS_LE_HI20: u32 = 83;
+/// 0..=11 bits of TLS LE 32/64-bit offset from thread pointer
+pub const R_LARCH_TLS_LE_LO12: u32 = 84;
+/// 32..=51 bits of TLS LE 64-bit offset from thread pointer
+pub const R_LARCH_TLS_LE64_LO20: u32 = 85;
+/// 52..=63 bits of TLS LE 64-bit offset from thread pointer
+pub const R_LARCH_TLS_LE64_HI12: u32 = 86;
+/// The signed 32-bit offset `offs` from `PC & 0xfffff000` to
+/// `(GP + IE + 0x800) & 0xfffff000`, with 12 trailing zeros removed.
+///
+/// We define the *PC relative anchor* for the TLS IE GOT entry at
+/// `GP + IE` as `PC + offs` (`offs` is sign-extended to VA bits).
+pub const R_LARCH_TLS_IE_PC_HI20: u32 = 87;
+/// 0..=12 bits of the 32/64-bit offset from the
+/// [PC-relative anchor][R_LARCH_TLS_IE_PC_HI20] to the TLS IE GOT entry.
+pub const R_LARCH_TLS_IE_PC_LO12: u32 = 88;
+/// 32..=51 bits of the 64-bit offset from the
+/// [PC-relative anchor][R_LARCH_TLS_IE_PC_HI20] to the TLS IE GOT entry.
+pub const R_LARCH_TLS_IE64_PC_LO20: u32 = 89;
+/// 52..=63 bits of the 64-bit offset from the
+/// [PC-relative anchor][R_LARCH_TLS_IE_PC_HI20] to the TLS IE GOT entry.
+pub const R_LARCH_TLS_IE64_PC_HI12: u32 = 90;
+/// 12..=31 bits of TLS IE GOT entry 32/64-bit absolute address
+pub const R_LARCH_TLS_IE_HI20: u32 = 91;
+/// 0..=11 bits of TLS IE GOT entry 32/64-bit absolute address
+pub const R_LARCH_TLS_IE_LO12: u32 = 92;
+/// 32..=51 bits of TLS IE GOT entry 64-bit absolute address
+pub const R_LARCH_TLS_IE64_LO20: u32 = 93;
+/// 51..=63 bits of TLS IE GOT entry 64-bit absolute address
+pub const R_LARCH_TLS_IE64_HI12: u32 = 94;
+/// 12..=31 bits of the offset from `PC` to `GP + GD + 0x800`, where
+/// `GP + GD` is a TLS LD GOT entry
+pub const R_LARCH_TLS_LD_PC_HI20: u32 = 95;
+/// 12..=31 bits of TLS LD GOT entry 32/64-bit absolute address
+pub const R_LARCH_TLS_LD_HI20: u32 = 96;
+/// 12..=31 bits of the 32/64-bit PC-relative offset to the PC-relative
+/// anchor for the TLE GD GOT entry.
+pub const R_LARCH_TLS_GD_PC_HI20: u32 = 97;
+/// 12..=31 bits of TLS GD GOT entry 32/64-bit absolute address
+pub const R_LARCH_TLS_GD_HI20: u32 = 98;
+/// 32-bit PC relative
+pub const R_LARCH_32_PCREL: u32 = 99;
+/// Paired with a normal relocation at the same address to indicate the
+/// insturction can be relaxed
+pub const R_LARCH_RELAX: u32 = 100;
+
+// Xtensa values Rel*::r_type`.
+#[allow(missing_docs)]
+pub const R_XTENSA_NONE: u32 = 0;
+#[allow(missing_docs)]
+pub const R_XTENSA_32: u32 = 1;
+#[allow(missing_docs)]
+pub const R_XTENSA_RTLD: u32 = 2;
+#[allow(missing_docs)]
+pub const R_XTENSA_GLOB_DAT: u32 = 3;
+#[allow(missing_docs)]
+pub const R_XTENSA_JMP_SLOT: u32 = 4;
+#[allow(missing_docs)]
+pub const R_XTENSA_RELATIVE: u32 = 5;
+#[allow(missing_docs)]
+pub const R_XTENSA_PLT: u32 = 6;
+#[allow(missing_docs)]
+pub const R_XTENSA_OP0: u32 = 8;
+#[allow(missing_docs)]
+pub const R_XTENSA_OP1: u32 = 9;
+#[allow(missing_docs)]
+pub const R_XTENSA_OP2: u32 = 10;
+#[allow(missing_docs)]
+pub const R_XTENSA_ASM_EXPAND: u32 = 11;
+#[allow(missing_docs)]
+pub const R_XTENSA_ASM_SIMPLIFY: u32 = 12;
+#[allow(missing_docs)]
+pub const R_XTENSA_32_PCREL: u32 = 14;
+#[allow(missing_docs)]
+pub const R_XTENSA_GNU_VTINHERIT: u32 = 15;
+#[allow(missing_docs)]
+pub const R_XTENSA_GNU_VTENTRY: u32 = 16;
+#[allow(missing_docs)]
+pub const R_XTENSA_DIFF8: u32 = 17;
+#[allow(missing_docs)]
+pub const R_XTENSA_DIFF16: u32 = 18;
+#[allow(missing_docs)]
+pub const R_XTENSA_DIFF32: u32 = 19;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT0_OP: u32 = 20;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT1_OP: u32 = 21;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT2_OP: u32 = 22;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT3_OP: u32 = 23;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT4_OP: u32 = 24;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT5_OP: u32 = 25;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT6_OP: u32 = 26;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT7_OP: u32 = 27;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT8_OP: u32 = 28;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT9_OP: u32 = 29;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT10_OP: u32 = 30;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT11_OP: u32 = 31;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT12_OP: u32 = 32;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT13_OP: u32 = 33;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT14_OP: u32 = 34;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT0_ALT: u32 = 35;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT1_ALT: u32 = 36;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT2_ALT: u32 = 37;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT3_ALT: u32 = 38;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT4_ALT: u32 = 39;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT5_ALT: u32 = 40;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT6_ALT: u32 = 41;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT7_ALT: u32 = 42;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT8_ALT: u32 = 43;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT9_ALT: u32 = 44;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT10_ALT: u32 = 45;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT11_ALT: u32 = 46;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT12_ALT: u32 = 47;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT13_ALT: u32 = 48;
+#[allow(missing_docs)]
+pub const R_XTENSA_SLOT14_ALT: u32 = 49;
+#[allow(missing_docs)]
+pub const R_XTENSA_TLSDESC_FN: u32 = 50;
+#[allow(missing_docs)]
+pub const R_XTENSA_TLSDESC_ARG: u32 = 51;
+#[allow(missing_docs)]
+pub const R_XTENSA_TLS_DTPOFF: u32 = 52;
+#[allow(missing_docs)]
+pub const R_XTENSA_TLS_TPOFF: u32 = 53;
+#[allow(missing_docs)]
+pub const R_XTENSA_TLS_FUNC: u32 = 54;
+#[allow(missing_docs)]
+pub const R_XTENSA_TLS_ARG: u32 = 55;
+#[allow(missing_docs)]
+pub const R_XTENSA_TLS_CALL: u32 = 56;
+#[allow(missing_docs)]
+pub const R_XTENSA_PDIFF8: u32 = 57;
+#[allow(missing_docs)]
+pub const R_XTENSA_PDIFF16: u32 = 58;
+#[allow(missing_docs)]
+pub const R_XTENSA_PDIFF32: u32 = 59;
+#[allow(missing_docs)]
+pub const R_XTENSA_NDIFF8: u32 = 60;
+#[allow(missing_docs)]
+pub const R_XTENSA_NDIFF16: u32 = 61;
+#[allow(missing_docs)]
+pub const R_XTENSA_NDIFF32: u32 = 62;
unsafe_impl_endian_pod!(
FileHeader32,
diff --git a/vendor/object/src/lib.rs b/vendor/object/src/lib.rs
index d50009f38..40f17c017 100644
--- a/vendor/object/src/lib.rs
+++ b/vendor/object/src/lib.rs
@@ -73,6 +73,9 @@
#[cfg(feature = "cargo-all")]
compile_error!("'--all-features' is not supported; use '--features all' instead");
+#[cfg(all(feature = "xcoff", not(feature = "unstable")))]
+compile_error!("'xcoff` is an unstable feature; enable 'unstable' as well");
+
#[cfg(any(feature = "read_core", feature = "write_core"))]
#[allow(unused_imports)]
#[macro_use]
@@ -110,3 +113,5 @@ pub mod elf;
pub mod macho;
#[cfg(any(feature = "coff", feature = "pe"))]
pub mod pe;
+#[cfg(feature = "xcoff")]
+pub mod xcoff;
diff --git a/vendor/object/src/pe.rs b/vendor/object/src/pe.rs
index c89b86caa..00105adac 100644
--- a/vendor/object/src/pe.rs
+++ b/vendor/object/src/pe.rs
@@ -1977,6 +1977,21 @@ pub struct ImageDelayloadDescriptor {
pub time_date_stamp: U32<LE>,
}
+impl ImageDelayloadDescriptor {
+ /// Tell whether this delay-load import descriptor is the null descriptor
+ /// (used to mark the end of the iterator array in a PE)
+ pub fn is_null(&self) -> bool {
+ self.attributes.get(LE) == 0
+ && self.dll_name_rva.get(LE) == 0
+ && self.module_handle_rva.get(LE) == 0
+ && self.import_address_table_rva.get(LE) == 0
+ && self.import_name_table_rva.get(LE) == 0
+ && self.bound_import_address_table_rva.get(LE) == 0
+ && self.unload_information_table_rva.get(LE) == 0
+ && self.time_date_stamp.get(LE) == 0
+ }
+}
+
/// Delay load version 2 flag for `ImageDelayloadDescriptor::attributes`.
pub const IMAGE_DELAYLOAD_RVA_BASED: u32 = 0x8000_0000;
diff --git a/vendor/object/src/pod.rs b/vendor/object/src/pod.rs
index 805cf8249..8ee78164f 100644
--- a/vendor/object/src/pod.rs
+++ b/vendor/object/src/pod.rs
@@ -14,6 +14,7 @@ type Result<T> = result::Result<T, ()>;
/// A trait for types that can safely be converted from and to byte slices.
///
+/// # Safety
/// A type that is `Pod` must:
/// - be `#[repr(C)]` or `#[repr(transparent)]`
/// - have no invalid byte values
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
+ }
+}
diff --git a/vendor/object/src/write/coff.rs b/vendor/object/src/write/coff.rs
index 6647b9611..c7489d3d6 100644
--- a/vendor/object/src/write/coff.rs
+++ b/vendor/object/src/write/coff.rs
@@ -117,8 +117,7 @@ impl<'a> Object<'a> {
}
let stub_size = self.architecture.address_size().unwrap().bytes();
- let mut name = b".rdata$.refptr.".to_vec();
- name.extend_from_slice(&self.symbols[symbol_id.0].name);
+ let name = b".rdata$.refptr".to_vec();
let section_id = self.add_section(Vec::new(), name, SectionKind::ReadOnlyData);
let section = self.section_mut(section_id);
section.set_data(vec![0; stub_size as usize], u64::from(stub_size));
diff --git a/vendor/object/src/write/elf/object.rs b/vendor/object/src/write/elf/object.rs
index 8c1fa4717..068ada6bd 100644
--- a/vendor/object/src/write/elf/object.rs
+++ b/vendor/object/src/write/elf/object.rs
@@ -67,6 +67,7 @@ impl<'a> Object<'a> {
fn elf_has_relocation_addend(&self) -> Result<bool> {
Ok(match self.architecture {
Architecture::Aarch64 => true,
+ Architecture::Aarch64_Ilp32 => true,
Architecture::Arm => false,
Architecture::Avr => true,
Architecture::Bpf => false,
@@ -83,7 +84,9 @@ impl<'a> Object<'a> {
Architecture::Riscv64 => true,
Architecture::Riscv32 => true,
Architecture::S390x => true,
+ Architecture::Sbf => false,
Architecture::Sparc64 => true,
+ Architecture::Xtensa => true,
_ => {
return Err(Error(format!(
"unimplemented architecture {:?}",
@@ -264,6 +267,7 @@ impl<'a> Object<'a> {
let e_type = elf::ET_REL;
let e_machine = match self.architecture {
Architecture::Aarch64 => elf::EM_AARCH64,
+ Architecture::Aarch64_Ilp32 => elf::EM_AARCH64,
Architecture::Arm => elf::EM_ARM,
Architecture::Avr => elf::EM_AVR,
Architecture::Bpf => elf::EM_BPF,
@@ -280,7 +284,9 @@ impl<'a> Object<'a> {
Architecture::Riscv32 => elf::EM_RISCV,
Architecture::Riscv64 => elf::EM_RISCV,
Architecture::S390x => elf::EM_S390,
+ Architecture::Sbf => elf::EM_SBF,
Architecture::Sparc64 => elf::EM_SPARCV9,
+ Architecture::Xtensa => elf::EM_XTENSA,
_ => {
return Err(Error(format!(
"unimplemented architecture {:?}",
@@ -450,6 +456,20 @@ impl<'a> Object<'a> {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
}
},
+ Architecture::Aarch64_Ilp32 => {
+ match (reloc.kind, reloc.encoding, reloc.size) {
+ (RelocationKind::Absolute, RelocationEncoding::Generic, 32) => {
+ elf::R_AARCH64_P32_ABS32
+ }
+ (RelocationKind::Elf(x), _, _) => x,
+ _ => {
+ return Err(Error(format!(
+ "unimplemented relocation {:?}",
+ reloc
+ )));
+ }
+ }
+ }
Architecture::Arm => match (reloc.kind, reloc.encoding, reloc.size) {
(RelocationKind::Absolute, _, 32) => elf::R_ARM_ABS32,
(RelocationKind::Elf(x), _, _) => x,
@@ -528,6 +548,25 @@ impl<'a> Object<'a> {
{
(RelocationKind::Absolute, _, 32) => elf::R_LARCH_32,
(RelocationKind::Absolute, _, 64) => elf::R_LARCH_64,
+ (RelocationKind::Relative, _, 32) => elf::R_LARCH_32_PCREL,
+ (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 16)
+ | (
+ RelocationKind::PltRelative,
+ RelocationEncoding::LoongArchBranch,
+ 16,
+ ) => elf::R_LARCH_B16,
+ (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 21)
+ | (
+ RelocationKind::PltRelative,
+ RelocationEncoding::LoongArchBranch,
+ 21,
+ ) => elf::R_LARCH_B21,
+ (RelocationKind::Relative, RelocationEncoding::LoongArchBranch, 26)
+ | (
+ RelocationKind::PltRelative,
+ RelocationEncoding::LoongArchBranch,
+ 26,
+ ) => elf::R_LARCH_B26,
(RelocationKind::Elf(x), _, _) => x,
_ => {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
@@ -574,6 +613,9 @@ impl<'a> Object<'a> {
match (reloc.kind, reloc.encoding, reloc.size) {
(RelocationKind::Absolute, _, 32) => elf::R_RISCV_32,
(RelocationKind::Absolute, _, 64) => elf::R_RISCV_64,
+ (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
+ elf::R_RISCV_32_PCREL
+ }
(RelocationKind::Elf(x), _, _) => x,
_ => {
return Err(Error(format!(
@@ -649,6 +691,14 @@ impl<'a> Object<'a> {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
}
},
+ Architecture::Sbf => match (reloc.kind, reloc.encoding, reloc.size) {
+ (RelocationKind::Absolute, _, 64) => elf::R_SBF_64_64,
+ (RelocationKind::Absolute, _, 32) => elf::R_SBF_64_32,
+ (RelocationKind::Elf(x), _, _) => x,
+ _ => {
+ return Err(Error(format!("unimplemented relocation {:?}", reloc)));
+ }
+ },
Architecture::Sparc64 => match (reloc.kind, reloc.encoding, reloc.size) {
// TODO: use R_SPARC_32/R_SPARC_64 if aligned.
(RelocationKind::Absolute, _, 32) => elf::R_SPARC_UA32,
@@ -658,6 +708,16 @@ impl<'a> Object<'a> {
return Err(Error(format!("unimplemented relocation {:?}", reloc)));
}
},
+ Architecture::Xtensa => match (reloc.kind, reloc.encoding, reloc.size) {
+ (RelocationKind::Absolute, _, 32) => elf::R_XTENSA_32,
+ (RelocationKind::Relative, RelocationEncoding::Generic, 32) => {
+ elf::R_XTENSA_32_PCREL
+ }
+ (RelocationKind::Elf(x), _, _) => x,
+ _ => {
+ return Err(Error(format!("unimplemented relocation {:?}", reloc)));
+ }
+ },
_ => {
if let RelocationKind::Elf(x) = reloc.kind {
x
diff --git a/vendor/object/src/write/macho.rs b/vendor/object/src/write/macho.rs
index f689dec51..8ef722fae 100644
--- a/vendor/object/src/write/macho.rs
+++ b/vendor/object/src/write/macho.rs
@@ -175,11 +175,17 @@ impl<'a> Object<'a> {
pub(crate) fn macho_fixup_relocation(&mut self, mut relocation: &mut Relocation) -> i64 {
let constant = match relocation.kind {
+ // AArch64Call relocations have special handling for the addend, so don't adjust it
+ RelocationKind::Relative if relocation.encoding == RelocationEncoding::AArch64Call => 0,
RelocationKind::Relative
| RelocationKind::GotRelative
| RelocationKind::PltRelative => relocation.addend + 4,
_ => relocation.addend,
};
+ // Aarch64 relocs of these sizes act as if they are double-word length
+ if self.architecture == Architecture::Aarch64 && matches!(relocation.size, 12 | 21 | 26) {
+ relocation.size = 32;
+ }
relocation.addend -= constant;
constant
}
@@ -326,6 +332,8 @@ impl<'a> Object<'a> {
Architecture::Aarch64 => (macho::CPU_TYPE_ARM64, macho::CPU_SUBTYPE_ARM64_ALL),
Architecture::I386 => (macho::CPU_TYPE_X86, macho::CPU_SUBTYPE_I386_ALL),
Architecture::X86_64 => (macho::CPU_TYPE_X86_64, macho::CPU_SUBTYPE_X86_64_ALL),
+ Architecture::PowerPc => (macho::CPU_TYPE_POWERPC, macho::CPU_SUBTYPE_POWERPC_ALL),
+ Architecture::PowerPc64 => (macho::CPU_TYPE_POWERPC64, macho::CPU_SUBTYPE_POWERPC_ALL),
_ => {
return Err(Error(format!(
"unimplemented architecture {:?}",
@@ -532,7 +540,7 @@ impl<'a> Object<'a> {
debug_assert_eq!(section_offsets[index].reloc_offset, buffer.len());
for reloc in &section.relocations {
let r_extern;
- let r_symbolnum;
+ let mut r_symbolnum;
let symbol = &self.symbols[reloc.symbol.0];
if symbol.kind == SymbolKind::Section {
r_symbolnum = section_offsets[symbol.section.id().unwrap().0].index as u32;
@@ -588,6 +596,26 @@ impl<'a> Object<'a> {
(RelocationKind::Absolute, RelocationEncoding::Generic, 0) => {
(false, macho::ARM64_RELOC_UNSIGNED)
}
+ (RelocationKind::Relative, RelocationEncoding::AArch64Call, 0) => {
+ (true, macho::ARM64_RELOC_BRANCH26)
+ }
+ // Non-zero addend, so we have to encode the addend separately
+ (RelocationKind::Relative, RelocationEncoding::AArch64Call, value) => {
+ // first emit the BR26 relocation
+ let reloc_info = macho::RelocationInfo {
+ r_address: reloc.offset as u32,
+ r_symbolnum,
+ r_pcrel: true,
+ r_length,
+ r_extern: true,
+ r_type: macho::ARM64_RELOC_BRANCH26,
+ };
+ buffer.write(&reloc_info.relocation(endian));
+
+ // set up a separate relocation for the addend
+ r_symbolnum = value as u32;
+ (false, macho::ARM64_RELOC_ADDEND)
+ }
(
RelocationKind::MachO { value, relative },
RelocationEncoding::Generic,
diff --git a/vendor/object/src/xcoff.rs b/vendor/object/src/xcoff.rs
new file mode 100644
index 000000000..4724f8ef8
--- /dev/null
+++ b/vendor/object/src/xcoff.rs
@@ -0,0 +1,893 @@
+//! XCOFF definitions
+//!
+//! These definitions are independent of read/write support, although we do implement
+//! some traits useful for those.
+//!
+//! This module is the equivalent of /usr/include/xcoff.h, and is based heavily on it.
+
+#![allow(missing_docs)]
+
+use crate::endian::{BigEndian as BE, I16, U16, U32, U64};
+use crate::pod::Pod;
+
+/// The header at the start of every 32-bit XCOFF file.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct FileHeader32 {
+ /// Magic number. Must be 0x01DF.
+ pub f_magic: U16<BE>,
+ /// Number of sections.
+ pub f_nscns: U16<BE>,
+ /// Time and date of file creation.
+ pub f_timdat: U32<BE>,
+ /// Byte offset to symbol table start.
+ pub f_symptr: U32<BE>,
+ /// Number of entries in symbol table.
+ pub f_nsyms: U32<BE>,
+ /// Number of bytes in optional header
+ pub f_opthdr: U16<BE>,
+ /// Extra flags.
+ pub f_flags: U16<BE>,
+}
+
+/// The header at the start of every 64-bit XCOFF file.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct FileHeader64 {
+ /// Magic number. Must be 0x01F7.
+ pub f_magic: U16<BE>,
+ /// Number of sections.
+ pub f_nscns: U16<BE>,
+ /// Time and date of file creation
+ pub f_timdat: U32<BE>,
+ /// Byte offset to symbol table start.
+ pub f_symptr: U64<BE>,
+ /// Number of bytes in optional header
+ pub f_opthdr: U16<BE>,
+ /// Extra flags.
+ pub f_flags: U16<BE>,
+ /// Number of entries in symbol table.
+ pub f_nsyms: U32<BE>,
+}
+
+// Values for `f_magic`.
+//
+/// the 64-bit mach magic number
+pub const MAGIC_64: u16 = 0x01F7;
+/// the 32-bit mach magic number
+pub const MAGIC_32: u16 = 0x01DF;
+
+// Values for `f_flags`.
+//
+/// Indicates that the relocation information for binding has been removed from
+/// the file.
+pub const F_RELFLG: u16 = 0x0001;
+/// Indicates that the file is executable. No unresolved external references exist.
+pub const F_EXEC: u16 = 0x0002;
+/// Indicates that line numbers have been stripped from the file by a utility program.
+pub const F_LNNO: u16 = 0x0004;
+/// Indicates that the file was profiled with the fdpr command.
+pub const F_FDPR_PROF: u16 = 0x0010;
+/// Indicates that the file was reordered with the fdpr command.
+pub const F_FDPR_OPTI: u16 = 0x0020;
+/// Indicates that the file uses Very Large Program Support.
+pub const F_DSA: u16 = 0x0040;
+/// Indicates that one of the members of the auxiliary header specifying the
+/// medium page sizes is non-zero.
+pub const F_VARPG: u16 = 0x0100;
+/// Indicates the file is dynamically loadable and executable. External references
+/// are resolved by way of imports, and the file might contain exports and loader
+/// relocation.
+pub const F_DYNLOAD: u16 = 0x1000;
+/// Indicates the file is a shared object (shared library). The file is separately
+/// loadable. That is, it is not normally bound with other objects, and its loader
+/// exports symbols are used as automatic import symbols for other object files.
+pub const F_SHROBJ: u16 = 0x2000;
+/// If the object file is a member of an archive, it can be loaded by the system
+/// loader, but the member is ignored by the binder. If the object file is not in
+/// an archive, this flag has no effect.
+pub const F_LOADONLY: u16 = 0x4000;
+
+/// The auxiliary header immediately following file header. If the value of the
+/// f_opthdr field in the file header is 0, the auxiliary header does not exist.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct AuxHeader32 {
+ /// Flags.
+ pub o_mflag: U16<BE>,
+ /// Version.
+ pub o_vstamp: U16<BE>,
+ /// Text size in bytes.
+ pub o_tsize: U32<BE>,
+ /// Initialized data size in bytes.
+ pub o_dsize: U32<BE>,
+ /// Uninitialized data size in bytes.
+ pub o_bsize: U32<BE>,
+ /// Entry point descriptor (virtual address).
+ pub o_entry: U32<BE>,
+ /// Base address of text (virtual address).
+ pub o_text_start: U32<BE>,
+ /// Base address of data (virtual address).
+ pub o_data_start: U32<BE>,
+ /// Address of TOC anchor.
+ pub o_toc: U32<BE>,
+ /// Section number for entry point.
+ pub o_snentry: U16<BE>,
+ /// Section number for .text.
+ pub o_sntext: U16<BE>,
+ /// Section number for .data.
+ pub o_sndata: U16<BE>,
+ /// Section number for TOC.
+ pub o_sntoc: U16<BE>,
+ /// Section number for loader data.
+ pub o_snloader: U16<BE>,
+ /// Section number for .bss.
+ pub o_snbss: U16<BE>,
+ /// Maximum alignment for .text.
+ pub o_algntext: U16<BE>,
+ /// Maximum alignment for .data.
+ pub o_algndata: U16<BE>,
+ /// Module type field.
+ pub o_modtype: U16<BE>,
+ /// Bit flags - cpu types of objects.
+ pub o_cpuflag: u8,
+ /// Reserved for CPU type.
+ pub o_cputype: u8,
+ /// Maximum stack size allowed (bytes).
+ pub o_maxstack: U32<BE>,
+ /// Maximum data size allowed (bytes).
+ pub o_maxdata: U32<BE>,
+ /// Reserved for debuggers.
+ pub o_debugger: U32<BE>,
+ /// Requested text page size.
+ pub o_textpsize: u8,
+ /// Requested data page size.
+ pub o_datapsize: u8,
+ /// Requested stack page size.
+ pub o_stackpsize: u8,
+ /// Flags and thread-local storage alignment.
+ pub o_flags: u8,
+ /// Section number for .tdata.
+ pub o_sntdata: U16<BE>,
+ /// Section number for .tbss.
+ pub o_sntbss: U16<BE>,
+}
+
+/// The auxiliary header immediately following file header. If the value of the
+/// f_opthdr field in the file header is 0, the auxiliary header does not exist.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct AuxHeader64 {
+ /// Flags.
+ pub o_mflag: U16<BE>,
+ /// Version.
+ pub o_vstamp: U16<BE>,
+ /// Reserved for debuggers.
+ pub o_debugger: U32<BE>,
+ /// Base address of text (virtual address).
+ pub o_text_start: U64<BE>,
+ /// Base address of data (virtual address).
+ pub o_data_start: U64<BE>,
+ /// Address of TOC anchor.
+ pub o_toc: U64<BE>,
+ /// Section number for entry point.
+ pub o_snentry: U16<BE>,
+ /// Section number for .text.
+ pub o_sntext: U16<BE>,
+ /// Section number for .data.
+ pub o_sndata: U16<BE>,
+ /// Section number for TOC.
+ pub o_sntoc: U16<BE>,
+ /// Section number for loader data.
+ pub o_snloader: U16<BE>,
+ /// Section number for .bss.
+ pub o_snbss: U16<BE>,
+ /// Maximum alignment for .text.
+ pub o_algntext: U16<BE>,
+ /// Maximum alignment for .data.
+ pub o_algndata: U16<BE>,
+ /// Module type field.
+ pub o_modtype: U16<BE>,
+ /// Bit flags - cpu types of objects.
+ pub o_cpuflag: u8,
+ /// Reserved for CPU type.
+ pub o_cputype: u8,
+ /// Requested text page size.
+ pub o_textpsize: u8,
+ /// Requested data page size.
+ pub o_datapsize: u8,
+ /// Requested stack page size.
+ pub o_stackpsize: u8,
+ /// Flags and thread-local storage alignment.
+ pub o_flags: u8,
+ /// Text size in bytes.
+ pub o_tsize: U64<BE>,
+ /// Initialized data size in bytes.
+ pub o_dsize: U64<BE>,
+ /// Uninitialized data size in bytes.
+ pub o_bsize: U64<BE>,
+ /// Entry point descriptor (virtual address).
+ pub o_entry: U64<BE>,
+ /// Maximum stack size allowed (bytes).
+ pub o_maxstack: U64<BE>,
+ /// Maximum data size allowed (bytes).
+ pub o_maxdata: U64<BE>,
+ /// Section number for .tdata.
+ pub o_sntdata: U16<BE>,
+ /// Section number for .tbss.
+ pub o_sntbss: U16<BE>,
+ /// XCOFF64 flags.
+ pub o_x64flags: U16<BE>,
+ /// Reserved.
+ pub o_resv3a: U16<BE>,
+ /// Reserved.
+ pub o_resv3: [U32<BE>; 2],
+}
+
+/// Some AIX programs generate auxiliary headers for 32-bit object files that
+/// end after the data_start field.
+pub const AOUTHSZ_SHORT: u16 = 28;
+
+/// Section header.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct SectionHeader32 {
+ /// Section name.
+ pub s_name: [u8; 8],
+ /// Physical address.
+ pub s_paddr: U32<BE>,
+ /// Virtual address (same as physical address).
+ pub s_vaddr: U32<BE>,
+ /// Section size.
+ pub s_size: U32<BE>,
+ /// Offset in file to raw data for section.
+ pub s_scnptr: U32<BE>,
+ /// Offset in file to relocation entries for section.
+ pub s_relptr: U32<BE>,
+ /// Offset in file to line number entries for section.
+ pub s_lnnoptr: U32<BE>,
+ /// Number of relocation entries.
+ pub s_nreloc: U16<BE>,
+ /// Number of line number entries.
+ pub s_nlnno: U16<BE>,
+ /// Flags to define the section type.
+ pub s_flags: U32<BE>,
+}
+
+/// Section header.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct SectionHeader64 {
+ /// Section name.
+ pub s_name: [u8; 8],
+ /// Physical address.
+ pub s_paddr: U64<BE>,
+ /// Virtual address (same as physical address).
+ pub s_vaddr: U64<BE>,
+ /// Section size.
+ pub s_size: U64<BE>,
+ /// Offset in file to raw data for section.
+ pub s_scnptr: U64<BE>,
+ /// Offset in file to relocation entries for section.
+ pub s_relptr: U64<BE>,
+ /// Offset in file to line number entries for section.
+ pub s_lnnoptr: U64<BE>,
+ /// Number of relocation entries.
+ pub s_nreloc: U32<BE>,
+ /// Number of line number entries.
+ pub s_nlnno: U32<BE>,
+ /// Flags to define the section type.
+ pub s_flags: U32<BE>,
+ /// Reserved.
+ pub s_reserve: U32<BE>,
+}
+
+// Values for `s_flags`.
+//
+/// "regular" section
+pub const STYP_REG: u16 = 0x00;
+/// Specifies a pad section. A section of this type is used to provide alignment
+/// padding between sections within an XCOFF executable object file. This section
+/// header type is obsolete since padding is allowed in an XCOFF file without a
+/// corresponding pad section header.
+pub const STYP_PAD: u16 = 0x08;
+/// Specifies a DWARF debugging section, which provide source file and symbol
+/// information for the symbolic debugger.
+pub const STYP_DWARF: u16 = 0x10;
+/// Specifies an executable text (code) section. A section of this type contains
+/// the executable instructions of a program.
+pub const STYP_TEXT: u16 = 0x20;
+/// Specifies an initialized data section. A section of this type contains the
+/// initialized data and the TOC of a program.
+pub const STYP_DATA: u16 = 0x40;
+/// Specifies an uninitialized data section. A section header of this type
+/// defines the uninitialized data of a program.
+pub const STYP_BSS: u16 = 0x80;
+/// Specifies an exception section. A section of this type provides information
+/// to identify the reason that a trap or exception occurred within an executable
+/// object program.
+pub const STYP_EXCEPT: u16 = 0x0100;
+/// Specifies a comment section. A section of this type provides comments or data
+/// to special processing utility programs.
+pub const STYP_INFO: u16 = 0x0200;
+/// Specifies an initialized thread-local data section.
+pub const STYP_TDATA: u16 = 0x0400;
+/// Specifies an uninitialized thread-local data section.
+pub const STYP_TBSS: u16 = 0x0800;
+/// Specifies a loader section. A section of this type contains object file
+/// information for the system loader to load an XCOFF executable. The information
+/// includes imported symbols, exported symbols, relocation data, type-check
+/// information, and shared object names.
+pub const STYP_LOADER: u16 = 0x1000;
+/// Specifies a debug section. A section of this type contains stabstring
+/// information used by the symbolic debugger.
+pub const STYP_DEBUG: u16 = 0x2000;
+/// Specifies a type-check section. A section of this type contains
+/// parameter/argument type-check strings used by the binder.
+pub const STYP_TYPCHK: u16 = 0x4000;
+/// Specifies a relocation or line-number field overflow section. A section
+/// header of this type contains the count of relocation entries and line
+/// number entries for some other section. This section header is required
+/// when either of the counts exceeds 65,534.
+pub const STYP_OVRFLO: u16 = 0x8000;
+
+pub const SIZEOF_SYMBOL: usize = 18;
+
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct SymbolBytes(pub [u8; SIZEOF_SYMBOL]);
+
+/// Symbol table entry.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Symbol32 {
+ /// Symbol name.
+ ///
+ /// If first 4 bytes are 0, then second 4 bytes are offset into string table.
+ pub n_name: [u8; 8],
+ /// Symbol value; storage class-dependent.
+ pub n_value: U32<BE>,
+ /// Section number of symbol.
+ pub n_scnum: I16<BE>,
+ /// Basic and derived type specification.
+ pub n_type: U16<BE>,
+ /// Storage class of symbol.
+ pub n_sclass: u8,
+ /// Number of auxiliary entries.
+ pub n_numaux: u8,
+}
+
+/// Symbol table entry.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Symbol64 {
+ /// Symbol value; storage class-dependent.
+ pub n_value: U64<BE>,
+ /// Offset of the name in string table or .debug section.
+ pub n_offset: U32<BE>,
+ /// Section number of symbol.
+ pub n_scnum: I16<BE>,
+ /// Basic and derived type specification.
+ pub n_type: U16<BE>,
+ /// Storage class of symbol.
+ pub n_sclass: u8,
+ /// Number of auxiliary entries.
+ pub n_numaux: u8,
+}
+
+// Values for `n_scnum`.
+//
+/// A special symbolic debugging symbol.
+pub const N_DEBUG: i16 = -2;
+/// An absolute symbol. The symbol has a value but is not relocatable.
+pub const N_ABS: i16 = -1;
+/// An undefined external symbol.
+pub const N_UNDEF: i16 = 0;
+
+// Vlaues for `n_type`.
+//
+/// Values for visibility as they would appear when encoded in the high 4 bits
+/// of the 16-bit unsigned n_type field of symbol table entries. Valid for
+/// 32-bit XCOFF only when the o_vstamp in the auxiliary header is greater than 1.
+pub const SYM_V_MASK: u16 = 0xF000;
+pub const SYM_V_INTERNAL: u16 = 0x1000;
+pub const SYM_V_HIDDEN: u16 = 0x2000;
+pub const SYM_V_PROTECTED: u16 = 0x3000;
+pub const SYM_V_EXPORTED: u16 = 0x4000;
+
+// Values for `n_sclass`.
+//
+// Storage classes used for symbolic debugging symbols.
+//
+/// Source file name and compiler information.
+pub const C_FILE: u8 = 103;
+/// Beginning of include file.
+pub const C_BINCL: u8 = 108;
+/// Ending of include file.
+pub const C_EINCL: u8 = 109;
+/// Global variable.
+pub const C_GSYM: u8 = 128;
+/// Statically allocated symbol.
+pub const C_STSYM: u8 = 133;
+/// Beginning of common block.
+pub const C_BCOMM: u8 = 135;
+/// End of common block.
+pub const C_ECOMM: u8 = 137;
+/// Alternate entry.
+pub const C_ENTRY: u8 = 141;
+/// Beginning of static block.
+pub const C_BSTAT: u8 = 143;
+/// End of static block.
+pub const C_ESTAT: u8 = 144;
+/// Global thread-local variable.
+pub const C_GTLS: u8 = 145;
+/// Static thread-local variable.
+pub const C_STTLS: u8 = 146;
+/// DWARF section symbol.
+pub const C_DWARF: u8 = 112;
+//
+// Storage classes used for absolute symbols.
+//
+/// Automatic variable allocated on stack.
+pub const C_LSYM: u8 = 129;
+/// Argument to subroutine allocated on stack.
+pub const C_PSYM: u8 = 130;
+/// Register variable.
+pub const C_RSYM: u8 = 131;
+/// Argument to function or procedure stored in register.
+pub const C_RPSYM: u8 = 132;
+/// Local member of common block.
+pub const C_ECOML: u8 = 136;
+/// Function or procedure.
+pub const C_FUN: u8 = 142;
+//
+// Storage classes used for undefined external symbols or symbols of general sections.
+//
+/// External symbol.
+pub const C_EXT: u8 = 2;
+/// Weak external symbol.
+pub const C_WEAKEXT: u8 = 111;
+//
+// Storage classes used for symbols of general sections.
+//
+/// Symbol table entry marked for deletion.
+pub const C_NULL: u8 = 0;
+/// Static.
+pub const C_STAT: u8 = 3;
+/// Beginning or end of inner block.
+pub const C_BLOCK: u8 = 100;
+/// Beginning or end of function.
+pub const C_FCN: u8 = 101;
+/// Un-named external symbol.
+pub const C_HIDEXT: u8 = 107;
+/// Comment string in .info section.
+pub const C_INFO: u8 = 110;
+/// Declaration of object (type).
+pub const C_DECL: u8 = 140;
+//
+// Storage classes - Obsolete/Undocumented.
+//
+/// Automatic variable.
+pub const C_AUTO: u8 = 1;
+/// Register variable.
+pub const C_REG: u8 = 4;
+/// External definition.
+pub const C_EXTDEF: u8 = 5;
+/// Label.
+pub const C_LABEL: u8 = 6;
+/// Undefined label.
+pub const C_ULABEL: u8 = 7;
+/// Member of structure.
+pub const C_MOS: u8 = 8;
+/// Function argument.
+pub const C_ARG: u8 = 9;
+/// Structure tag.
+pub const C_STRTAG: u8 = 10;
+/// Member of union.
+pub const C_MOU: u8 = 11;
+/// Union tag.
+pub const C_UNTAG: u8 = 12;
+/// Type definition.
+pub const C_TPDEF: u8 = 13;
+/// Undefined static.
+pub const C_USTATIC: u8 = 14;
+/// Enumeration tag.
+pub const C_ENTAG: u8 = 15;
+/// Member of enumeration.
+pub const C_MOE: u8 = 16;
+/// Register parameter.
+pub const C_REGPARM: u8 = 17;
+/// Bit field.
+pub const C_FIELD: u8 = 18;
+/// End of structure.
+pub const C_EOS: u8 = 102;
+/// Duplicate tag.
+pub const C_ALIAS: u8 = 105;
+/// Special storage class for external.
+pub const C_HIDDEN: u8 = 106;
+/// Physical end of function.
+pub const C_EFCN: u8 = 255;
+/// Reserved.
+pub const C_TCSYM: u8 = 134;
+
+/// File Auxiliary Entry for C_FILE Symbols.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct FileAux32 {
+ /// The source file name or compiler-related string.
+ ///
+ /// If first 4 bytes are 0, then second 4 bytes are offset into string table.
+ pub x_fname: [u8; 8],
+ /// Pad size for file name.
+ pub x_fpad: [u8; 6],
+ /// The source-file string type.
+ pub x_ftype: u8,
+ /// Reserved.
+ pub x_freserve: [u8; 3],
+}
+
+/// File Auxiliary Entry for C_FILE Symbols.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct FileAux64 {
+ /// The source file name or compiler-related string.
+ ///
+ /// If first 4 bytes are 0, then second 4 bytes are offset into string table.
+ pub x_fname: [u8; 8],
+ /// Pad size for file name.
+ pub x_fpad: [u8; 6],
+ /// The source-file string type.
+ pub x_ftype: u8,
+ /// Reserved.
+ pub x_freserve: [u8; 2],
+ /// Specifies the type of auxiliary entry. Contains _AUX_FILE for this auxiliary entry.
+ pub x_auxtype: u8,
+}
+
+// Values for `x_ftype`.
+//
+/// Specifies the source-file name.
+pub const XFT_FN: u8 = 0;
+/// Specifies the compiler time stamp.
+pub const XFT_CT: u8 = 1;
+/// Specifies the compiler version number.
+pub const XFT_CV: u8 = 2;
+/// Specifies compiler-defined information.
+pub const XFT_CD: u8 = 128;
+
+/// Csect auxiliary entry for C_EXT, C_WEAKEXT, and C_HIDEXT symbols.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct CsectAux32 {
+ /// Section length.
+ pub x_scnlen: U32<BE>,
+ /// Offset of parameter type-check hash in .typchk section.
+ pub x_parmhash: U32<BE>,
+ /// .typchk section number.
+ pub x_snhash: U16<BE>,
+ /// Symbol alignment and type.
+ pub x_smtyp: u8,
+ /// Storage mapping class.
+ pub x_smclas: u8,
+ /// Reserved.
+ pub x_stab: U32<BE>,
+ /// x_snstab.
+ pub x_snstab: U16<BE>,
+}
+
+/// Csect auxiliary entry for C_EXT, C_WEAKEXT, and C_HIDEXT symbols.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct CsectAux64 {
+ /// Low 4 bytes of section length.
+ pub x_scnlen_lo: U32<BE>,
+ /// Offset of parameter type-check hash in .typchk section.
+ pub x_parmhash: U32<BE>,
+ /// .typchk section number.
+ pub x_snhash: U16<BE>,
+ /// Symbol alignment and type.
+ pub x_smtyp: u8,
+ /// Storage mapping class.
+ pub x_smclas: u8,
+ /// High 4 bytes of section length.
+ pub x_scnlen_hi: U32<BE>,
+ /// Reserved.
+ pub pad: u8,
+ /// Contains _AUX_CSECT; indicates type of auxiliary entry.
+ pub x_auxtype: u8,
+}
+
+// Values for `x_smtyp`.
+//
+/// External reference.
+pub const XTY_ER: u8 = 0;
+/// Csect definition for initialized storage.
+pub const XTY_SD: u8 = 1;
+/// Defines an entry point to an initialized csect.
+pub const XTY_LD: u8 = 2;
+/// Common csect definition. For uninitialized storage.
+pub const XTY_CM: u8 = 3;
+
+// Values for `x_smclas`.
+//
+// READ ONLY CLASSES
+//
+/// Program Code
+pub const XMC_PR: u8 = 0;
+/// Read Only Constant
+pub const XMC_RO: u8 = 1;
+/// Debug Dictionary Table
+pub const XMC_DB: u8 = 2;
+/// Global Linkage (Interfile Interface Code)
+pub const XMC_GL: u8 = 6;
+/// Extended Operation (Pseudo Machine Instruction)
+pub const XMC_XO: u8 = 7;
+/// Supervisor Call (32-bit process only)
+pub const XMC_SV: u8 = 8;
+/// Supervisor Call for 64-bit process
+pub const XMC_SV64: u8 = 17;
+/// Supervisor Call for both 32- and 64-bit processes
+pub const XMC_SV3264: u8 = 18;
+/// Traceback Index csect
+pub const XMC_TI: u8 = 12;
+/// Traceback Table csect
+pub const XMC_TB: u8 = 13;
+//
+// READ WRITE CLASSES
+//
+/// Read Write Data
+pub const XMC_RW: u8 = 5;
+/// TOC Anchor for TOC Addressability
+pub const XMC_TC0: u8 = 15;
+/// General TOC item
+pub const XMC_TC: u8 = 3;
+/// Scalar data item in the TOC
+pub const XMC_TD: u8 = 16;
+/// Descriptor csect
+pub const XMC_DS: u8 = 10;
+/// Unclassified - Treated as Read Write
+pub const XMC_UA: u8 = 4;
+/// BSS class (uninitialized static internal)
+pub const XMC_BS: u8 = 9;
+/// Un-named Fortran Common
+pub const XMC_UC: u8 = 11;
+/// Initialized thread-local variable
+pub const XMC_TL: u8 = 20;
+/// Uninitialized thread-local variable
+pub const XMC_UL: u8 = 21;
+/// Symbol mapped at the end of TOC
+pub const XMC_TE: u8 = 22;
+
+/// Function auxiliary entry.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct FunAux32 {
+ /// File offset to exception table entry.
+ pub x_exptr: U32<BE>,
+ /// Size of function in bytes.
+ pub x_fsize: U32<BE>,
+ /// File pointer to line number
+ pub x_lnnoptr: U32<BE>,
+ /// Symbol table index of next entry beyond this function.
+ pub x_endndx: U32<BE>,
+ /// Pad
+ pub pad: U16<BE>,
+}
+
+/// Function auxiliary entry.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct FunAux64 {
+ /// File pointer to line number
+ pub x_lnnoptr: U64<BE>,
+ /// Size of function in bytes.
+ pub x_fsize: U32<BE>,
+ /// Symbol table index of next entry beyond this function.
+ pub x_endndx: U32<BE>,
+ /// Pad
+ pub pad: u8,
+ /// Contains _AUX_FCN; Type of auxiliary entry.
+ pub x_auxtype: u8,
+}
+
+/// Exception auxiliary entry. (XCOFF64 only)
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct ExpAux {
+ /// File offset to exception table entry.
+ pub x_exptr: U64<BE>,
+ /// Size of function in bytes.
+ pub x_fsize: U32<BE>,
+ /// Symbol table index of next entry beyond this function.
+ pub x_endndx: U32<BE>,
+ /// Pad
+ pub pad: u8,
+ /// Contains _AUX_EXCEPT; Type of auxiliary entry
+ pub x_auxtype: u8,
+}
+
+/// Block auxiliary entry for the C_BLOCK and C_FCN Symbols.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct BlockAux32 {
+ /// Reserved.
+ pub pad: [u8; 2],
+ /// High-order 2 bytes of the source line number.
+ pub x_lnnohi: U16<BE>,
+ /// Low-order 2 bytes of the source line number.
+ pub x_lnnolo: U16<BE>,
+ /// Reserved.
+ pub pad2: [u8; 12],
+}
+
+/// Block auxiliary entry for the C_BLOCK and C_FCN Symbols.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct BlockAux64 {
+ /// Source line number.
+ pub x_lnno: U32<BE>,
+ /// Reserved.
+ pub pad: [u8; 13],
+ /// Contains _AUX_SYM; Type of auxiliary entry.
+ pub x_auxtype: u8,
+}
+
+/// Section auxiliary entry for the C_STAT Symbol. (XCOFF32 Only)
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct StatAux {
+ /// Section length.
+ pub x_scnlen: U32<BE>,
+ /// Number of relocation entries.
+ pub x_nreloc: U16<BE>,
+ /// Number of line numbers.
+ pub x_nlinno: U16<BE>,
+ /// Reserved.
+ pub pad: [u8; 10],
+}
+
+/// Section auxiliary entry Format for C_DWARF symbols.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct DwarfAux32 {
+ /// Length of portion of section represented by symbol.
+ pub x_scnlen: U32<BE>,
+ /// Reserved.
+ pub pad: [u8; 4],
+ /// Number of relocation entries in section.
+ pub x_nreloc: U32<BE>,
+ /// Reserved.
+ pub pad2: [u8; 6],
+}
+
+/// Section auxiliary entry Format for C_DWARF symbols.
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct DwarfAux64 {
+ /// Length of portion of section represented by symbol.
+ pub x_scnlen: U64<BE>,
+ /// Number of relocation entries in section.
+ pub x_nreloc: U64<BE>,
+ /// Reserved.
+ pub pad: u8,
+ /// Contains _AUX_SECT; Type of Auxillary entry.
+ pub x_auxtype: u8,
+}
+
+// Values for `x_auxtype`
+//
+/// Identifies an exception auxiliary entry.
+pub const AUX_EXCEPT: u8 = 255;
+/// Identifies a function auxiliary entry.
+pub const AUX_FCN: u8 = 254;
+/// Identifies a symbol auxiliary entry.
+pub const AUX_SYM: u8 = 253;
+/// Identifies a file auxiliary entry.
+pub const AUX_FILE: u8 = 252;
+/// Identifies a csect auxiliary entry.
+pub const AUX_CSECT: u8 = 251;
+/// Identifies a SECT auxiliary entry.
+pub const AUX_SECT: u8 = 250;
+
+/// Relocation table entry
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Rel32 {
+ /// Virtual address (position) in section to be relocated.
+ pub r_vaddr: U32<BE>,
+ /// Symbol table index of item that is referenced.
+ pub r_symndx: U32<BE>,
+ /// Relocation size and information.
+ pub r_rsize: u8,
+ /// Relocation type.
+ pub r_rtype: u8,
+}
+
+/// Relocation table entry
+#[derive(Debug, Clone, Copy)]
+#[repr(C)]
+pub struct Rel64 {
+ /// Virtual address (position) in section to be relocated.
+ pub r_vaddr: U64<BE>,
+ /// Symbol table index of item that is referenced.
+ pub r_symndx: U32<BE>,
+ /// Relocation size and information.
+ pub r_rsize: u8,
+ /// Relocation type.
+ pub r_rtype: u8,
+}
+
+// Values for `r_rtype`.
+//
+/// Positive relocation.
+pub const R_POS: u8 = 0x00;
+/// Positive indirect load relocation.
+pub const R_RL: u8 = 0x0c;
+/// Positive load address relocation. Modifiable instruction.
+pub const R_RLA: u8 = 0x0d;
+/// Negative relocation.
+pub const R_NEG: u8 = 0x01;
+/// Relative to self relocation.
+pub const R_REL: u8 = 0x02;
+/// Relative to the TOC relocation.
+pub const R_TOC: u8 = 0x03;
+/// TOC relative indirect load relocation.
+pub const R_TRL: u8 = 0x12;
+/// Relative to the TOC or to the thread-local storage base relocation.
+pub const R_TRLA: u8 = 0x13;
+/// Global linkage-external TOC address relocation.
+pub const R_GL: u8 = 0x05;
+/// Local object TOC address relocation.
+pub const R_TCL: u8 = 0x06;
+/// A non-relocating relocation.
+pub const R_REF: u8 = 0x0f;
+/// Branch absolute relocation. References a non-modifiable instruction.
+pub const R_BA: u8 = 0x08;
+/// Branch relative to self relocation. References a non-modifiable instruction.
+pub const R_BR: u8 = 0x0a;
+/// Branch absolute relocation. References a modifiable instruction.
+pub const R_RBA: u8 = 0x18;
+/// Branch relative to self relocation. References a modifiable instruction.
+pub const R_RBR: u8 = 0x1a;
+/// General-dynamic reference to TLS symbol.
+pub const R_TLS: u8 = 0x20;
+/// Initial-exec reference to TLS symbol.
+pub const R_TLS_IE: u8 = 0x21;
+/// Local-dynamic reference to TLS symbol.
+pub const R_TLS_LD: u8 = 0x22;
+/// Local-exec reference to TLS symbol.
+pub const R_TLS_LE: u8 = 0x23;
+/// Module reference to TLS.
+pub const R_TLSM: u8 = 0x24;
+/// Module reference to the local TLS storage.
+pub const R_TLSML: u8 = 0x25;
+/// Relative to TOC upper.
+pub const R_TOCU: u8 = 0x30;
+/// Relative to TOC lower.
+pub const R_TOCL: u8 = 0x31;
+
+unsafe_impl_pod!(
+ FileHeader32,
+ FileHeader64,
+ AuxHeader32,
+ AuxHeader64,
+ SectionHeader32,
+ SectionHeader64,
+ SymbolBytes,
+ Symbol32,
+ Symbol64,
+ FileAux32,
+ FileAux64,
+ CsectAux32,
+ CsectAux64,
+ FunAux32,
+ FunAux64,
+ ExpAux,
+ BlockAux32,
+ BlockAux64,
+ StatAux,
+ DwarfAux32,
+ DwarfAux64,
+ Rel32,
+ Rel64,
+);