yggdrasil-elf/src/types.rs
2016-06-21 14:44:53 +10:00

804 lines
28 KiB
Rust

use std::fmt;
/// Length of ELF file header platform-independent identification fields
pub const EI_NIDENT: usize = 16;
/// ELF magic number byte 1
pub const ELFMAG0: u8 = 0x7f;
/// ELF magic number byte 2
pub const ELFMAG1: u8 = 0x45;
/// ELF magic number byte 3
pub const ELFMAG2: u8 = 0x4c;
/// ELF magic number byte 4
pub const ELFMAG3: u8 = 0x46;
/// Location of ELF class field in ELF file header ident array
pub const EI_CLASS: usize = 4;
/// Location of data format field in ELF file header ident array
pub const EI_DATA: usize = 5;
/// Location of ELF version field in ELF file header ident array
pub const EI_VERSION: usize = 6;
/// Location of OS ABI field in ELF file header ident array
pub const EI_OSABI: usize = 7;
/// Location of ABI version field in ELF file header ident array
pub const EI_ABIVERSION: usize = 8;
/// Represents the ELF file class (32-bit vs 64-bit)
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Class(pub u8);
/// Invalid ELF file class
pub const ELFCLASSNONE : Class = Class(0);
/// 32-bit ELF file
pub const ELFCLASS32 : Class = Class(1);
/// 64-bit ELF file
pub const ELFCLASS64 : Class = Class(2);
impl fmt::Debug for Class {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for Class {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
ELFCLASSNONE => "Invalid",
ELFCLASS32 => "32-bit",
ELFCLASS64 => "64-bit",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
/// Represents the ELF file data format (little-endian vs big-endian)
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Data(pub u8);
/// Invalid ELF data format
pub const ELFDATANONE : Data = Data(0);
/// little-endian ELF file
pub const ELFDATA2LSB : Data = Data(1);
/// big-endian ELF file
pub const ELFDATA2MSB : Data = Data(2);
impl fmt::Debug for Data {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for Data {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
ELFDATANONE => "Invalid",
ELFDATA2LSB => "2's complement, little endian",
ELFDATA2MSB => "2's complement, big endian",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
/// Represents the ELF file version
///
/// This field represents the values both found in the e_ident byte array and the e_version field.
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Version(pub u32);
/// Invalid version
pub const EV_NONE : Version = Version(0);
/// Current version
pub const EV_CURRENT : Version = Version(1);
impl fmt::Debug for Version {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for Version {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
EV_NONE => "Invalid",
EV_CURRENT => "1 (Current)",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
/// Represents the ELF file OS ABI
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct OSABI(pub u8);
/// Defaults to Unix System V
pub const ELFOSABI_NONE : OSABI = OSABI(0);
/// Unix System V
pub const ELFOSABI_SYSV : OSABI = OSABI(0);
/// HP-UX
pub const ELFOSABI_HPUX : OSABI = OSABI(1);
/// NetBSD
pub const ELFOSABI_NETBSD : OSABI = OSABI(2);
/// Linux with GNU extensions
pub const ELFOSABI_LINUX : OSABI = OSABI(3);
/// Solaris
pub const ELFOSABI_SOLARIS : OSABI = OSABI(6);
/// AIX
pub const ELFOSABI_AIX : OSABI = OSABI(7);
/// SGI Irix
pub const ELFOSABI_IRIX : OSABI = OSABI(8);
/// FreeBSD
pub const ELFOSABI_FREEBSD : OSABI = OSABI(9);
/// Compaq TRU64 UNIX
pub const ELFOSABI_TRU64 : OSABI = OSABI(10);
/// Novell Modesto
pub const ELFOSABI_MODESTO : OSABI = OSABI(11);
/// OpenBSD
pub const ELFOSABI_OPENBSD : OSABI = OSABI(12);
impl fmt::Debug for OSABI {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for OSABI {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
ELFOSABI_SYSV => "UNIX System V",
ELFOSABI_HPUX => "HP-UX",
ELFOSABI_NETBSD => "NetBSD",
ELFOSABI_LINUX => "Linux with GNU extensions",
ELFOSABI_SOLARIS => "Solaris",
ELFOSABI_AIX => "AIX",
ELFOSABI_IRIX => "SGI Irix",
ELFOSABI_FREEBSD => "FreeBSD",
ELFOSABI_TRU64 => "Compaq TRU64 UNIX",
ELFOSABI_MODESTO => "Novell Modesto",
ELFOSABI_OPENBSD => "OpenBSD",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
/// Represents the ELF file type (object, executable, shared lib, core)
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Type(pub u16);
/// No file type
pub const ET_NONE : Type = Type(0);
/// Relocatable object file
pub const ET_REL : Type = Type(1);
/// Executable file
pub const ET_EXEC : Type = Type(2);
/// Shared library
pub const ET_DYN : Type = Type(3);
/// Core file
pub const ET_CORE : Type = Type(4);
impl fmt::Debug for Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for Type {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
ET_NONE => "No file type",
ET_REL => "Relocatable file",
ET_EXEC => "Executable file",
ET_DYN => "Shared object file",
ET_CORE => "Core file",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
/// Represents the ELF file machine architecture
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Machine(pub u16);
pub const EM_NONE : Machine = Machine(0);
pub const EM_M32 : Machine = Machine(1);
pub const EM_SPARC : Machine = Machine(2);
pub const EM_386 : Machine = Machine(3);
pub const EM_68K : Machine = Machine(4);
pub const EM_88K : Machine = Machine(5);
pub const EM_860 : Machine = Machine(7);
pub const EM_MIPS : Machine = Machine(8);
pub const EM_S370 : Machine = Machine(9);
pub const EM_MIPS_RS3_LE : Machine = Machine(10);
pub const EM_PARISC : Machine = Machine(15);
pub const EM_VPP500 : Machine = Machine(17);
pub const EM_SPARC32PLUS : Machine = Machine(18);
pub const EM_960 : Machine = Machine(19);
pub const EM_PPC : Machine = Machine(20);
pub const EM_PPC64 : Machine = Machine(21);
pub const EM_S390 : Machine = Machine(22);
pub const EM_V800 : Machine = Machine(36);
pub const EM_FR20 : Machine = Machine(37);
pub const EM_RH32 : Machine = Machine(38);
pub const EM_RCE : Machine = Machine(39);
pub const EM_ARM : Machine = Machine(40);
pub const EM_FAKE_ALPHA : Machine = Machine(41);
pub const EM_SH : Machine = Machine(42);
pub const EM_SPARCV9 : Machine = Machine(43);
pub const EM_TRICORE : Machine = Machine(44);
pub const EM_ARC : Machine = Machine(45);
pub const EM_H8_300 : Machine = Machine(46);
pub const EM_H8_300H : Machine = Machine(47);
pub const EM_H8S : Machine = Machine(48);
pub const EM_H8_500 : Machine = Machine(49);
pub const EM_IA_64 : Machine = Machine(50);
pub const EM_MIPS_X : Machine = Machine(51);
pub const EM_COLDFIRE : Machine = Machine(52);
pub const EM_68HC12 : Machine = Machine(53);
pub const EM_MMA : Machine = Machine(54);
pub const EM_PCP : Machine = Machine(55);
pub const EM_NCPU : Machine = Machine(56);
pub const EM_NDR1 : Machine = Machine(57);
pub const EM_STARCORE : Machine = Machine(58);
pub const EM_ME16 : Machine = Machine(59);
pub const EM_ST100 : Machine = Machine(60);
pub const EM_TINYJ : Machine = Machine(61);
pub const EM_X86_64 : Machine = Machine(62);
pub const EM_PDSP : Machine = Machine(63);
pub const EM_FX66 : Machine = Machine(66);
pub const EM_ST9PLUS : Machine = Machine(67);
pub const EM_ST7 : Machine = Machine(68);
pub const EM_68HC16 : Machine = Machine(69);
pub const EM_68HC11 : Machine = Machine(70);
pub const EM_68HC08 : Machine = Machine(71);
pub const EM_68HC05 : Machine = Machine(72);
pub const EM_SVX : Machine = Machine(73);
pub const EM_ST19 : Machine = Machine(74);
pub const EM_VAX : Machine = Machine(75);
pub const EM_CRIS : Machine = Machine(76);
pub const EM_JAVELIN : Machine = Machine(77);
pub const EM_FIREPATH : Machine = Machine(78);
pub const EM_ZSP : Machine = Machine(79);
pub const EM_MMIX : Machine = Machine(80);
pub const EM_HUANY : Machine = Machine(81);
pub const EM_PRISM : Machine = Machine(82);
pub const EM_AVR : Machine = Machine(83);
pub const EM_FR30 : Machine = Machine(84);
pub const EM_D10V : Machine = Machine(85);
pub const EM_D30V : Machine = Machine(86);
pub const EM_V850 : Machine = Machine(87);
pub const EM_M32R : Machine = Machine(88);
pub const EM_MN10300 : Machine = Machine(89);
pub const EM_MN10200 : Machine = Machine(90);
pub const EM_PJ : Machine = Machine(91);
pub const EM_OPENRISC : Machine = Machine(92);
pub const EM_ARC_A5 : Machine = Machine(93);
pub const EM_XTENSA : Machine = Machine(94);
pub const EM_AARCH64 : Machine = Machine(183);
pub const EM_TILEPRO : Machine = Machine(188);
pub const EM_MICROBLAZE : Machine = Machine(189);
pub const EM_TILEGX : Machine = Machine(191);
impl fmt::Debug for Machine {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for Machine {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
EM_NONE => "No machine",
EM_M32 => "AT&T WE 32100",
EM_SPARC => "SUN SPARC",
EM_386 => "Intel 80386",
EM_68K => "Motorola m68k family",
EM_88K => "Motorola m88k family",
EM_860 => "Intel 80860",
EM_MIPS => "MIPS R3000 big-endian",
EM_S370 => "IBM System/370",
EM_MIPS_RS3_LE => "MIPS R3000 little-endian",
EM_PARISC => "HPPA",
EM_VPP500 => "Fujitsu VPP500",
EM_SPARC32PLUS => "Sun's 'v8plus'",
EM_960 => "Intel 80960",
EM_PPC => "PowerPC",
EM_PPC64 => "PowerPC 64-bit",
EM_S390 => "IBM S390",
EM_V800 => "NEC V800 series",
EM_FR20 => "Fujitsu FR20",
EM_RH32 => "TRW RH-32",
EM_RCE => "Motorola RCE",
EM_ARM => "ARM",
EM_FAKE_ALPHA => "Digital Alpha",
EM_SH => "Hitachi SH",
EM_SPARCV9 => "SPARC v9 64-bit",
EM_TRICORE => "Siemens Tricore",
EM_ARC => "Argonaut RISC Core",
EM_H8_300 => "Hitachi H8/300",
EM_H8_300H => "Hitachi H8/300H",
EM_H8S => "Hitachi H8S",
EM_H8_500 => "Hitachi H8/500",
EM_IA_64 => "Intel Merced",
EM_MIPS_X => "Stanford MIPS-X",
EM_COLDFIRE => "Motorola Coldfire",
EM_68HC12 => "Motorola M68HC12",
EM_MMA => "Fujitsu MMA Multimedia Accelerato",
EM_PCP => "Siemens PCP",
EM_NCPU => "Sony nCPU embeeded RISC",
EM_NDR1 => "Denso NDR1 microprocessor",
EM_STARCORE => "Motorola Start*Core processor",
EM_ME16 => "Toyota ME16 processor",
EM_ST100 => "STMicroelectronic ST100 processor",
EM_TINYJ => "Advanced Logic Corp. Tinyj emb.fa",
EM_X86_64 => "AMD x86-64 architecture",
EM_PDSP => "Sony DSP Processor",
EM_FX66 => "Siemens FX66 microcontroller",
EM_ST9PLUS => "STMicroelectronics ST9+ 8/16 mc",
EM_ST7 => "STmicroelectronics ST7 8 bit mc",
EM_68HC16 => "Motorola MC68HC16 microcontroller",
EM_68HC11 => "Motorola MC68HC11 microcontroller",
EM_68HC08 => "Motorola MC68HC08 microcontroller",
EM_68HC05 => "Motorola MC68HC05 microcontroller",
EM_SVX => "Silicon Graphics SVx",
EM_ST19 => "STMicroelectronics ST19 8 bit mc",
EM_VAX => "Digital VAX",
EM_CRIS => "Axis Communications 32-bit embedded processor",
EM_JAVELIN => "Infineon Technologies 32-bit embedded processor",
EM_FIREPATH => "Element 14 64-bit DSP Processor",
EM_ZSP => "LSI Logic 16-bit DSP Processor",
EM_MMIX => "Donald Knuth's educational 64-bit processor",
EM_HUANY => "Harvard University machine-independent object files",
EM_PRISM => "SiTera Prism",
EM_AVR => "Atmel AVR 8-bit microcontroller",
EM_FR30 => "Fujitsu FR30",
EM_D10V => "Mitsubishi D10V",
EM_D30V => "Mitsubishi D30V",
EM_V850 => "NEC v850",
EM_M32R => "Mitsubishi M32R",
EM_MN10300 => "Matsushita MN10300",
EM_MN10200 => "Matsushita MN10200",
EM_PJ => "picoJava",
EM_OPENRISC => "OpenRISC 32-bit embedded processor",
EM_ARC_A5 => "ARC Cores Tangent-A5",
EM_XTENSA => "Tensilica Xtensa Architecture",
EM_AARCH64 => "ARM AARCH64",
EM_TILEPRO => "Tilera TILEPro",
EM_MICROBLAZE => "Xilinx MicroBlaze",
EM_TILEGX => "Tilera TILE-Gx",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
/// Encapsulates the contents of the ELF File Header
///
/// The ELF File Header starts off every ELF file and both identifies the
/// file contents and informs how to interpret said contents. This includes
/// the width of certain fields (32-bit vs 64-bit), the data endianness, the
/// file type, and more.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct FileHeader {
/// 32-bit vs 64-bit
pub class: Class,
/// little vs big endian
pub data: Data,
/// elf version
pub version: Version,
/// OS ABI
pub osabi: OSABI,
/// Version of the OS ABI
pub abiversion: u8,
/// ELF file type
pub elftype: Type,
/// Target machine architecture
pub machine: Machine,
/// Virtual address of program entry point
pub entry: u64,
}
impl FileHeader {
pub fn new() -> FileHeader {
FileHeader { class : ELFCLASSNONE, data : ELFDATANONE, version : EV_NONE,
elftype : ET_NONE, machine : EM_NONE, osabi : ELFOSABI_NONE,
abiversion : 0, entry : 0 }
}
}
impl fmt::Display for FileHeader {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "File Header for {} {} Elf {} for {} {}", self.class, self.data,
self.elftype, self.osabi, self.machine)
}
}
/// Represents ELF Program Header flags
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct ProgFlag(pub u32);
pub const PF_NONE : ProgFlag = ProgFlag(0);
/// Executable program segment
pub const PF_X : ProgFlag = ProgFlag(1);
/// Writable program segment
pub const PF_W : ProgFlag = ProgFlag(2);
/// Readable program segment
pub const PF_R : ProgFlag = ProgFlag(4);
impl fmt::Debug for ProgFlag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for ProgFlag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if (self.0 & PF_R.0) != 0 {
try!(write!(f, "R"));
} else {
try!(write!(f, " "));
}
if (self.0 & PF_W.0) != 0 {
try!(write!(f, "W"));
} else {
try!(write!(f, " "));
}
if (self.0 & PF_X.0) != 0 {
write!(f, "E")
} else {
write!(f, " ")
}
}
}
/// Represents ELF Program Header type
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct ProgType(pub u32);
/// Program header table entry unused
pub const PT_NULL : ProgType = ProgType(0);
/// Loadable program segment
pub const PT_LOAD : ProgType = ProgType(1);
/// Dynamic linking information
pub const PT_DYNAMIC : ProgType = ProgType(2);
/// Program interpreter
pub const PT_INTERP : ProgType = ProgType(3);
/// Auxiliary information
pub const PT_NOTE : ProgType = ProgType(4);
/// Unused
pub const PT_SHLIB : ProgType = ProgType(5);
/// The program header table
pub const PT_PHDR : ProgType = ProgType(6);
/// Thread-local storage segment
pub const PT_TLS : ProgType = ProgType(7);
/// GCC .eh_frame_hdr segment
pub const PT_GNU_EH_FRAME : ProgType = ProgType(0x6474e550);
/// Indicates stack executability
pub const PT_GNU_STACK : ProgType = ProgType(0x6474e551);
/// Read-only after relocation
pub const PT_GNU_RELRO : ProgType = ProgType(0x6474e552);
impl fmt::Debug for ProgType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for ProgType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
PT_NULL => "NULL",
PT_LOAD => "LOAD",
PT_DYNAMIC => "DYNAMIC",
PT_INTERP => "INTERP",
PT_NOTE => "NOTE",
PT_SHLIB => "SHLIB",
PT_PHDR => "PHDR",
PT_TLS => "TLS",
PT_GNU_EH_FRAME => "GNU_EH_FRAME",
PT_GNU_STACK => "GNU_STACK",
PT_GNU_RELRO => "GNU_RELRO",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
/// Encapsulates the contents of an ELF Program Header
///
/// The program header table is an array of program header structures describing
/// the various segments for program execution.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct ProgramHeader {
/// Program segment type
pub progtype: ProgType,
/// Offset into the ELF file where this segment begins
pub offset: u64,
/// Virtual adress where this segment should be loaded
pub vaddr: u64,
/// Physical address where this segment should be loaded
pub paddr: u64,
/// Size of this segment in the file
pub filesz: u64,
/// Size of this segment in memory
pub memsz: u64,
/// Flags for this segment
pub flags: ProgFlag,
/// file and memory alignment
pub align: u64,
}
impl fmt::Display for ProgramHeader {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Program Header: Type: {} Offset: {:#010x} VirtAddr: {:#010x} PhysAddr: {:#010x} FileSize: {:#06x} MemSize: {:#06x} Flags: {} Align: {:#x}",
self.progtype, self.offset, self.vaddr, self.paddr, self.filesz,
self.memsz, self.flags, self.align)
}
}
/// Represens ELF Section type
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct SectionType(pub u32);
/// Inactive section with undefined values
pub const SHT_NULL : SectionType = SectionType(0);
/// Information defined by the program, includes executable code and data
pub const SHT_PROGBITS : SectionType = SectionType(1);
/// Section data contains a symbol table
pub const SHT_SYMTAB : SectionType = SectionType(2);
/// Section data contains a string table
pub const SHT_STRTAB : SectionType = SectionType(3);
/// Section data contains relocation entries with explicit addends
pub const SHT_RELA : SectionType = SectionType(4);
/// Section data contains a symbol hash table. Must be present for dynamic linking
pub const SHT_HASH : SectionType = SectionType(5);
/// Section data contains information for dynamic linking
pub const SHT_DYNAMIC : SectionType = SectionType(6);
/// Section data contains information that marks the file in some way
pub const SHT_NOTE : SectionType = SectionType(7);
/// Section data occupies no space in the file but otherwise resembles SHT_PROGBITS
pub const SHT_NOBITS : SectionType = SectionType(8);
/// Section data contains relocation entries without explicit addends
pub const SHT_REL : SectionType = SectionType(9);
/// Section is reserved but has unspecified semantics
pub const SHT_SHLIB : SectionType = SectionType(10);
/// Section data contains a minimal set of dynamic linking symbols
pub const SHT_DYNSYM : SectionType = SectionType(11);
/// Section data contains an array of constructors
pub const SHT_INIT_ARRAY : SectionType = SectionType(14);
/// Section data contains an array of destructors
pub const SHT_FINI_ARRAY : SectionType = SectionType(15);
/// Section data contains an array of pre-constructors
pub const SHT_PREINIT_ARRAY : SectionType = SectionType(16);
/// Section group
pub const SHT_GROUP : SectionType = SectionType(17);
/// Extended symbol table section index
pub const SHT_SYMTAB_SHNDX : SectionType = SectionType(18);
/// Number of reserved SHT_* values
pub const SHT_NUM : SectionType = SectionType(19);
/// Object attributes
pub const SHT_GNU_ATTRIBUTES : SectionType = SectionType(0x6ffffff5);
/// GNU-style hash section
pub const SHT_GNU_HASH : SectionType = SectionType(0x6ffffff6);
/// Pre-link library list
pub const SHT_GNU_LIBLIST : SectionType = SectionType(0x6ffffff7);
/// Version definition section
pub const SHT_GNU_VERDEF : SectionType = SectionType(0x6ffffffd);
/// Version needs section
pub const SHT_GNU_VERNEED : SectionType = SectionType(0x6ffffffe);
/// Version symbol table
pub const SHT_GNU_VERSYM : SectionType = SectionType(0x6fffffff);
impl fmt::Debug for SectionType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for SectionType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
SHT_NULL => "SHT_NULL",
SHT_PROGBITS => "SHT_PROGBITS",
SHT_SYMTAB => "SHT_SYMTAB",
SHT_STRTAB => "SHT_STRTAB",
SHT_RELA => "SHT_RELA",
SHT_HASH => "SHT_HASH",
SHT_DYNAMIC => "SHT_DYNAMIC",
SHT_NOTE => "SHT_NOTE",
SHT_NOBITS => "SHT_NOBITS",
SHT_REL => "SHT_REL",
SHT_SHLIB => "SHT_SHLIB",
SHT_DYNSYM => "SHT_DYNSYM",
SHT_INIT_ARRAY => "SHT_INIT_ARRAY",
SHT_FINI_ARRAY => "SHT_FINI_ARRAY",
SHT_PREINIT_ARRAY => "SHT_PREINIT_ARRAY",
SHT_GROUP => "SHT_GROUP",
SHT_SYMTAB_SHNDX => "SHT_SYMTAB_SHNDX",
SHT_NUM => "SHT_NUM",
SHT_GNU_ATTRIBUTES => "SHT_GNU_ATTRIBUTES",
SHT_GNU_HASH => "SHT_GNU_HASH",
SHT_GNU_LIBLIST => "SHT_GNU_LIBLIST",
SHT_GNU_VERDEF => "SHT_GNU_VERDEF",
SHT_GNU_VERNEED => "SHT_GNU_VERNEED",
SHT_GNU_VERSYM => "SHT_GNU_VERSYM",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
///
/// Wrapper type for SectionFlag
///
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct SectionFlag(pub u64);
/// Empty flags
pub const SHF_NONE : SectionFlag = SectionFlag(0);
/// Writable
pub const SHF_WRITE : SectionFlag = SectionFlag(1);
/// Occupies memory during execution
pub const SHF_ALLOC : SectionFlag = SectionFlag(2);
/// Executable
pub const SHF_EXECINSTR : SectionFlag = SectionFlag(4);
/// Might be merged
pub const SHF_MERGE : SectionFlag = SectionFlag(16);
/// Contains nul-terminated strings
pub const SHF_STRINGS : SectionFlag = SectionFlag(32);
/// `sh_info' contains SHT index
pub const SHF_INFO_LINK : SectionFlag = SectionFlag(64);
/// Preserve order after combining
pub const SHF_LINK_ORDER : SectionFlag = SectionFlag(128);
/// Non-standard OS specific handling required
pub const SHF_OS_NONCONFORMING : SectionFlag = SectionFlag(256);
/// Section is member of a group
pub const SHF_GROUP : SectionFlag = SectionFlag(512);
/// Section hold thread-local data
pub const SHF_TLS : SectionFlag = SectionFlag(1024);
impl fmt::Debug for SectionFlag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
impl fmt::Display for SectionFlag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:#x}", self.0)
}
}
/// Encapsulates the contents of an ELF Section Header
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SectionHeader {
/// Section Name
pub name: String,
/// Section Type
pub shtype: SectionType,
/// Section Flags
pub flags: SectionFlag,
/// in-memory address where this section is loaded
pub addr: u64,
/// Byte-offset into the file where this section starts
pub offset: u64,
/// Section size in bytes
pub size: u64,
/// Defined by section type
pub link: u32,
/// Defined by section type
pub info: u32,
/// address alignment
pub addralign: u64,
/// size of an entry if section data is an array of entries
pub entsize: u64,
}
impl fmt::Display for SectionHeader {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Section Header: Name: {} Type: {} Flags: {} Addr: {:#010x} Offset: {:#06x} Size: {:#06x} Link: {} Info: {:#x} AddrAlign: {} EntSize: {}",
self.name, self.shtype, self.flags, self.addr, self.offset,
self.size, self.link, self.info, self.addralign, self.entsize)
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct SymbolType(pub u8);
/// Unspecified symbol type
pub const STT_NOTYPE : SymbolType = SymbolType(0);
/// Data object symbol
pub const STT_OBJECT : SymbolType = SymbolType(1);
/// Code object symbol
pub const STT_FUNC : SymbolType = SymbolType(2);
/// Section symbol
pub const STT_SECTION : SymbolType = SymbolType(3);
/// File name symbol
pub const STT_FILE : SymbolType = SymbolType(4);
/// Common data object symbol
pub const STT_COMMON : SymbolType = SymbolType(5);
/// Thread-local data object symbol
pub const STT_TLS : SymbolType = SymbolType(6);
/// Indirect code object symbol
pub const STT_GNU_IFUNC : SymbolType = SymbolType(10);
impl fmt::Display for SymbolType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
STT_NOTYPE => "unspecified",
STT_OBJECT => "data object",
STT_FUNC => "code object",
STT_SECTION => "section",
STT_FILE => "file name",
STT_COMMON => "common data object",
STT_TLS => "thread-local data object",
STT_GNU_IFUNC => "indirect code object",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct SymbolBind(pub u8);
/// Local symbol
pub const STB_LOCAL : SymbolBind = SymbolBind(0);
/// Global symbol
pub const STB_GLOBAL : SymbolBind = SymbolBind(1);
/// Weak symbol
pub const STB_WEAK : SymbolBind = SymbolBind(2);
/// Unique symbol
pub const STB_GNU_UNIQUE : SymbolBind = SymbolBind(10);
impl fmt::Display for SymbolBind {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
STB_LOCAL => "local",
STB_GLOBAL => "global",
STB_WEAK => "weak",
STB_GNU_UNIQUE => "unique",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub struct SymbolVis(pub u8);
/// Default symbol visibility
pub const STV_DEFAULT : SymbolVis = SymbolVis(0);
/// Processor-specific hidden visibility
pub const STV_INTERNAL : SymbolVis = SymbolVis(1);
/// Hidden visibility
pub const STV_HIDDEN : SymbolVis = SymbolVis(2);
/// Protected visibility
pub const STV_PROTECTED : SymbolVis = SymbolVis(3);
impl fmt::Display for SymbolVis {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let str = match *self {
STV_DEFAULT => "default",
STV_INTERNAL => "internal",
STV_HIDDEN => "hidden",
STV_PROTECTED => "protected",
_ => "Unknown",
};
write!(f, "{}", str)
}
}
#[derive(Clone, PartialEq, Eq)]
pub struct Symbol {
/// Symbol name
pub name: String,
/// Symbol value
pub value: u64,
/// Symbol size
pub size: u64,
/// Section index
pub shndx: u16,
/// Symbol type
pub symtype: SymbolType,
/// Symbol binding
pub bind: SymbolBind,
/// Symbol visibility
pub vis: SymbolVis,
}
impl fmt::Display for Symbol {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Symbol: Value: {:#010x} Size: {:#06x} Type: {} Bind: {} Vis: {} Section: {} Name: {}",
self.value, self.size, self.symtype, self.bind, self.vis, self.shndx, self.name)
}
}