📄 elfutils.pas
字号:
//////////////////////////////////////////////////////////////////////
// //
// elfUtils.pas: .ELF loading, section parsing, and flattening. //
// //
// The contents of this file are subject to the Bottled Light //
// Public License Version 1.0 (the "License"); you may not use this //
// file except in compliance with the License. You may obtain a //
// copy of the License at http://www.bottledlight.com/BLPL/ //
// //
// Software distributed under the License is distributed on an //
// "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or //
// implied. See the License for the specific language governing //
// rights and limitations under the License. //
// //
// The Original Code is the Mappy VM User Interface, released //
// April 1st, 2003. The Initial Developer of the Original Code is //
// Bottled Light, Inc. Portions created by Bottled Light, Inc. are //
// Copyright (C) 2001-2003 Bottled Light, Inc. All Rights Reserved. //
// //
// Author(s): //
// Michael Noland (joat), michael@bottledlight.com //
// //
// Changelog: //
// 1.0: First public release (April 1st, 2003) //
// //
// Notes: //
// Flattening: the process of turning a segmented .ELF into a //
// a linear image one can just stick in ROM space. //
// //
// The developers of the ELF and DWARF standard has an odd sense //
// of humor, but flattening an ELF does have a ring to it, as //
// do DWARFs attacking my sanity all the time. //
// //
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
unit elfUtils; ///////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
interface ////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
uses
Classes, SysUtils, Contnrs, Math, console, nexus, AddressSpace;
//////////////////////////////////////////////////////////////////////
const
// Indicies for the identifier block
ELF_INDEX_MAGIC0 = 0; // File identification
ELF_INDEX_MAGIC1 = 1; // File identification
ELF_INDEX_MAGIC2 = 2; // File identification
ELF_INDEX_MAGIC3 = 3; // File identification
ELF_INDEX_CLASS = 4; // File class
ELF_INDEX_DATA = 5; // Data encoding
ELF_INDEX_VERSION = 6; // File version
ELF_INDEX_PAD = 7; // Start of padding bytes
ELF_INDEX_NIDENT = 16; // Size of e_ident[]
// Magic numbers for the identifier block
ELF_MAGIC0 = $7F; // e_ident[ELF_INDEX_MAG0]
ELF_MAGIC1 = ord('E'); // e_ident[ELF_INDEX_MAG1]
ELF_MAGIC2 = ord('L'); // e_ident[ELF_INDEX_MAG2]
ELF_MAGIC3 = ord('F'); // e_ident[ELF_INDEX_MAG3]
//////////////////////////////////////////////////////////////////////
// Type of ELF
ELF_TYPE_NONE = 0; // No file type
ELF_TYPE_REL = 1; // Relocatable file
ELF_TYPE_EXEC = 2; // Executable file
ELF_TYPE_DYN = 3; // Shared object file
ELF_TYPE_CORE = 4; // Core file
ELF_TYPE_LOPROC = $ff00; // Processor-specific
ELF_TYPE_HIPROC = $ffff; // Processor-specific
// Version codes
ELF_VERSION_NONE = 0; // Invalid version
ELF_VERSION_CURRENT = 1; // Current version
//////////////////////////////////////////////////////////////////////
// Target machine for the ELF
ELF_MACHINE_NONE = 0; // No machine
ELF_MACHINE_M32 = 1; // AT&T WE 32100
ELF_MACHINE_SPARC = 2; // SPARC
ELF_MACHINE_386 = 3; // Intel 80386
ELF_MACHINE_68K = 4; // Motorola 68000
ELF_MACHINE_88K = 5; // Motorola 88000
ELF_MACHINE_860 = 7; // Intel 80860
ELF_MACHINE_MIPS = 8; // MIPS RS3000
ELF_MACHINE_ARM = 40; // ARM7tdmi
// Target architechure width
ELF_CLASS_NONE = 0; // Invalid class
ELF_CLASS_32 = 1; // 32-bit objects
ELF_CLASS_64 = 2; // 64-bit objects
// Target architechure organization
ELF_DATA_NONE = 0; // Invalid data encoding
ELF_DATA_LSB = 1; // See below
ELF_DATA_MSB = 2; // See below
//////////////////////////////////////////////////////////////////////
// Reserved section indicies
SECTION_UNDEF = 0;
SECTION_LORESERVE = $FF00;
SECTION_LOPROC = $FF00;
SECTION_HIPROC = $FF1F;
SECTION_ABS = $FFF1;
SECTION_COMMON = $FFF2;
SECTION_HIRESERVE = $FFFF;
// Section types
SECTION_TYPE_NULL = 0;
SECTION_TYPE_PROGBITS = 1;
SECTION_TYPE_SYMTAB = 2;
SECTION_TYPE_STRTAB = 3;
SECTION_TYPE_RELA = 4;
SECTION_TYPE_HASH = 5;
SECTION_TYPE_DYNAMIC = 6;
SECTION_TYPE_NOTE = 7;
SECTION_TYPE_NOBITS = 8;
SECTION_TYPE_REL = 9;
SECTION_TYPE_SHLIB = 10;
SECTION_TYPE_DYNSYM = 11;
SECTION_TYPE_LOPROC = $70000000;
SECTION_TYPE_HIPROC = $7FFFFFFF;
SECTION_TYPE_LOUSER = $80000000;
SECTION_TYPE_HIUSER = $FFFFFFFF;
// Section flags
SECTION_FLAGS_WRITE = $1;
SECTION_FLAGS_ALLOC = $2;
SECTION_FLAGS_EXECINSTR = $4;
SECTION_FLAGS_MASKPROC = $F0000000;
//////////////////////////////////////////////////////////////////////
// Symbol Table Entry Binding Modes
SYMBOL_BINDING_LOCAL = 0;
SYMBOL_BINDING_GLOBAL = 1;
SYMBOL_BINDING_WEAK = 2;
SYMBOL_BINDING_LOPROC = 13;
SYMBOL_BINDING_HIPROC = 15;
// Symbol Table Entry Types
SYMBOL_TYPE_NOTYPE = 0;
SYMBOL_TYPE_OBJECT = 1;
SYMBOL_TYPE_FUNC = 2;
SYMBOL_TYPE_SECTION = 3;
SYMBOL_TYPE_FILE = 4;
SYMBOL_TYPE_LOPROC = 13;
SYMBOL_TYPE_HIPROC = 15;
//////////////////////////////////////////////////////////////////////
type
// ELF File Header
TElf32Header = packed record
ident: array[0..15] of byte;
elfType: uint16;
machine: uint16;
version: uint32;
entryPoint: uint32;
progTableOffset: uint32;
sectionTableOffset: uint32;
flags: uint32;
headerSize: uint16;
progEntrySize: uint16;
numProgEntries: uint16;
sectionEntrySize: uint16;
numSectionEntries: uint16;
stringTableIndex: uint16;
end;
PElf32Header = ^TElf32Header;
// ELF Section Header
TElf32SectionHeader = packed record
sh_name: uint32;
sh_type: uint32;
sh_flags: uint32;
sh_addr: uint32;
sh_offset: uint32;
sh_size: uint32;
sh_link: uint32;
sh_info: uint32;
sh_addralign: uint32;
sh_entsize: uint32;
end;
PElf32SectionHeader = ^TElf32SectionHeader;
// ELF Symbol Table Entry
TElf32SymbolEntry = packed record
name: uint32;
value: uint32;
size: uint32;
info: byte;
other: byte;
sectionIndex: uint16;
end;
PElf32SymbolEntry = ^TElf32SymbolEntry;
//////////////////////////////////////////////////////////////////////
type
TELFFile = class;
TReadableResource = class
public
data: PByteArray;
dataPointer: pointer;
size: uint32;
function ReadUint8: uint32;
function ReadInt8: int32;
function ReadUint16: uint32;
function ReadInt16: int32;
function ReadUint32: uint32;
function ReadInt32: int32;
function ReadUint64: uint32;
function ReadInt64: int32;
function ReadLEB128: uint32;
function ReadSLEB128: int32;
procedure ReadBlock(var block; size: uint32);
function ReadString: PChar;
function ReadAddress: uint32;
procedure SeekRelAddress(offset: integer);
procedure Seek(absOffset: integer);
end;
// A container class for an ELF section
TELFSection = class(TReadableResource)
public
FHeader: PElf32SectionHeader;
constructor Create(myParent: TElfFile; header: PElf32SectionHeader);
destructor Destroy; override;
procedure ProcessSymtab(q: integer);
function Name: string;
function HasSubstance: boolean;
function ReadElfString(index: integer): string;
private
FParent: TElfFile;
end;
//////////////////////////////////////////////////////////////////////
// A container class for an ELF file (has children sections and
// manages the memory associated with them)
TELFFile = class
private
FSections: TObjectList;
function GetSection(index: integer): TElfSection;
public
header: PElf32Header;
size: integer;
data: PByteArray;
property Sections[index: integer]: TElfSection read GetSection;
function FindSectionByName(name: string): TElfSection;
function ReadString(index: integer): string;
function NumSections: integer;
constructor Create(stream: TStream);
procedure Build;
destructor Destroy; override;
function Flatten(var data: Puint8array): integer;
end;
//////////////////////////////////////////////////////////////////////
var
elf: TELFFile;
//////////////////////////////////////////////////////////////////////
implementation ///////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
// TELFSection ///////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////
constructor TELFSection.Create(myParent: TElfFile; header: PElf32SectionHeader);
begin
FParent := myParent;
FHeader := header;
data := @(FParent.data^[FHeader^.sh_offset]);
size := FHeader^.sh_size;
end;
//////////////////////////////////////////////////////////////////////
destructor TELFSection.Destroy;
begin
end;
//////////////////////////////////////////////////////////////////////
function TELFSection.HasSubstance: boolean;
begin
with FHeader^ do
Result := (sh_type = SECTION_TYPE_PROGBITS) and (sh_flags and SECTION_FLAGS_ALLOC <> 0);
end;
//////////////////////////////////////////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -