⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 elfutils.pas

📁 一个不出名的GBA模拟器
💻 PAS
📖 第 1 页 / 共 2 页
字号:
//////////////////////////////////////////////////////////////////////
//                                                                  //
// 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 + -