mirror of https://github.com/x64dbg/btparser
795 lines
26 KiB
Plaintext
795 lines
26 KiB
Plaintext
|
//----------------------------------------
|
||
|
//--- 010 Editor v2.0 Binary Template
|
||
|
//
|
||
|
// File: ELFTemplate.bt
|
||
|
// Author: 010Editor (Unknown?)
|
||
|
// Tim "diff" Strazzere <diff@lookout.com> <strazz@gmail.com>
|
||
|
// Revision: 2.2
|
||
|
// Purpose: Defines a template for
|
||
|
// parsing ELF 32-bit and 64-bit files.
|
||
|
//----------------------------------------
|
||
|
//
|
||
|
// Version 2.2
|
||
|
// FIXED:
|
||
|
// - Fixed issues if the section header count is greater
|
||
|
// the actual number of sections that exist.
|
||
|
// More information;
|
||
|
// http://dustri.org/b/?p=832
|
||
|
//
|
||
|
// Version 2.1
|
||
|
// FIXED:
|
||
|
// - Fixed issue with local variables so it's actually
|
||
|
// runnable inside v4.0.3
|
||
|
|
||
|
// Define structures used in ELF files
|
||
|
|
||
|
// ELF Header Types
|
||
|
// ELF identification element
|
||
|
|
||
|
// Accelerate a slow lookup with an array
|
||
|
local int sec_tbl_elem[255];
|
||
|
|
||
|
typedef enum <uchar> {
|
||
|
ELFCLASSNONE =0,
|
||
|
ELFCLASS32 =1,
|
||
|
ELFCLASS64 =2
|
||
|
}ei_class_2_e;
|
||
|
|
||
|
typedef enum <uchar> {
|
||
|
ELFDATAONE =0,
|
||
|
ELFDATA2LSB =1,
|
||
|
ELFDATA2MSB =2
|
||
|
}ei_data_e;
|
||
|
|
||
|
typedef enum <uchar> {
|
||
|
E_NONE =0,
|
||
|
E_CURRENT =1
|
||
|
}ei_version_e;
|
||
|
|
||
|
typedef enum <uchar> {
|
||
|
ELFOSABI_NONE =0, //No extensions or unspecified
|
||
|
ELFOSABI_HPUX =1, //Hewlett-Packard HP-UX
|
||
|
ELFOSABI_NETBSD =2, //NetBSD
|
||
|
ELFOSABI_SOLARIS=6, //Sun Solaris
|
||
|
ELFOSABI_AIX =7, //AIX
|
||
|
ELFOSABI_IRIX =8, //IRIX
|
||
|
ELFOSABI_FREEBSD=9, //FreeBSD
|
||
|
ELFOSABI_TRU64 =10, //Compaq TRU64 UNIX
|
||
|
ELFOSABI_MODESTO=11, //Novell Modesto
|
||
|
ELFOSABI_OPENBSD=12, //Open BSD
|
||
|
ELFOSABI_OPENVMS=13, //Open VMS
|
||
|
ELFOSABI_NSK =14, //Hewlett-Packard Non-Stop Kernel
|
||
|
ELFOSABI_AROS =15 //Amiga Research OS
|
||
|
}ei_osabi_e;
|
||
|
|
||
|
|
||
|
typedef struct {
|
||
|
char file_identification[4];
|
||
|
ei_class_2_e ei_class_2;
|
||
|
ei_data_e ei_data;
|
||
|
if( ei_data == ELFDATA2LSB ) {
|
||
|
LittleEndian();
|
||
|
} else {
|
||
|
BigEndian();
|
||
|
}
|
||
|
ei_version_e ei_version;
|
||
|
ei_osabi_e ei_osabi;
|
||
|
uchar ei_abiversion;
|
||
|
uchar ei_pad[6];
|
||
|
uchar ei_nident_SIZE;
|
||
|
} e_ident_t;
|
||
|
|
||
|
// Elf Data Types for 32/64 bit
|
||
|
//32 bit
|
||
|
typedef uint32 Elf32_Word;
|
||
|
typedef uint32 Elf32_Off;
|
||
|
typedef uint32 Elf32_Addr <read=VAddr32>;
|
||
|
typedef uint16 Elf32_Half;
|
||
|
typedef uint32 Elf32_Xword;
|
||
|
//64 bit
|
||
|
typedef uint32 Elf64_Word;
|
||
|
typedef uint64 Elf64_Off;
|
||
|
typedef uint64 Elf64_Addr <read=VAddr64>;
|
||
|
typedef uint16 Elf64_Half;
|
||
|
typedef uint64 Elf64_Xword;
|
||
|
|
||
|
string VAddr32( Elf32_Addr &addr ) {
|
||
|
local char buf[128];
|
||
|
SPrintf( buf, "0x%08X", addr );
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
string VAddr64( Elf64_Addr &addr ) {
|
||
|
local char buf[128];
|
||
|
SPrintf( buf, "0x%016LX", addr );
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
typedef enum <Elf32_Half> {
|
||
|
ET_NONE =0,
|
||
|
ET_REL =1,
|
||
|
ET_EXEC =2,
|
||
|
ET_DYN =3,
|
||
|
ET_CORE =4,
|
||
|
ET_LOOS =0xfe00,
|
||
|
ET_HIOS =0xfeff,
|
||
|
ET_LOPROC =0xff00,
|
||
|
ET_HIPROC =0xffff
|
||
|
} e_type32_e;
|
||
|
typedef e_type32_e e_type64_e;
|
||
|
|
||
|
typedef enum <Elf32_Half> { // list has to to be completed
|
||
|
EM_NONE =0, //No machine
|
||
|
EM_M32 =1, //AT&T WE 32100
|
||
|
EM_SPARC =2, //SPARC
|
||
|
EM_386 =3, //Intel 80386
|
||
|
EM_68K =4, //Motorola 68000
|
||
|
EM_88K =5, //Motorola 88000
|
||
|
reserved6 =6, //Reserved for future use (was EM_486)
|
||
|
EM_860 =7, //Intel 80860
|
||
|
EM_MIPS =8, //MIPS I Architecture
|
||
|
EM_S370 =9, //IBM System/370 Processor
|
||
|
EM_MIPS_RS3_LE =10, //MIPS RS3000 Little-endian
|
||
|
reserved11 =11, //Reserved for future use
|
||
|
reserved12 =12, //Reserved for future use
|
||
|
reserved13 =13, //Reserved for future use
|
||
|
reserved14 =14, //Reserved for future use
|
||
|
EM_PARISC =15, //Hewlett-Packard PA-RISC
|
||
|
reserved16 =16, //Reserved for future use
|
||
|
EM_VPP500 =17, //Fujitsu VPP500
|
||
|
EM_SPARC32PLUS =18, //Enhanced instruction set SPARC
|
||
|
EM_960 =19, //Intel 80960
|
||
|
EM_PPC =20, //PowerPC
|
||
|
EM_PPC64 =21, //64-bit PowerPC
|
||
|
EM_S390 =22, //IBM System/390 Processor
|
||
|
reserved23 =23, //Reserved for future use
|
||
|
reserved24 =24, //Reserved for future use
|
||
|
reserved25 =25, //Reserved for future use
|
||
|
reserved26 =26, //Reserved for future use
|
||
|
reserved27 =27, //Reserved for future use
|
||
|
reserved28 =28, //Reserved for future use
|
||
|
reserved29 =29, //Reserved for future use
|
||
|
reserved30 =30, //Reserved for future use
|
||
|
reserved31 =31, //Reserved for future use
|
||
|
reserved32 =32, //Reserved for future use
|
||
|
reserved33 =33, //Reserved for future use
|
||
|
reserved34 =34, //Reserved for future use
|
||
|
reserved35 =35, //Reserved for future use
|
||
|
EM_V800 =36, //NEC V800
|
||
|
EM_FR20 =37, //Fujitsu FR20
|
||
|
EM_RH32 =38, //TRW RH-32
|
||
|
EM_RCE =39, //Motorola RCE
|
||
|
EM_ARM =40, //Advanced RISC Machines ARM
|
||
|
EM_ALPHA =41, //Digital Alpha
|
||
|
EM_SH =42, //Hitachi SH
|
||
|
EM_SPARCV9 =43, //SPARC Version 9
|
||
|
EM_TRICORE =44, //Siemens TriCore embedded processor
|
||
|
EM_ARC =45, //Argonaut RISC Core, Argonaut Technologies Inc.
|
||
|
EM_H8_300 =46, //Hitachi H8/300
|
||
|
EM_H8_300H =47, //Hitachi H8/300H
|
||
|
EM_H8S =48, //Hitachi H8S
|
||
|
EM_H8_500 =49, //Hitachi H8/500
|
||
|
EM_IA_64 =50, //Intel IA-64 processor architecture
|
||
|
EM_MIPS_X =51, //Stanford MIPS-X
|
||
|
EM_COLDFIRE =52, //Motorola ColdFire
|
||
|
EM_68HC12 =53, //Motorola M68HC12
|
||
|
EM_MMA =54, //Fujitsu MMA Multimedia Accelerator
|
||
|
EM_PCP =55, //Siemens PCP
|
||
|
EM_NCPU =56, //Sony nCPU embedded RISC processor
|
||
|
EM_NDR1 =57, //Denso NDR1 microprocessor
|
||
|
EM_STARCORE =58, //Motorola Star*Core processor
|
||
|
EM_ME16 =59, //Toyota ME16 processor
|
||
|
EM_ST100 =60, //STMicroelectronics ST100 processor
|
||
|
EM_TINYJ =61, //Advanced Logic Corp. TinyJ embedded processor family
|
||
|
EM_X86_64 =62, //AMD x86-64 architecture
|
||
|
EM_PDSP =63, //Sony DSP Processor
|
||
|
EM_PDP10 =64, //Digital Equipment Corp. PDP-10
|
||
|
EM_PDP11 =65, //Digital Equipment Corp. PDP-11
|
||
|
EM_FX66 =66, //Siemens FX66 microcontroller
|
||
|
EM_ST9PLUS =67, //STMicroelectronics ST9+ 8/16 bit microcontroller
|
||
|
EM_ST7 =68, //STMicroelectronics ST7 8-bit microcontroller
|
||
|
EM_68HC16 =69, //Motorola MC68HC16 Microcontroller
|
||
|
EM_68HC11 =70, //Motorola MC68HC11 Microcontroller
|
||
|
EM_68HC08 =71, //Motorola MC68HC08 Microcontroller
|
||
|
EM_68HC05 =72, //Motorola MC68HC05 Microcontroller
|
||
|
EM_SVX =73, //Silicon Graphics SVx
|
||
|
EM_ST19 =75, //Digital VAX
|
||
|
EM_CRIS =76, //Axis Communications 32-bit embedded processor
|
||
|
EM_JAVELIN =77, //Infineon Technologies 32-bit embedded processor
|
||
|
EM_FIREPATH =78, //Element 14 64-bit DSP Processor
|
||
|
EM_ZSP =79, //LSI Logic 16-bit DSP Processor
|
||
|
EM_MMIX =80, //Donald Knuth's educational 64-bit processor
|
||
|
EM_HUANY =81, //Harvard University machine-independent object files
|
||
|
EM_PRISM =82, //SiTera Prism
|
||
|
EM_AVR =83, //Atmel AVR 8-bit microcontroller
|
||
|
EM_FR30 =84, //Fujitsu FR30
|
||
|
EM_D10V =85, //Mitsubishi D10V
|
||
|
EM_D30V =86, //Mitsubishi D30V
|
||
|
EM_V850 =87, //NEC v850
|
||
|
EM_M32R =88, //Mitsubishi M32R
|
||
|
EM_MN10300 =89, //Matsushita MN10300
|
||
|
EM_MN10200 =90, //Matsushita MN10200
|
||
|
EM_PJ =91, //picoJava
|
||
|
EM_OPENRISC =92, //OpenRISC 32-bit embedded processor
|
||
|
EM_ARC_A5 =93, //ARC Cores Tangent-A5
|
||
|
EM_XTENSA =94, //Tensilica Xtensa Architecture
|
||
|
EM_VIDEOCORE =95, //Alphamosaic VideoCore processor
|
||
|
EM_TMM_GPP =96, //Thompson Multimedia General Purpose Processor
|
||
|
EM_NS32K =97, //National Semiconductor 32000 series
|
||
|
EM_TPC =98, //Tenor Network TPC processor
|
||
|
EM_SNP1K =99, //Trebia SNP 1000 processor
|
||
|
EM_ST200 =100, //STMicroelectronics (www.st.com) ST200 microcontroller
|
||
|
EM_IP2K =101, //Ubicom IP2xxx microcontroller family
|
||
|
EM_MAX =102, //MAX Processor
|
||
|
EM_CR =103, //National Semiconductor CompactRISC microprocessor
|
||
|
EM_F2MC16 =104, //Fujitsu F2MC16
|
||
|
EM_MSP430 =105, //Texas Instruments embedded microcontroller msp430
|
||
|
EM_BLACKFIN =106, //Analog Devices Blackfin (DSP) processor
|
||
|
EM_SE_C33 =107, //S1C33 Family of Seiko Epson processors
|
||
|
EM_SEP =108, //Sharp embedded microprocessor
|
||
|
EM_ARCA =109, //Arca RISC Microprocessor
|
||
|
EM_UNICORE =110 //Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University
|
||
|
} e_machine32_e;
|
||
|
|
||
|
typedef e_machine32_e e_machine64_e;
|
||
|
|
||
|
typedef enum <Elf32_Word> {
|
||
|
EV_NONE =0,
|
||
|
EV_CURRENT =1
|
||
|
} e_version32_e;
|
||
|
typedef e_version32_e e_version64_e;
|
||
|
|
||
|
|
||
|
// Program Header Types
|
||
|
typedef enum <Elf32_Word> {
|
||
|
PT_NULL =0,
|
||
|
PT_LOAD =1,
|
||
|
PT_DYNAMIC =2,
|
||
|
PT_INERP =3,
|
||
|
PT_NOTE =4,
|
||
|
PT_SHLIB =5,
|
||
|
PT_PHDR =6,
|
||
|
PT_LOOS =0x60000000,
|
||
|
PT_HIOS =0x6fffffff,
|
||
|
PT_LOPROC =0x70000000,
|
||
|
PT_HIPROC =0x7fffffff
|
||
|
} p_type32_e;
|
||
|
typedef p_type32_e p_type64_e;
|
||
|
|
||
|
typedef enum <Elf32_Word> {
|
||
|
PF_None =0,
|
||
|
PF_Exec =1,
|
||
|
PF_Write =2,
|
||
|
PF_Write_Exec =3,
|
||
|
PF_Read =4,
|
||
|
PF_Read_Exec =5,
|
||
|
PF_Read_Write =6,
|
||
|
PF_Read_Write_Exec =7
|
||
|
} p_flags32_e;
|
||
|
typedef p_flags32_e p_flags64_e;
|
||
|
|
||
|
typedef enum <Elf32_Word> {
|
||
|
SHN_UNDEF = 0, /* undefined, e.g. undefined symbol */
|
||
|
SHN_LORESERVE = 0xff00, /* Lower bound of reserved indices */
|
||
|
SHN_LOPROC = 0xff00, /* Lower bound processor-specific index */
|
||
|
SHN_HIPROC = 0xff1f, /* Upper bound processor-specific index */
|
||
|
SHN_LOOS = 0xff20, /* Lower bound OS-specific index */
|
||
|
SHN_HIOS = 0xff3f, /* Upper bound OS-specific index */
|
||
|
SHN_ABS = 0xfff1, /* Absolute value, not relocated */
|
||
|
SHN_COMMON = 0xfff2, /* FORTRAN common or unallocated C */
|
||
|
SHN_HIRESERVE = 0xffff /* Upper bound of reserved indices */
|
||
|
} s_name32_e;
|
||
|
typedef s_name32_e s_name64_e;
|
||
|
|
||
|
typedef enum <Elf32_Word> {
|
||
|
SHT_NULL = 0, /* Inactive section header */
|
||
|
SHT_PROGBITS = 1, /* Information defined by the program */
|
||
|
SHT_SYMTAB = 2, /* Symbol table - not DLL */
|
||
|
SHT_STRTAB = 3, /* String table */
|
||
|
SHT_RELA = 4, /* Explicit addend relocations, Elf64_Rela */
|
||
|
SHT_HASH = 5, /* Symbol hash table */
|
||
|
SHT_DYNAMIC = 6, /* Information for dynamic linking */
|
||
|
SHT_NOTE = 7, /* A Note section */
|
||
|
SHT_NOBITS = 8, /* Like SHT_PROGBITS with no data */
|
||
|
SHT_REL = 9, /* Implicit addend relocations, Elf64_Rel */
|
||
|
SHT_SHLIB = 10, /* Currently unspecified semantics */
|
||
|
SHT_DYNSYM = 11, /* Symbol table for a DLL */
|
||
|
|
||
|
SHT_LOOS = 0x60000000, /* Lowest OS-specific section type */
|
||
|
SHT_HIOS = 0x6fffffff, /* Highest OS-specific section type */
|
||
|
|
||
|
SHT_LOPROC = 0x70000000, /* Lowest processor-specific section type */
|
||
|
SHT_HIPROC = 0x7fffffff /* Highest processor-specific section type */
|
||
|
} s_type32_e;
|
||
|
typedef s_type32_e s_type64_e;
|
||
|
|
||
|
string ReservedSectionName( s_name32_e id ) {
|
||
|
local char buf[255];
|
||
|
if( id == SHN_UNDEF ) return "SHN_UNDEF";
|
||
|
if( id >= SHN_LOPROC && id <= SHN_HIPROC ) {
|
||
|
SPrintf( buf, "SHN_PROC_%02X", id - SHN_LOPROC );
|
||
|
return buf;
|
||
|
}
|
||
|
if( id >= SHN_LOOS && id <= SHN_HIOS ) {
|
||
|
SPrintf( buf, "SHN_OS_%02X", id - SHN_LOOS );
|
||
|
return buf;
|
||
|
}
|
||
|
if( id == SHN_ABS ) return "SHN_ABS";
|
||
|
if( id == SHN_COMMON ) return "SHN_COMMON";
|
||
|
|
||
|
SPrintf( buf, "SHN_RESERVE_%02X", id - SHN_LORESERVE );
|
||
|
return buf;
|
||
|
}
|
||
|
|
||
|
// Program Table 32/64 bit
|
||
|
typedef struct { //32bit
|
||
|
local quad off = FTell();
|
||
|
|
||
|
p_type32_e p_type;
|
||
|
Elf32_Off p_offset_FROM_FILE_BEGIN <format=hex>;
|
||
|
Elf32_Addr p_vaddr_VIRTUAL_ADDRESS;
|
||
|
Elf32_Addr p_paddr_PHYSICAL_ADDRESS;
|
||
|
Elf32_Word p_filesz_SEGMENT_FILE_LENGTH;
|
||
|
Elf32_Word p_memsz_SEGMENT_RAM_LENGTH;
|
||
|
p_flags32_e p_flags;
|
||
|
Elf32_Word p_align;
|
||
|
|
||
|
if( p_filesz_SEGMENT_FILE_LENGTH > 0 ) {
|
||
|
FSeek(p_offset_FROM_FILE_BEGIN);
|
||
|
char p_data[p_filesz_SEGMENT_FILE_LENGTH];
|
||
|
}
|
||
|
|
||
|
FSeek(off + file.elf_header.e_phentsize_PROGRAM_HEADER_ENTRY_SIZE_IN_FILE);
|
||
|
} program_table_entry32_t <read=ProgramInfo32,optimize=false>;
|
||
|
typedef struct { //64bit
|
||
|
local quad off = FTell();
|
||
|
|
||
|
p_type64_e p_type;
|
||
|
p_flags64_e p_flags;
|
||
|
Elf64_Off p_offset_FROM_FILE_BEGIN <format=hex>;
|
||
|
Elf64_Addr p_vaddr_VIRTUAL_ADDRESS;
|
||
|
Elf64_Addr p_paddr_PHYSICAL_ADDRESS;
|
||
|
Elf64_Xword p_filesz_SEGMENT_FILE_LENGTH;
|
||
|
Elf64_Xword p_memsz_SEGMENT_RAM_LENGTH;
|
||
|
Elf64_Xword p_align;
|
||
|
|
||
|
if( p_filesz_SEGMENT_FILE_LENGTH > 0 ) {
|
||
|
FSeek(p_offset_FROM_FILE_BEGIN);
|
||
|
char p_data[p_filesz_SEGMENT_FILE_LENGTH];
|
||
|
}
|
||
|
|
||
|
FSeek(off + file.elf_header.e_phentsize_PROGRAM_HEADER_ENTRY_SIZE_IN_FILE);
|
||
|
} program_table_entry64_t <read=ProgramInfo64,optimize=false>;
|
||
|
|
||
|
string ProgramType( p_type64_e type ) {
|
||
|
switch( type ) {
|
||
|
case PT_NULL: return "NULL";
|
||
|
case PT_LOAD: return "Loadable Segment";
|
||
|
case PT_DYNAMIC: return "Dynamic Segment";
|
||
|
case PT_INERP: return "Interpreter Path";
|
||
|
case PT_NOTE: return "Note";
|
||
|
case PT_SHLIB: return "PT_SHLIB";
|
||
|
case PT_PHDR: return "Program Header";
|
||
|
default: return "Unknown Section";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
string ProgramFlags( p_flags64_e flags ) {
|
||
|
local string rv = "(";
|
||
|
|
||
|
rv += ( flags & PF_Read ) ? "R" : "_";
|
||
|
rv += ( flags & PF_Write ) ? "W" : "_";
|
||
|
rv += ( flags & PF_Exec ) ? "X" : "_";
|
||
|
rv += ")";
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
string ProgramInfo64( program_table_entry64_t &ent ) {
|
||
|
return ProgramFlags( ent.p_flags ) + " " + ProgramType( ent.p_type );
|
||
|
}
|
||
|
|
||
|
string ProgramInfo32( program_table_entry32_t &ent ) {
|
||
|
return ProgramFlags( ent.p_flags ) + " " + ProgramType( ent.p_type );
|
||
|
}
|
||
|
|
||
|
// ************************************* Section Table ***************************************
|
||
|
|
||
|
typedef enum <Elf32_Xword> {
|
||
|
SF32_None =0,
|
||
|
SF32_Exec =1,
|
||
|
SF32_Alloc =2,
|
||
|
SF32_Alloc_Exec =3,
|
||
|
SF32_Write =4,
|
||
|
SF32_Write_Exec =5,
|
||
|
SF32_Write_Alloc =6,
|
||
|
SF32_Write_Alloc_Exec =7
|
||
|
} s_flags32_e;
|
||
|
typedef enum <Elf64_Xword> {
|
||
|
SF64_None =0,
|
||
|
SF64_Exec =1,
|
||
|
SF64_Alloc =2,
|
||
|
SF64_Alloc_Exec =3,
|
||
|
SF64_Write =4,
|
||
|
SF64_Write_Exec =5,
|
||
|
SF64_Write_Alloc =6,
|
||
|
SF64_Write_Alloc_Exec =7
|
||
|
} s_flags64_e;
|
||
|
|
||
|
// Pointer to where the next name is located
|
||
|
local quad section_name_block_off;
|
||
|
|
||
|
typedef struct {
|
||
|
s_name32_e s_name_off <format=hex>;
|
||
|
|
||
|
local quad off = FTell();
|
||
|
FSeek( section_name_block_off + s_name_off );
|
||
|
|
||
|
string s_name_str;
|
||
|
|
||
|
FSeek( off );
|
||
|
} s_name32_t <read=SectionName>;
|
||
|
|
||
|
typedef s_name32_t s_name64_t;
|
||
|
|
||
|
string SectionName( s_name32_t § ) {
|
||
|
if( sect.s_name_off > SHN_UNDEF && sect.s_name_off < SHN_LORESERVE ) {
|
||
|
return sect.s_name_str;
|
||
|
}
|
||
|
return ReservedSectionName( sect.s_name_off );
|
||
|
}
|
||
|
|
||
|
typedef struct { //64bit
|
||
|
local quad off = FTell();
|
||
|
|
||
|
s_name64_t s_name; /* Section name */
|
||
|
s_type64_e s_type; /* Section type */
|
||
|
s_flags64_e s_flags; /* Section attributes */
|
||
|
Elf64_Addr s_addr; /* Virtual address in memory */
|
||
|
Elf64_Off s_offset <format=hex>; /* Offset in file */
|
||
|
Elf64_Xword s_size; /* Size of section */
|
||
|
Elf64_Word s_link; /* Link to other section */
|
||
|
Elf64_Word s_info; /* Miscellaneous information */
|
||
|
Elf64_Xword s_addralign; /* Address alignment boundary */
|
||
|
Elf64_Xword s_entsize; /* Entry size, if section has table */
|
||
|
|
||
|
if( s_type != SHT_NOBITS && s_type != SHT_NULL && s_size > 0 ) {
|
||
|
FSeek(s_offset);
|
||
|
|
||
|
char data[s_size];
|
||
|
}
|
||
|
FSeek(off + file.elf_header.e_shentzise_SECTION_HEADER_ENTRY_SIZE);
|
||
|
} section_table_entry64_t <optimize=false>;
|
||
|
// Section Table 32/64 bit
|
||
|
typedef struct { //32bit
|
||
|
local quad off = FTell();
|
||
|
|
||
|
s_name32_t s_name; /* Section name */
|
||
|
s_type32_e s_type; /* Section type */
|
||
|
s_flags32_e s_flags; /* Section attributes */
|
||
|
Elf32_Addr s_addr; /* Virtual address in memory */
|
||
|
Elf32_Off s_offset <format=hex>; /* Offset in file */
|
||
|
Elf32_Xword s_size; /* Size of section */
|
||
|
Elf32_Word s_link; /* Link to other section */
|
||
|
Elf32_Word s_info; /* Miscellaneous information */
|
||
|
Elf32_Xword s_addralign; /* Address alignment boundary*/
|
||
|
Elf32_Xword s_entsize; /* Entry size, if section has table */
|
||
|
|
||
|
if( s_type != SHT_NOBITS && s_type != SHT_NULL && s_size > 0 ) {
|
||
|
FSeek(s_offset);
|
||
|
|
||
|
char s_data[s_size];
|
||
|
}
|
||
|
FSeek(off + file.elf_header.e_shentzise_SECTION_HEADER_ENTRY_SIZE);
|
||
|
} section_table_entry32_t <read=SectionName32,optimize=false>;
|
||
|
|
||
|
string SectionName64( section_table_entry64_t § ) {
|
||
|
return SectionName( sect.s_name );
|
||
|
}
|
||
|
|
||
|
string SectionName32( section_table_entry32_t § ) {
|
||
|
return SectionName( sect.s_name );
|
||
|
}
|
||
|
|
||
|
// ************************************** Symbol Table ***************************************
|
||
|
|
||
|
local quad symbol_name_block_off;
|
||
|
|
||
|
typedef struct {
|
||
|
Elf32_Word sym_name_off <format=hex>; /* Symbol table name offset */
|
||
|
|
||
|
local quad off = FTell();
|
||
|
FSeek( symbol_name_block_off + sym_name_off );
|
||
|
|
||
|
string sym_name_str;
|
||
|
|
||
|
FSeek( off );
|
||
|
} sym_name32_t <read=SymbolName,optimize=false>;
|
||
|
typedef sym_name32_t sym_name64_t;
|
||
|
|
||
|
string SymbolName( sym_name32_t &sym ) {
|
||
|
if( sym.sym_name_off > 0 ) {
|
||
|
return sym.sym_name_str;
|
||
|
}
|
||
|
return "<Undefined>";
|
||
|
}
|
||
|
|
||
|
typedef enum <unsigned char> {
|
||
|
STB_LOCAL = 0,
|
||
|
STB_GLOBAL = 1,
|
||
|
STB_WEAK = 2,
|
||
|
STB_OS_1 = 10,
|
||
|
STB_OS_2 = 11,
|
||
|
STB_OS_3 = 12,
|
||
|
STB_PROC_1 = 13,
|
||
|
STB_PROC_2 = 14,
|
||
|
STB_PROC_3 = 15
|
||
|
} sym_info_bind_e;
|
||
|
|
||
|
typedef enum <unsigned char> {
|
||
|
STT_NOTYPE = 0,
|
||
|
STT_OBJECT = 1,
|
||
|
STT_FUNC = 2,
|
||
|
STT_SECTION = 3,
|
||
|
STT_FILE = 4,
|
||
|
STT_OS_1 = 10,
|
||
|
STT_OS_2 = 11,
|
||
|
STT_OS_3 = 12,
|
||
|
STT_PROC_1 = 13,
|
||
|
STT_PROC_2 = 14,
|
||
|
STT_PROC_3 = 15
|
||
|
} sym_info_type_e;
|
||
|
|
||
|
typedef struct {
|
||
|
BitfieldDisablePadding();
|
||
|
if( IsBigEndian() ) {
|
||
|
uchar sym_info_bind:4;
|
||
|
uchar sym_info_type:4;
|
||
|
} else {
|
||
|
uchar sym_info_type:4;
|
||
|
uchar sym_info_bind:4;
|
||
|
}
|
||
|
BitfieldEnablePadding();
|
||
|
} sym_info_t <read=SymInfoEnums>;
|
||
|
|
||
|
string SymInfoEnums( sym_info_t &info ) {
|
||
|
local sym_info_bind_e x = info.sym_info_bind;
|
||
|
local sym_info_type_e y = info.sym_info_type;
|
||
|
return EnumToString( x ) + " | " + EnumToString( y );
|
||
|
}
|
||
|
|
||
|
typedef struct {
|
||
|
Elf64_Word sym_name; /* Symbol name */
|
||
|
unsigned char sym_info; /* Type and Binding attributes */
|
||
|
unsigned char sym_other; /* Reserved */
|
||
|
Elf64_Half sym_shndx; /* Section table index */
|
||
|
Elf64_Addr sym_value; /* Symbol value */
|
||
|
Elf64_Xword sym_size; /* Size of object (e.g., common) */
|
||
|
} Elf64_Sym_fixed;
|
||
|
|
||
|
typedef struct {
|
||
|
Elf32_Word sym_name; /* Symbol name */
|
||
|
Elf32_Addr sym_value; /* Symbol value */
|
||
|
Elf32_Xword sym_size; /* Size of object (e.g., common) */
|
||
|
unsigned char sym_info; /* Type and Binding attributes */
|
||
|
unsigned char sym_other; /* Reserved */
|
||
|
Elf32_Half sym_shndx; /* Section table index */
|
||
|
} Elf32_Sym_fixed;
|
||
|
|
||
|
typedef struct {
|
||
|
sym_name64_t sym_name; /* Symbol name */
|
||
|
sym_info_t sym_info; /* Type and Binding attributes */
|
||
|
unsigned char sym_other; /* Reserved */
|
||
|
Elf64_Half sym_shndx; /* Section table index */
|
||
|
Elf64_Addr sym_value; /* Symbol value */
|
||
|
Elf64_Xword sym_size; /* Size of object (e.g., common) */
|
||
|
|
||
|
if( sym_size && SectionHasData( sym_shndx ) ) {
|
||
|
local quad off = FTell();
|
||
|
FSeek( SectionVAddrOffset( sym_shndx, sym_value ) );
|
||
|
|
||
|
char sym_data[sym_size];
|
||
|
|
||
|
FSeek( off );
|
||
|
}
|
||
|
} Elf64_Sym <read=SymbolName64,optimize=false>;
|
||
|
|
||
|
typedef struct {
|
||
|
sym_name32_t sym_name; /* Symbol name */
|
||
|
Elf32_Addr sym_value; /* Symbol value */
|
||
|
Elf32_Xword sym_size; /* Size of object (e.g., common) */
|
||
|
sym_info_t sym_info; /* Type and Binding attributes */
|
||
|
unsigned char sym_other; /* Reserved */
|
||
|
Elf32_Half sym_shndx; /* Section table index */
|
||
|
|
||
|
if( sym_size && SectionHasData( sym_shndx ) ) {
|
||
|
local quad off = FTell();
|
||
|
FSeek( SectionVAddrOffset( sym_shndx, sym_value ) );
|
||
|
|
||
|
char sym_data[sym_size];
|
||
|
|
||
|
FSeek( off );
|
||
|
}
|
||
|
} Elf32_Sym <read=SymbolName32,optimize=false>;
|
||
|
|
||
|
string SymbolName64( Elf64_Sym &sym ) {
|
||
|
return ( sym.sym_size ? "" : "[U] " ) + SymbolName( sym.sym_name );
|
||
|
}
|
||
|
|
||
|
string SymbolName32( Elf32_Sym &sym ) {
|
||
|
return ( sym.sym_size ? "" : "[U] " ) + SymbolName( sym.sym_name );
|
||
|
}
|
||
|
|
||
|
// **************************************** ELF File *****************************************
|
||
|
|
||
|
local int iter;
|
||
|
|
||
|
int FindNamedSection( string sect ) {
|
||
|
// local int iter;
|
||
|
|
||
|
for( iter=0; iter < file.elf_header.e_shnum_NUMBER_OF_SECTION_HEADER_ENTRIES; iter++ ) {
|
||
|
if( Strcmp( file.section_header_table.section_table_element[ iter ].s_name.s_name_str, sect ) == 0 ) {
|
||
|
return iter;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
quad FindNamedSectionBlock( string sect ) {
|
||
|
local int off = FindNamedSection( sect );
|
||
|
if( off != -1 )
|
||
|
return file.section_header_table.section_table_element[off].s_offset;
|
||
|
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
int SectionHasData( Elf64_Half s_index ) {
|
||
|
// This is ridiculously slow for some reason, so cache our results in an array
|
||
|
if( sec_tbl_elem[s_index] == -1 ) {
|
||
|
sec_tbl_elem[s_index] = exists( file.section_header_table.section_table_element[s_index].s_data );
|
||
|
}
|
||
|
return sec_tbl_elem[s_index];
|
||
|
}
|
||
|
|
||
|
quad SectionVAddrOffset( Elf64_Half s_index, Elf64_Addr s_vaddr ) {
|
||
|
if( s_index < file.elf_header.e_shnum_NUMBER_OF_SECTION_HEADER_ENTRIES ) {
|
||
|
return file.section_header_table.section_table_element[s_index].s_offset + s_vaddr -
|
||
|
file.section_header_table.section_table_element[s_index].s_addr;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Structure of elf
|
||
|
struct {
|
||
|
local int i;
|
||
|
for( i=0; i<255; i++ ) {
|
||
|
sec_tbl_elem[i] = -1;
|
||
|
}
|
||
|
|
||
|
struct {
|
||
|
e_ident_t e_ident;
|
||
|
if (file.elf_header.e_ident.ei_class_2 == ELFCLASS32 )
|
||
|
{
|
||
|
//32-Bit definitions of ELF Header
|
||
|
e_type32_e e_type;
|
||
|
e_machine32_e e_machine;
|
||
|
e_version32_e e_version;
|
||
|
Elf32_Addr e_entry_START_ADDRESS;
|
||
|
Elf32_Off e_phoff_PROGRAM_HEADER_OFFSET_IN_FILE;
|
||
|
Elf32_Off e_shoff_SECTION_HEADER_OFFSET_IN_FILE;
|
||
|
Elf32_Word e_flags;
|
||
|
Elf32_Half e_ehsize_ELF_HEADER_SIZE;
|
||
|
Elf32_Half e_phentsize_PROGRAM_HEADER_ENTRY_SIZE_IN_FILE;
|
||
|
Elf32_Half e_phnum_NUMBER_OF_PROGRAM_HEADER_ENTRIES;
|
||
|
Elf32_Half e_shentzise_SECTION_HEADER_ENTRY_SIZE;
|
||
|
Elf32_Half e_shnum_NUMBER_OF_SECTION_HEADER_ENTRIES;
|
||
|
Elf32_Half e_shtrndx_STRING_TABLE_INDEX;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
//64-Bit definitions of ELF Header
|
||
|
e_type64_e e_type;
|
||
|
e_machine64_e e_machine;
|
||
|
e_version64_e e_version;
|
||
|
Elf64_Addr e_entry_START_ADDRESS;
|
||
|
Elf64_Off e_phoff_PROGRAM_HEADER_OFFSET_IN_FILE;
|
||
|
Elf64_Off e_shoff_SECTION_HEADER_OFFSET_IN_FILE;
|
||
|
Elf32_Word e_flags;
|
||
|
Elf64_Half e_ehsize_ELF_HEADER_SIZE;
|
||
|
Elf64_Half e_phentsize_PROGRAM_HEADER_ENTRY_SIZE_IN_FILE;
|
||
|
Elf64_Half e_phnum_NUMBER_OF_PROGRAM_HEADER_ENTRIES;
|
||
|
Elf64_Half e_shentzise_SECTION_HEADER_ENTRY_SIZE;
|
||
|
Elf64_Half e_shnum_NUMBER_OF_SECTION_HEADER_ENTRIES;
|
||
|
Elf64_Half e_shtrndx_STRING_TABLE_INDEX;
|
||
|
}
|
||
|
} elf_header;
|
||
|
|
||
|
// Find the program table
|
||
|
if( file.elf_header.e_phnum_NUMBER_OF_PROGRAM_HEADER_ENTRIES > 0 ) {
|
||
|
FSeek(file.elf_header.e_phoff_PROGRAM_HEADER_OFFSET_IN_FILE);
|
||
|
struct {
|
||
|
if (file.elf_header.e_ident.ei_class_2 == ELFCLASS32 ) {
|
||
|
program_table_entry32_t program_table_element[file.elf_header.e_phnum_NUMBER_OF_PROGRAM_HEADER_ENTRIES];
|
||
|
} else {
|
||
|
program_table_entry64_t program_table_element[file.elf_header.e_phnum_NUMBER_OF_PROGRAM_HEADER_ENTRIES];
|
||
|
}
|
||
|
} program_header_table;
|
||
|
}
|
||
|
|
||
|
// Find the header name location
|
||
|
local quad section_name_off =
|
||
|
file.elf_header.e_shoff_SECTION_HEADER_OFFSET_IN_FILE +
|
||
|
( file.elf_header.e_shentzise_SECTION_HEADER_ENTRY_SIZE *
|
||
|
file.elf_header.e_shtrndx_STRING_TABLE_INDEX );
|
||
|
|
||
|
// Find the header name block
|
||
|
if (file.elf_header.e_ident.ei_class_2 == ELFCLASS32 ) {
|
||
|
if( FileSize() >= section_name_off + 2 * sizeof( Elf32_Word ) +
|
||
|
sizeof( Elf32_Xword ) + sizeof( Elf32_Addr ) )
|
||
|
section_name_block_off = ReadUInt( section_name_off + 2 * sizeof( Elf32_Word ) +
|
||
|
sizeof( Elf32_Xword ) + sizeof( Elf32_Addr ) );
|
||
|
else {
|
||
|
Printf("Invalid section header found, skipping!\n");
|
||
|
Warning("Invalid section header found, skipped and attempting to continue...");
|
||
|
}
|
||
|
} else {
|
||
|
if( FileSize() >= section_name_off + 2 * sizeof( Elf64_Word ) +
|
||
|
sizeof( Elf64_Xword ) + sizeof( Elf64_Addr ) )
|
||
|
section_name_block_off = ReadUQuad( section_name_off + 2 * sizeof( Elf64_Word ) +
|
||
|
sizeof( Elf64_Xword ) + sizeof( Elf64_Addr ) );
|
||
|
else {
|
||
|
Printf("Invalid section header found, skipping!\n");
|
||
|
Warning("Invalid section header found, skipped and attempting to continue...");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
local int sec_tbl_cur_elem;
|
||
|
// Find the section headers
|
||
|
if( file.elf_header.e_shnum_NUMBER_OF_SECTION_HEADER_ENTRIES > 0 ) {
|
||
|
FSeek(file.elf_header.e_shoff_SECTION_HEADER_OFFSET_IN_FILE);
|
||
|
struct {
|
||
|
if (file.elf_header.e_ident.ei_class_2 == ELFCLASS32 ) {
|
||
|
sec_tbl_cur_elem = 0;
|
||
|
section_table_entry32_t section_table_element[file.elf_header.e_shnum_NUMBER_OF_SECTION_HEADER_ENTRIES];
|
||
|
} else {
|
||
|
sec_tbl_cur_elem = 0;
|
||
|
section_table_entry64_t section_table_element[file.elf_header.e_shnum_NUMBER_OF_SECTION_HEADER_ENTRIES];
|
||
|
}
|
||
|
} section_header_table;
|
||
|
}
|
||
|
|
||
|
local int sym_sect;
|
||
|
local int sym_name_sect;
|
||
|
|
||
|
// Find the symbol section
|
||
|
sym_sect = FindNamedSection( ".symtab" );
|
||
|
if( sym_sect >= 0 ) {
|
||
|
sym_name_sect = file.section_header_table.section_table_element[sym_sect].s_link;
|
||
|
symbol_name_block_off = file.section_header_table.section_table_element[sym_name_sect].s_offset;
|
||
|
|
||
|
FSeek( file.section_header_table.section_table_element[sym_sect].s_offset );
|
||
|
struct {
|
||
|
if (file.elf_header.e_ident.ei_class_2 == ELFCLASS32 ) {
|
||
|
Elf32_Sym symtab[file.section_header_table.section_table_element[sym_sect].s_size / sizeof(Elf32_Sym_fixed)];
|
||
|
} else {
|
||
|
Elf64_Sym symtab[file.section_header_table.section_table_element[sym_sect].s_size / sizeof(Elf64_Sym_fixed)];
|
||
|
}
|
||
|
} symbol_table;
|
||
|
}
|
||
|
|
||
|
// Find the dynamic symbol section
|
||
|
sym_sect = FindNamedSection( ".dynsym" );
|
||
|
if( sym_sect >= 0 ) {
|
||
|
sym_name_sect = file.section_header_table.section_table_element[sym_sect].s_link;
|
||
|
symbol_name_block_off = file.section_header_table.section_table_element[sym_name_sect].s_offset;
|
||
|
|
||
|
FSeek( file.section_header_table.section_table_element[sym_sect].s_offset );
|
||
|
struct {
|
||
|
if (file.elf_header.e_ident.ei_class_2 == ELFCLASS32 ) {
|
||
|
Elf32_Sym symtab[file.section_header_table.section_table_element[sym_sect].s_size / sizeof(Elf32_Sym_fixed)];
|
||
|
} else {
|
||
|
Elf64_Sym symtab[file.section_header_table.section_table_element[sym_sect].s_size / sizeof(Elf64_Sym_fixed)];
|
||
|
}
|
||
|
} dynamic_symbol_table;
|
||
|
}
|
||
|
} file;
|