Bug 1807630 - Update the object crate to 0.30.0. r=mstange,supply-chain-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D165528
This commit is contained in:
Mike Hommey 2022-12-30 21:49:55 +00:00
Родитель 5f638aa50c
Коммит 06330c8a21
40 изменённых файлов: 4153 добавлений и 130 удалений

4
Cargo.lock сгенерированный
Просмотреть файл

@ -3879,9 +3879,9 @@ dependencies = [
[[package]]
name = "object"
version = "0.28.4"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424"
checksum = "239da7f290cfa979f43f85a8efeee9a8a76d0827c356d37f9d3d7254d6b537fb"
dependencies = [
"memchr",
]

Просмотреть файл

@ -1270,6 +1270,11 @@ who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "1.13.1 -> 1.14.0"
[[audits.object]]
who = "Mike Hommey <mh+mozilla@glandium.org>"
criteria = "safe-to-deploy"
delta = "0.28.4 -> 0.30.0"
[[audits.ohttp]]
who = "Dana Keeler <dkeeler@mozilla.com>"
criteria = "safe-to-deploy"

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

87
third_party/rust/object/CHANGELOG.md поставляемый
Просмотреть файл

@ -2,6 +2,93 @@
--------------------------------------------------------------------------------
## 0.30.0
Released 2022/11/22.
### Breaking changes
* The minimum supported rust version for the `read` feature has changed to 1.52.0.
[#458](https://github.com/gimli-rs/object/pull/458)
* The minimum supported rust version for the `write` feature has changed to 1.61.0.
* Fixed endian handling in `read::elf::SymbolTable::shndx`.
[#458](https://github.com/gimli-rs/object/pull/458)
* Fixed endian handling in `read::pe::ResourceName`.
[#458](https://github.com/gimli-rs/object/pull/458)
* Changed definitions for LoongArch ELF header flags.
[#483](https://github.com/gimli-rs/object/pull/483)
### Changed
* Fixed parsing of multiple debug directory entries in `read::pe::PeFile::pdb_info`.
[#451](https://github.com/gimli-rs/object/pull/451)
* Changed the section name used when writing COFF stub symbols.
[#475](https://github.com/gimli-rs/object/pull/475)
### Added
* Added `read::pe::DataDirectories::delay_load_import_table`.
[#448](https://github.com/gimli-rs/object/pull/448)
* Added `read::macho::LoadCommandData::raw_data`.
[#449](https://github.com/gimli-rs/object/pull/449)
* Added ELF relocations for LoongArch ps ABI v2.
[#450](https://github.com/gimli-rs/object/pull/450)
* Added PowerPC support for Mach-O.
[#460](https://github.com/gimli-rs/object/pull/460)
* Added support for reading the AIX big archive format.
[#462](https://github.com/gimli-rs/object/pull/462)
[#467](https://github.com/gimli-rs/object/pull/467)
[#473](https://github.com/gimli-rs/object/pull/473)
* Added support for `RelocationEncoding::AArch64Call` when writing Mach-O files.
[#465](https://github.com/gimli-rs/object/pull/465)
* Added support for `RelocationKind::Relative` when writing RISC-V ELF files.
[#470](https://github.com/gimli-rs/object/pull/470)
* Added Xtensa architecture support for ELF.
[#481](https://github.com/gimli-rs/object/pull/481)
* Added `read::pe::ResourceName::raw_data`.
[#487](https://github.com/gimli-rs/object/pull/487)
--------------------------------------------------------------------------------
## 0.29.0
Released 2022/06/22.
### Breaking changes
* The `write` feature now has a minimum supported rust version of 1.56.1.
[#444](https://github.com/gimli-rs/object/pull/444)
* Added `os_abi` and `abi_version` fields to `FileFlags::Elf`.
[#438](https://github.com/gimli-rs/object/pull/438)
[#441](https://github.com/gimli-rs/object/pull/441)
### Changed
* Fixed handling of empty symbol tables in `read::elf::ElfFile::symbol_table` and
`read::elf::ElfFile::dynamic_symbol_table`.
[#443](https://github.com/gimli-rs/object/pull/443)
### Added
* Added more `ELF_OSABI_*` constants.
[#439](https://github.com/gimli-rs/object/pull/439)
--------------------------------------------------------------------------------
## 0.28.4
Released 2022/05/09.

13
third_party/rust/object/Cargo.toml поставляемый
Просмотреть файл

@ -12,12 +12,13 @@
[package]
edition = "2018"
name = "object"
version = "0.28.4"
version = "0.30.0"
exclude = [
"/.github",
"/testfiles",
]
description = "A unified interface for reading and writing object file formats."
readme = "README.md"
keywords = [
"object",
"elf",
@ -27,6 +28,7 @@ keywords = [
]
license = "Apache-2.0 OR MIT"
repository = "https://github.com/gimli-rs/object"
resolver = "2"
[package.metadata.docs.rs]
features = ["doc"]
@ -55,7 +57,7 @@ version = "1"
optional = true
[dependencies.hashbrown]
version = "0.11"
version = "0.13.1"
features = ["ahash"]
optional = true
default-features = false
@ -124,6 +126,12 @@ rustc-dep-of-std = [
]
std = ["memchr/std"]
unaligned = []
unstable = []
unstable-all = [
"all",
"unstable",
"xcoff",
]
wasm = ["wasmparser"]
write = [
"write_std",
@ -143,3 +151,4 @@ write_std = [
"indexmap/std",
"crc32fast/std",
]
xcoff = []

8
third_party/rust/object/README.md поставляемый
Просмотреть файл

@ -34,6 +34,14 @@ fn main() -> Result<(), Box<dyn Error>> {
See [`crates/examples`](crates/examples) for more examples.
## Minimum Supported Rust Version (MSRV)
Changes to MSRV are considered breaking changes. We are conservative about changing the MSRV,
but sometimes are required to due to dependencies. The MSRV is:
* 1.52.0 for the `read` feature and its dependencies.
* 1.61.0 for the `write` feature and its dependencies.
## License
Licensed under either of

54
third_party/rust/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,);

24
third_party/rust/object/src/common.rs поставляемый
Просмотреть файл

@ -24,6 +24,7 @@ pub enum Architecture {
S390x,
Sparc64,
Wasm32,
Xtensa,
}
impl Architecture {
@ -52,6 +53,7 @@ impl Architecture {
Architecture::S390x => Some(AddressSize::U64),
Architecture::Sparc64 => Some(AddressSize::U64),
Architecture::Wasm32 => Some(AddressSize::U32),
Architecture::Xtensa => Some(AddressSize::U32),
}
}
}
@ -88,6 +90,7 @@ pub enum BinaryFormat {
MachO,
Pe,
Wasm,
Xcoff,
}
/// The kind of a section.
@ -305,6 +308,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 +348,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.
@ -353,6 +363,10 @@ pub enum FileFlags {
None,
/// ELF file flags.
Elf {
/// `os_abi` field in the ELF file header.
os_abi: u8,
/// `abi_version` field in the ELF file header.
abi_version: u8,
/// `e_flags` field in the ELF file header.
e_flags: u32,
},
@ -366,6 +380,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.
@ -416,6 +435,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.

257
third_party/rust/object/src/elf.rs поставляемый
Просмотреть файл

@ -162,6 +162,8 @@ pub const ELFOSABI_GNU: u8 = 3;
///
/// Compatibility alias.
pub const ELFOSABI_LINUX: u8 = ELFOSABI_GNU;
/// GNU/Hurd.
pub const ELFOSABI_HURD: u8 = 4;
/// Sun Solaris.
pub const ELFOSABI_SOLARIS: u8 = 6;
/// IBM AIX.
@ -176,6 +178,16 @@ pub const ELFOSABI_TRU64: u8 = 10;
pub const ELFOSABI_MODESTO: u8 = 11;
/// OpenBSD.
pub const ELFOSABI_OPENBSD: u8 = 12;
/// OpenVMS.
pub const ELFOSABI_OPENVMS: u8 = 13;
/// Hewlett-Packard Non-Stop Kernel.
pub const ELFOSABI_NSK: u8 = 14;
/// AROS
pub const ELFOSABI_AROS: u8 = 15;
/// FenixOS
pub const ELFOSABI_FENIXOS: u8 = 16;
/// Nuxi CloudABI
pub const ELFOSABI_CLOUDABI: u8 = 17;
/// ARM EABI.
pub const ELFOSABI_ARM_AEABI: u8 = 64;
/// ARM.
@ -6239,18 +6251,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
@ -6360,6 +6371,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,

7
third_party/rust/object/src/lib.rs поставляемый
Просмотреть файл

@ -39,7 +39,7 @@
//!
//! /// Reads a file and displays the content of the ".boot" section.
//! fn main() -> Result<(), Box<dyn Error>> {
//! # #[cfg(feature = "read")] {
//! # #[cfg(all(feature = "read", feature = "std"))] {
//! let bin_data = fs::read("./multiboot2-binary.elf")?;
//! let obj_file = object::File::parse(&*bin_data)?;
//! if let Some(section) = obj_file.section_by_name(".boot") {
@ -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;

15
third_party/rust/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;

1
third_party/rust/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

90
third_party/rust/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> {

315
third_party/rust/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;
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)
}
},
}
let member = ArchiveMember::parse(self.data, &mut self.offset, self.names);
if member.is_err() {
self.offset = self.len;
}
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());
}
}

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -176,6 +176,7 @@ where
// We only support the 64-bit variant s390x here.
(elf::EM_S390, true) => Architecture::S390x,
(elf::EM_SPARCV9, true) => Architecture::Sparc64,
(elf::EM_XTENSA, false) => Architecture::Xtensa,
_ => Architecture::Unknown,
}
}
@ -264,6 +265,9 @@ where
}
fn symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>> {
if self.symbols.is_empty() {
return None;
}
Some(ElfSymbolTable {
endian: self.endian,
symbols: &self.symbols,
@ -279,6 +283,9 @@ where
}
fn dynamic_symbol_table(&'file self) -> Option<ElfSymbolTable<'data, 'file, Elf, R>> {
if self.dynamic_symbols.is_empty() {
return None;
}
Some(ElfSymbolTable {
endian: self.endian,
symbols: &self.dynamic_symbols,
@ -419,6 +426,8 @@ where
fn flags(&self) -> FileFlags {
FileFlags::Elf {
os_abi: self.header.e_ident().os_abi,
abi_version: self.header.e_ident().abi_version,
e_flags: self.header.e_flags(self.endian),
}
}

Просмотреть файл

@ -304,6 +304,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) {
@ -379,6 +392,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;

Просмотреть файл

@ -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,

Просмотреть файл

@ -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()))),
@ -369,7 +369,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,
},

Просмотреть файл

@ -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,
}
}

Просмотреть файл

@ -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,
}
}

Просмотреть файл

@ -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

25
third_party/rust/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)

Просмотреть файл

@ -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.

91
third_party/rust/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)
let debug_data_size = data_dir.size.get(LE) as usize;
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 debug_dirs = debug_data
.read_slice_at::<pe::ImageDebugDirectory>(0, count)
.read_error("Invalid PE debug dir size")?;
if debug_dir.typ.get(LE) != pe::IMAGE_DEBUG_TYPE_CODEVIEW {
return Ok(None);
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 age = info.read::<U32<LE>>().read_error("Invalid CodeView Age")?;
let path = info
.read_string()
.read_error("Invalid CodeView file path")?;
return Ok(Some(CodeView {
path: ByteString(path),
guid,
age: age.get(LE),
}));
}
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 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 path = info
.read_string()
.read_error("Invalid CodeView file path")?;
Ok(Some(CodeView {
path: ByteString(path),
guid,
age: age.get(LE),
}))
Ok(None)
}
fn has_debug_symbols(&self) -> bool {

114
third_party/rust/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))
}
}
}

Просмотреть файл

@ -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.

130
third_party/rust/object/src/read/xcoff/comdat.rs поставляемый Normal file
Просмотреть файл

@ -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
}
}

629
third_party/rust/object/src/read/xcoff/file.rs поставляемый Normal file
Просмотреть файл

@ -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
}
}

21
third_party/rust/object/src/read/xcoff/mod.rs поставляемый Normal file
Просмотреть файл

@ -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::*;

128
third_party/rust/object/src/read/xcoff/relocation.rs поставляемый Normal file
Просмотреть файл

@ -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
}
}

426
third_party/rust/object/src/read/xcoff/section.rs поставляемый Normal file
Просмотреть файл

@ -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")
}
}

115
third_party/rust/object/src/read/xcoff/segment.rs поставляемый Normal file
Просмотреть файл

@ -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!();
}
}

634
third_party/rust/object/src/read/xcoff/symbol.rs поставляемый Normal file
Просмотреть файл

@ -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
}
}

3
third_party/rust/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));

Просмотреть файл

@ -84,6 +84,7 @@ impl<'a> Object<'a> {
Architecture::Riscv32 => true,
Architecture::S390x => true,
Architecture::Sparc64 => true,
Architecture::Xtensa => true,
_ => {
return Err(Error(format!(
"unimplemented architecture {:?}",
@ -281,6 +282,7 @@ impl<'a> Object<'a> {
Architecture::Riscv64 => elf::EM_RISCV,
Architecture::S390x => elf::EM_S390,
Architecture::Sparc64 => elf::EM_SPARCV9,
Architecture::Xtensa => elf::EM_XTENSA,
_ => {
return Err(Error(format!(
"unimplemented architecture {:?}",
@ -288,14 +290,19 @@ impl<'a> Object<'a> {
)));
}
};
let e_flags = if let FileFlags::Elf { e_flags } = self.flags {
e_flags
let (os_abi, abi_version, e_flags) = if let FileFlags::Elf {
os_abi,
abi_version,
e_flags,
} = self.flags
{
(os_abi, abi_version, e_flags)
} else {
0
(elf::ELFOSABI_NONE, 0, 0)
};
writer.write_file_header(&FileHeader {
os_abi: elf::ELFOSABI_NONE,
abi_version: 0,
os_abi,
abi_version,
e_type,
e_machine,
e_entry: 0,
@ -523,6 +530,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)));
@ -569,6 +595,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!(
@ -653,6 +682,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

30
third_party/rust/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,

893
third_party/rust/object/src/xcoff.rs поставляемый Normal file
Просмотреть файл

@ -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,
);

Просмотреть файл

@ -248,6 +248,7 @@ fn elf_any() {
(Architecture::Riscv64, Endianness::Little),
(Architecture::S390x, Endianness::Big),
(Architecture::Sparc64, Endianness::Big),
(Architecture::Xtensa, Endianness::Little),
]
.iter()
.copied()

Просмотреть файл

@ -10,7 +10,7 @@ rustc-demangle = "0.1"
uuid = "1.0"
[dependencies.object]
version = "0.28"
version = "0.30"
optional = true
default-features = false
features = ["std", "read_core", "elf"]