#![allow(missing_docs)]
#[cfg(feature = "names")]
use crate::constants::{ConstantNames, FlagNames};
use crate::endian::{BigEndian as BE, I16, U16, U32, U64};
use crate::pod::Pod;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FileHeader32 {
pub f_magic: U16<BE>,
pub f_nscns: U16<BE>,
pub f_timdat: U32<BE>,
pub f_symptr: U32<BE>,
pub f_nsyms: U32<BE>,
pub f_opthdr: U16<BE>,
pub f_flags: U16<BE, FileFlags>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FileHeader64 {
pub f_magic: U16<BE>,
pub f_nscns: U16<BE>,
pub f_timdat: U32<BE>,
pub f_symptr: U64<BE>,
pub f_opthdr: U16<BE>,
pub f_flags: U16<BE, FileFlags>,
pub f_nsyms: U32<BE>,
}
pub const MAGIC_64: u16 = 0x01F7;
pub const MAGIC_32: u16 = 0x01DF;
newtype!(
struct FileFlags(u16);
);
newtype_flag_names!(NAMES_F: FileFlags(u16) = {
F_RELFLG = 0x0001,
F_EXEC = 0x0002,
F_LNNO = 0x0004,
F_FDPR_PROF = 0x0010,
F_FDPR_OPTI = 0x0020,
F_DSA = 0x0040,
F_VARPG = 0x0100,
F_DYNLOAD = 0x1000,
F_SHROBJ = 0x2000,
F_LOADONLY = 0x4000,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct AuxHeader32 {
pub o_mflag: U16<BE>,
pub o_vstamp: U16<BE>,
pub o_tsize: U32<BE>,
pub o_dsize: U32<BE>,
pub o_bsize: U32<BE>,
pub o_entry: U32<BE>,
pub o_text_start: U32<BE>,
pub o_data_start: U32<BE>,
pub o_toc: U32<BE>,
pub o_snentry: U16<BE>,
pub o_sntext: U16<BE>,
pub o_sndata: U16<BE>,
pub o_sntoc: U16<BE>,
pub o_snloader: U16<BE>,
pub o_snbss: U16<BE>,
pub o_algntext: U16<BE>,
pub o_algndata: U16<BE>,
pub o_modtype: U16<BE>,
pub o_cpuflag: u8,
pub o_cputype: u8,
pub o_maxstack: U32<BE>,
pub o_maxdata: U32<BE>,
pub o_debugger: U32<BE>,
pub o_textpsize: u8,
pub o_datapsize: u8,
pub o_stackpsize: u8,
pub o_flags: u8,
pub o_sntdata: U16<BE>,
pub o_sntbss: U16<BE>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct AuxHeader64 {
pub o_mflag: U16<BE>,
pub o_vstamp: U16<BE>,
pub o_debugger: U32<BE>,
pub o_text_start: U64<BE>,
pub o_data_start: U64<BE>,
pub o_toc: U64<BE>,
pub o_snentry: U16<BE>,
pub o_sntext: U16<BE>,
pub o_sndata: U16<BE>,
pub o_sntoc: U16<BE>,
pub o_snloader: U16<BE>,
pub o_snbss: U16<BE>,
pub o_algntext: U16<BE>,
pub o_algndata: U16<BE>,
pub o_modtype: U16<BE>,
pub o_cpuflag: u8,
pub o_cputype: u8,
pub o_textpsize: u8,
pub o_datapsize: u8,
pub o_stackpsize: u8,
pub o_flags: u8,
pub o_tsize: U64<BE>,
pub o_dsize: U64<BE>,
pub o_bsize: U64<BE>,
pub o_entry: U64<BE>,
pub o_maxstack: U64<BE>,
pub o_maxdata: U64<BE>,
pub o_sntdata: U16<BE>,
pub o_sntbss: U16<BE>,
pub o_x64flags: U16<BE>,
pub o_resv3a: U16<BE>,
pub o_resv3: [U32<BE>; 2],
}
pub const AOUTHSZ_SHORT: u16 = 28;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SectionHeader32 {
pub s_name: [u8; 8],
pub s_paddr: U32<BE>,
pub s_vaddr: U32<BE>,
pub s_size: U32<BE>,
pub s_scnptr: U32<BE>,
pub s_relptr: U32<BE>,
pub s_lnnoptr: U32<BE>,
pub s_nreloc: U16<BE>,
pub s_nlnno: U16<BE>,
pub s_flags: U32<BE, SectionFlags>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SectionHeader64 {
pub s_name: [u8; 8],
pub s_paddr: U64<BE>,
pub s_vaddr: U64<BE>,
pub s_size: U64<BE>,
pub s_scnptr: U64<BE>,
pub s_relptr: U64<BE>,
pub s_lnnoptr: U64<BE>,
pub s_nreloc: U32<BE>,
pub s_nlnno: U32<BE>,
pub s_flags: U32<BE, SectionFlags>,
pub s_reserve: U32<BE>,
}
newtype!(
struct SectionFlags(u32);
);
const SFLAGS_TYPE_MASK: u32 = 0x0000_ffff;
const SFLAGS_SUBTYPE_MASK: u32 = 0xffff_0000;
impl core::fmt::Debug for SectionFlags {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.typ().fmt(f)?;
let subtype = self.subtype();
if subtype.0 != 0 {
#[cfg(feature = "names")]
if self.typ() == STYP_DWARF {
if let Some(name) = SectionFlags::NAMES_DWARF.name(subtype) {
return write!(f, " | {}", name);
}
}
write!(f, " | {:x}", subtype.0)?;
}
Ok(())
}
}
impl SectionFlags {
#[cfg(feature = "names")]
pub const NAMES_DWARF: &ConstantNames<SectionFlags> = &NAMES_SSUBTYP_DWARF;
pub fn typ(self) -> SectionType {
SectionType(self.0 as u16)
}
pub fn with_type(self, typ: SectionType) -> SectionFlags {
SectionFlags(self.0 & !SFLAGS_TYPE_MASK | u32::from(typ.0))
}
pub fn subtype(self) -> SectionFlags {
SectionFlags(self.0 & SFLAGS_SUBTYPE_MASK)
}
pub fn with_subtype(self, subtype: SectionFlags) -> SectionFlags {
SectionFlags(self.0 & !SFLAGS_SUBTYPE_MASK | subtype.0 & SFLAGS_SUBTYPE_MASK)
}
}
impl From<SectionType> for SectionFlags {
fn from(value: SectionType) -> Self {
SectionFlags(u32::from(value.0))
}
}
impl core::ops::BitOr<SectionFlags> for SectionType {
type Output = SectionFlags;
fn bitor(self, subtype: SectionFlags) -> SectionFlags {
subtype.with_type(self)
}
}
newtype!(
struct SectionType(u16);
);
pub const STYP_REG: SectionType = SectionType(0x00);
newtype_flag_names!(NAMES_STYP: SectionType(u16) = {
STYP_PAD = 0x08,
STYP_DWARF = 0x10,
STYP_TEXT = 0x20,
STYP_DATA = 0x40,
STYP_BSS = 0x80,
STYP_EXCEPT = 0x0100,
STYP_INFO = 0x0200,
STYP_TDATA = 0x0400,
STYP_TBSS = 0x0800,
STYP_LOADER = 0x1000,
STYP_DEBUG = 0x2000,
STYP_TYPCHK = 0x4000,
STYP_OVRFLO = 0x8000,
});
constant_names!(NAMES_SSUBTYP_DWARF: SectionFlags(u32) = {
SSUBTYP_DWINFO = 0x10000,
SSUBTYP_DWLINE = 0x20000,
SSUBTYP_DWPBNMS = 0x30000,
SSUBTYP_DWPBTYP = 0x40000,
SSUBTYP_DWARNGE = 0x50000,
SSUBTYP_DWABREV = 0x60000,
SSUBTYP_DWSTR = 0x70000,
SSUBTYP_DWRNGES = 0x80000,
SSUBTYP_DWLOC = 0x90000,
SSUBTYP_DWFRAME = 0xA0000,
SSUBTYP_DWMAC = 0xB0000,
});
pub const SIZEOF_SYMBOL: usize = 18;
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct SymbolBytes(pub [u8; SIZEOF_SYMBOL]);
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Symbol32 {
pub n_name: [u8; 8],
pub n_value: U32<BE>,
pub n_scnum: I16<BE, SymbolSection>,
pub n_type: U16<BE, SymbolType>,
pub n_sclass: SymbolClass,
pub n_numaux: u8,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Symbol64 {
pub n_value: U64<BE>,
pub n_offset: U32<BE>,
pub n_scnum: I16<BE, SymbolSection>,
pub n_type: U16<BE, SymbolType>,
pub n_sclass: SymbolClass,
pub n_numaux: u8,
}
newtype!(
struct SymbolSection(i16);
);
impl SymbolSection {
pub fn is_reserved(self) -> bool {
self.0 <= 0
}
pub fn index(self) -> Option<u16> {
if self.0 > 0 {
Some(self.0 as u16)
} else {
None
}
}
}
newtype_constant_names!(NAMES_N: SymbolSection(i16) = {
N_DEBUG = -2,
N_ABS = -1,
N_UNDEF = 0,
});
newtype!(
struct SymbolType(u16);
);
newtype_flag_names!(SymbolType(u16) = {});
flag_names!(NAMES_SYM_T_EXT: SymbolType(u16) = {
_ = SYM_V_MASK => NAMES_SYM_V,
SYM_DT_FCN = DT_FCN << N_BTSHFT,
});
const DT_FCN: u16 = 2;
const N_BTSHFT: usize = 4;
impl SymbolType {
#[cfg(feature = "names")]
pub const NAMES_EXT: &FlagNames<SymbolType> = &NAMES_SYM_T_EXT;
pub fn visibility(self) -> SymbolVisibility {
SymbolVisibility(self.0 & SYM_V_MASK)
}
pub fn is_function(self) -> bool {
self.contains(SYM_DT_FCN)
}
}
newtype!(
struct SymbolVisibility(u16);
);
pub const SYM_V_MASK: u16 = 0xF000;
newtype_constant_names!(NAMES_SYM_V: SymbolVisibility(u16) = {
SYM_V_INTERNAL = 0x1000,
SYM_V_HIDDEN = 0x2000,
SYM_V_PROTECTED = 0x3000,
SYM_V_EXPORTED = 0x4000,
});
impl From<SymbolVisibility> for SymbolType {
fn from(value: SymbolVisibility) -> Self {
SymbolType(value.0 & SYM_V_MASK)
}
}
impl From<SymbolType> for SymbolVisibility {
fn from(value: SymbolType) -> Self {
value.visibility()
}
}
newtype!(
#[repr(transparent)]
struct SymbolClass(u8);
);
newtype_constant_names!(NAMES_C: SymbolClass(u8) = {
C_FILE = 103,
C_BINCL = 108,
C_EINCL = 109,
C_GSYM = 128,
C_STSYM = 133,
C_BCOMM = 135,
C_ECOMM = 137,
C_ENTRY = 141,
C_BSTAT = 143,
C_ESTAT = 144,
C_GTLS = 145,
C_STTLS = 146,
C_DWARF = 112,
C_LSYM = 129,
C_PSYM = 130,
C_RSYM = 131,
C_RPSYM = 132,
C_ECOML = 136,
C_FUN = 142,
C_EXT = 2,
C_WEAKEXT = 111,
C_NULL = 0,
C_STAT = 3,
C_BLOCK = 100,
C_FCN = 101,
C_HIDEXT = 107,
C_INFO = 110,
C_DECL = 140,
C_AUTO = 1,
C_REG = 4,
C_EXTDEF = 5,
C_LABEL = 6,
C_ULABEL = 7,
C_MOS = 8,
C_ARG = 9,
C_STRTAG = 10,
C_MOU = 11,
C_UNTAG = 12,
C_TPDEF = 13,
C_USTATIC = 14,
C_ENTAG = 15,
C_MOE = 16,
C_REGPARM = 17,
C_FIELD = 18,
C_EOS = 102,
C_ALIAS = 105,
C_HIDDEN = 106,
C_EFCN = 255,
C_TCSYM = 134,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FileAux32 {
pub x_fname: [u8; 8],
pub x_fpad: [u8; 6],
pub x_ftype: FileAuxType,
pub x_freserve: [u8; 3],
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FileAux64 {
pub x_fname: [u8; 8],
pub x_fpad: [u8; 6],
pub x_ftype: FileAuxType,
pub x_freserve: [u8; 2],
pub x_auxtype: AuxType,
}
newtype!(
#[repr(transparent)]
struct FileAuxType(u8);
);
newtype_constant_names!(NAMES_XFT: FileAuxType(u8) = {
XFT_FN = 0,
XFT_CT = 1,
XFT_CV = 2,
XFT_CD = 128,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsectAux32 {
pub x_scnlen: U32<BE>,
pub x_parmhash: U32<BE>,
pub x_snhash: U16<BE>,
pub x_smtyp: CsectAuxSmtyp,
pub x_smclas: CsectAuxClass,
pub x_stab: U32<BE>,
pub x_snstab: U16<BE>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct CsectAux64 {
pub x_scnlen_lo: U32<BE>,
pub x_parmhash: U32<BE>,
pub x_snhash: U16<BE>,
pub x_smtyp: CsectAuxSmtyp,
pub x_smclas: CsectAuxClass,
pub x_scnlen_hi: U32<BE>,
pub pad: u8,
pub x_auxtype: AuxType,
}
newtype!(
#[repr(transparent)]
struct CsectAuxSmtyp(u8);
);
impl core::fmt::Debug for CsectAuxSmtyp {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
self.typ().fmt(f)?;
let alignment = self.alignment();
if alignment != 0 {
write!(f, " | {}", alignment)?;
}
Ok(())
}
}
impl CsectAuxSmtyp {
pub fn new(typ: CsectAuxType, alignment: u8) -> Self {
CsectAuxSmtyp(typ.0 & 0x7 | alignment << 3)
}
pub fn alignment(self) -> u8 {
self.0 >> 3
}
pub fn typ(self) -> CsectAuxType {
CsectAuxType(self.0 & 0x7)
}
}
impl From<CsectAuxType> for CsectAuxSmtyp {
fn from(value: CsectAuxType) -> Self {
CsectAuxSmtyp(value.0 & 0x7)
}
}
newtype!(
struct CsectAuxType(u8);
);
newtype_constant_names!(NAMES_XTY: CsectAuxType(u8) = {
XTY_ER = 0,
XTY_SD = 1,
XTY_LD = 2,
XTY_CM = 3,
});
newtype!(
#[repr(transparent)]
struct CsectAuxClass(u8);
);
newtype_constant_names!(NAMES_XMC: CsectAuxClass(u8) = {
XMC_PR = 0,
XMC_RO = 1,
XMC_DB = 2,
XMC_GL = 6,
XMC_XO = 7,
XMC_SV = 8,
XMC_SV64 = 17,
XMC_SV3264 = 18,
XMC_TI = 12,
XMC_TB = 13,
XMC_RW = 5,
XMC_TC0 = 15,
XMC_TC = 3,
XMC_TD = 16,
XMC_DS = 10,
XMC_UA = 4,
XMC_BS = 9,
XMC_UC = 11,
XMC_TL = 20,
XMC_UL = 21,
XMC_TE = 22,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FunAux32 {
pub x_exptr: U32<BE>,
pub x_fsize: U32<BE>,
pub x_lnnoptr: U32<BE>,
pub x_endndx: U32<BE>,
pub pad: U16<BE>,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct FunAux64 {
pub x_lnnoptr: U64<BE>,
pub x_fsize: U32<BE>,
pub x_endndx: U32<BE>,
pub pad: u8,
pub x_auxtype: AuxType,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct ExpAux {
pub x_exptr: U64<BE>,
pub x_fsize: U32<BE>,
pub x_endndx: U32<BE>,
pub pad: u8,
pub x_auxtype: AuxType,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct BlockAux32 {
pub pad: [u8; 2],
pub x_lnnohi: U16<BE>,
pub x_lnnolo: U16<BE>,
pub pad2: [u8; 12],
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct BlockAux64 {
pub x_lnno: U32<BE>,
pub pad: [u8; 13],
pub x_auxtype: AuxType,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct StatAux {
pub x_scnlen: U32<BE>,
pub x_nreloc: U16<BE>,
pub x_nlinno: U16<BE>,
pub pad: [u8; 10],
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DwarfAux32 {
pub x_scnlen: U32<BE>,
pub pad: [u8; 4],
pub x_nreloc: U32<BE>,
pub pad2: [u8; 6],
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct DwarfAux64 {
pub x_scnlen: U64<BE>,
pub x_nreloc: U64<BE>,
pub pad: u8,
pub x_auxtype: AuxType,
}
newtype!(
#[repr(transparent)]
struct AuxType(u8);
);
newtype_constant_names!(NAMES_AUX: AuxType(u8) = {
AUX_EXCEPT = 255,
AUX_FCN = 254,
AUX_SYM = 253,
AUX_FILE = 252,
AUX_CSECT = 251,
AUX_SECT = 250,
});
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Rel32 {
pub r_vaddr: U32<BE>,
pub r_symndx: U32<BE>,
pub r_rsize: u8,
pub r_rtype: RelocationType,
}
#[derive(Debug, Clone, Copy)]
#[repr(C)]
pub struct Rel64 {
pub r_vaddr: U64<BE>,
pub r_symndx: U32<BE>,
pub r_rsize: u8,
pub r_rtype: RelocationType,
}
newtype!(
struct RelocationType(u8);
);
newtype_constant_names!(NAMES_REL_TYPE: RelocationType(u8) = {
R_POS = 0x00,
R_RL = 0x0c,
R_RLA = 0x0d,
R_NEG = 0x01,
R_REL = 0x02,
R_TOC = 0x03,
R_TRL = 0x12,
R_TRLA = 0x13,
R_GL = 0x05,
R_TCL = 0x06,
R_REF = 0x0f,
R_BA = 0x08,
R_BR = 0x0a,
R_RBA = 0x18,
R_RBR = 0x1a,
R_TLS = 0x20,
R_TLS_IE = 0x21,
R_TLS_LD = 0x22,
R_TLS_LE = 0x23,
R_TLSM = 0x24,
R_TLSML = 0x25,
R_TOCU = 0x30,
R_TOCL = 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,
);