123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705 |
- {
- Copyright (c) 1998-2006 by Peter Vreman
- Contains ELF definitions
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- unit elfbase;
- {$i fpcdefs.inc}
- interface
- const
- EI_MAG0 = 0;
- ELFMAG0 = $7F;
- EI_MAG1 = 1;
- ELFMAG1 = ord('E');
- EI_MAG2 = 2;
- ELFMAG2 = ord('L');
- EI_MAG3 = 3;
- ELFMAG3 = ord('F');
- EI_CLASS = 4;
- ELFCLASSNONE = 0;
- ELFCLASS32 = 1;
- ELFCLASS64 = 2;
- EI_DATA = 5;
- ELFDATANONE = 0;
- ELFDATA2LSB = 1;
- ELFDATA2MSB = 2;
- EI_VERSION = 6;
- EI_OSABI = 7;
- ELFOSABI_NONE = 0; { UNIX System V ABI }
- ELFOSABI_HPUX = 1; { HP-UX operating system }
- ELFOSABI_NETBSD = 2; { NetBSD }
- ELFOSABI_LINUX = 3; { GNU/Linux }
- ELFOSABI_HURD = 4; { GNU/Hurd }
- ELFOSABI_SOLARIS = 6; { Solaris }
- ELFOSABI_AIX = 7; { AIX }
- ELFOSABI_IRIX = 8; { IRIX }
- ELFOSABI_FREEBSD = 9; { FreeBSD }
- ELFOSABI_TRU64 = 10; { TRU64 UNIX }
- ELFOSABI_MODESTO = 11; { Novell Modesto }
- ELFOSABI_OPENBSD = 12; { OpenBSD }
- ELFOSABI_OPENVMS = 13; { OpenVMS }
- ELFOSABI_NSK = 14; { Hewlett-Packard Non-Stop Kernel }
- ELFOSABI_AROS = 15; { AROS }
- ELFOSABI_FENIXOS = 16; { FenixOS }
- ELFOSABI_C6000_ELFABI = 64; { Bare-metal TMS320C6000 }
- ELFOSABI_C6000_LINUX = 65; { Linux TMS320C6000 }
- ELFOSABI_ARM = 97; { ARM }
- ELFOSABI_STANDALONE = 255; { Standalone (embedded) application }
- EI_ABIVERSION = 8;
- EI_PAD = 9;
- { ELFHeader.e_type }
- ET_NONE = 0;
- ET_REL = 1;
- ET_EXEC = 2;
- ET_DYN = 3;
- ET_CORE = 4;
- { ELFHeader.e_machine }
- EM_SPARC = 2;
- EM_386 = 3;
- EM_M68K = 4;
- EM_MIPS = 8;
- EM_PPC = 20;
- EM_ARM = 40;
- EM_X86_64 = 62;
- { ElfSechdr.sh_num }
- SHN_UNDEF = 0;
- SHN_LORESERVE = $FF00;
- SHN_ABS = $fff1;
- SHN_COMMON = $fff2;
- { ElfSechdr.sh_type }
- SHT_NULL = 0;
- SHT_PROGBITS = 1;
- SHT_SYMTAB = 2;
- SHT_STRTAB = 3;
- SHT_RELA = 4;
- SHT_HASH = 5;
- SHT_DYNAMIC = 6;
- SHT_NOTE = 7;
- SHT_NOBITS = 8;
- SHT_REL = 9;
- SHT_SHLIB = 10;
- SHT_DYNSYM = 11;
- SHT_INIT_ARRAY = 14;
- SHT_FINI_ARRAY = 15;
- SHT_PREINIT_ARRAY = 16;
- SHT_GROUP = 17;
- SHT_SYMTAB_SHNDX = 18;
- SHT_GNU_ATTRIBUTES = $6ffffff5;
- SHT_GNU_HASH = $6ffffff6;
- SHT_GNU_LIBLIST = $6ffffff7;
- SHT_GNU_verdef = $6ffffffd;
- SHT_GNU_verneed = $6ffffffe;
- SHT_GNU_versym = $6fffffff;
- SHT_ARM_ATTRIBUTES = $70000003;
- { ElfSechdr.sh_flags }
- SHF_WRITE = 1;
- SHF_ALLOC = 2;
- SHF_EXECINSTR = 4;
- SHF_MERGE = 16;
- SHF_STRINGS = 32;
- SHF_INFO_LINK = 64;
- SHF_LINK_ORDER = 128;
- SHF_OS_NONCONFORMING = 256;
- SHF_GROUP = 512;
- SHF_TLS = 1024;
- STB_LOCAL = 0;
- STB_GLOBAL = 1;
- STB_WEAK = 2;
- STT_NOTYPE = 0;
- STT_OBJECT = 1;
- STT_FUNC = 2;
- STT_SECTION = 3;
- STT_FILE = 4;
- STT_COMMON = 5;
- STT_TLS = 6;
- STT_GNU_IFUNC = 10;
- STV_DEFAULT = 0;
- STV_INTERNAL = 1;
- STV_HIDDEN = 2;
- STV_PROTECTED = 3;
- { program header types }
- PT_NULL = 0;
- PT_LOAD = 1;
- PT_DYNAMIC = 2;
- PT_INTERP = 3;
- PT_NOTE = 4;
- PT_SHLIB = 5;
- PT_PHDR = 6;
- PT_TLS = 7;
- PT_LOOS = $60000000;
- PT_HIOS = $6FFFFFFF;
- PT_LOPROC = $70000000;
- PT_HIPROC = $7FFFFFFF;
- PT_GNU_EH_FRAME = PT_LOOS + $474e550; { Frame unwind information }
- PT_GNU_STACK = PT_LOOS + $474e551; { Stack flags }
- PT_GNU_RELRO = PT_LOOS + $474e552; { Read-only after relocation }
- { program header flags }
- PF_X = 1;
- PF_W = 2;
- PF_R = 4;
- PF_MASKOS = $0FF00000; { OS-specific reserved bits }
- PF_MASKPROC = $F0000000; { Processor-specific reserved bits }
- { .dynamic tags }
- DT_NULL = 0;
- DT_NEEDED = 1;
- DT_PLTRELSZ = 2;
- DT_PLTGOT = 3;
- DT_HASH = 4;
- DT_STRTAB = 5;
- DT_SYMTAB = 6;
- DT_RELA = 7;
- DT_RELASZ = 8;
- DT_RELAENT = 9;
- DT_STRSZ = 10;
- DT_SYMENT = 11;
- DT_INIT = 12;
- DT_FINI = 13;
- DT_SONAME = 14;
- DT_RPATH = 15;
- DT_SYMBOLIC = 16;
- DT_REL = 17;
- DT_RELSZ = 18;
- DT_RELENT = 19;
- DT_PLTREL = 20;
- DT_DEBUG = 21;
- DT_TEXTREL = 22;
- DT_JMPREL = 23;
- DT_BIND_NOW = 24;
- DT_INIT_ARRAY = 25;
- DT_FINI_ARRAY = 26;
- DT_INIT_ARRAYSZ = 27;
- DT_FINI_ARRAYSZ = 28;
- DT_RUNPATH = 29;
- DT_FLAGS = 30;
- DT_ENCODING = 32;
- DT_PREINIT_ARRAY = 32;
- DT_PREINIT_ARRAYSZ = 33;
- DT_NUM = 34;
- DT_LOOS = $6000000D;
- DT_HIOS = $6ffff000;
- DT_LOPROC = $70000000;
- DT_HIPROC = $7fffffff;
- DT_RELACOUNT = $6ffffff9;
- DT_RELCOUNT = $6ffffffa;
- DT_FLAGS_1 = $6ffffffb;
- DT_VERDEF = $6ffffffc;
- DT_VERDEFNUM = $6ffffffd;
- DT_VERNEED = $6ffffffe;
- DT_VERNEEDNUM = $6fffffff;
- { GNU extension to Solaris versioning scheme }
- DT_VERSYM = $6ffffff0;
- GRP_COMDAT = 1;
- { DT_FLAGS }
- DF_ORIGIN = 1;
- DF_SYMBOLIC = 2; // supersedes DT_SYMBOLIC
- DF_TEXTREL = 4; // supersedes DT_TEXTREL
- DF_BIND_NOW = 8; // supersedes DT_BIND_NOW
- DF_STATIC_TLS = 16;
- { DT_FLAGS_1 }
- DF_1_NOW = $01;
- DF_1_GLOBAL = $02;
- DF_1_GROUP = $04;
- DF_1_NODELETE = $08;
- DF_1_LOADFLTR = $10;
- DF_1_INITFIRST = $20;
- DF_1_NOOPEN = $40;
- DF_1_ORIGIN = $80;
- DF_1_DIRECT = $100;
- DF_1_TRANS = $200;
- DF_1_INTERPOSE = $400;
- DF_1_NODEFLIB = $800;
- DF_1_NODUMP = $1000;
- DF_1_CONFALT = $2000;
- type
- TElfIdent = array[0..15] of byte;
- { Structures which are written directly to the output file }
- TElf32header=record
- e_ident : TElfIdent;
- e_type : word;
- e_machine : word;
- e_version : longword;
- e_entry : longword; { entrypoint }
- e_phoff : longword; { program header offset }
- e_shoff : longword; { sections header offset }
- e_flags : longword;
- e_ehsize : word; { elf header size in bytes }
- e_phentsize : word; { size of an entry in the program header array }
- e_phnum : word; { 0..e_phnum-1 of entrys }
- e_shentsize : word; { size of an entry in sections header array }
- e_shnum : word; { 0..e_shnum-1 of entrys }
- e_shstrndx : word; { index of string section header }
- end;
- TElf32sechdr=record
- sh_name : longword;
- sh_type : longword;
- sh_flags : longword;
- sh_addr : longword;
- sh_offset : longword;
- sh_size : longword;
- sh_link : longword;
- sh_info : longword;
- sh_addralign : longword;
- sh_entsize : longword;
- end;
- TElf32proghdr=record
- p_type : longword;
- p_offset : longword;
- p_vaddr : longword;
- p_paddr : longword;
- p_filesz : longword;
- p_memsz : longword;
- p_flags : longword;
- p_align : longword;
- end;
- TElf32reloc=record
- address : longword;
- info : longword; { bit 0-7: type, 8-31: symbol }
- addend : longint;
- end;
- TElf32symbol=record
- st_name : longword;
- st_value : longword;
- st_size : longword;
- st_info : byte; { bit 0-3: type, 4-7: bind }
- st_other : byte;
- st_shndx : word;
- end;
- TElf32Dyn=record
- d_tag: longword;
- case integer of
- 0: (d_val: longword);
- 1: (d_ptr: longword);
- end;
- telf64header=record
- e_ident : TElfIdent;
- e_type : word;
- e_machine : word;
- e_version : longword;
- e_entry : qword; { entrypoint }
- e_phoff : qword; { program header offset }
- e_shoff : qword; { sections header offset }
- e_flags : longword;
- e_ehsize : word; { elf header size in bytes }
- e_phentsize : word; { size of an entry in the program header array }
- e_phnum : word; { 0..e_phnum-1 of entrys }
- e_shentsize : word; { size of an entry in sections header array }
- e_shnum : word; { 0..e_shnum-1 of entrys }
- e_shstrndx : word; { index of string section header }
- end;
- TElf64sechdr=record
- sh_name : longword;
- sh_type : longword;
- sh_flags : qword;
- sh_addr : qword;
- sh_offset : qword;
- sh_size : qword;
- sh_link : longword;
- sh_info : longword;
- sh_addralign : qword;
- sh_entsize : qword;
- end;
- telf64proghdr=record
- p_type : longword;
- p_flags : longword;
- p_offset : qword;
- p_vaddr : qword;
- p_paddr : qword;
- p_filesz : qword;
- p_memsz : qword;
- p_align : qword;
- end;
- telf64reloc=record
- address : qword;
- info : qword; { bit 0-31: type, 32-63: symbol }
- addend : int64; { signed! }
- end;
- telf64symbol=record
- st_name : longword;
- st_info : byte; { bit 0-3: type, 4-7: bind }
- st_other : byte;
- st_shndx : word;
- st_value : qword;
- st_size : qword;
- end;
- TElf64Dyn=record
- d_tag: qword;
- case integer of
- 0: (d_val: qword);
- 1: (d_ptr: qword);
- end;
- { The following records are same for 32 and 64 bit ELF files }
- TElfVerdef=record
- vd_version: word; { =VER_DEF_CURRENT }
- vd_flags: word;
- vd_ndx: word;
- vd_cnt: word; { number of verdaux records }
- vd_hash: longword; { ELF hash of version name }
- vd_aux: longword; { offset to verdaux records }
- vd_next: longword; { offset to next verdef record }
- end;
- TElfVerdaux=record
- vda_name: longword;
- vda_next: longword;
- end;
- TElfVerneed=record
- vn_version: word; { =VER_NEED_CURRENT }
- vn_cnt: word;
- vn_file: longword;
- vn_aux: longword;
- vn_next: longword;
- end;
- TElfVernaux=record
- vna_hash: longword;
- vna_flags: word;
- vna_other: word;
- vna_name: longword;
- vna_next: longword;
- end;
- const
- VERSYM_VERSION = $7FFF;
- VERSYM_HIDDEN = $8000;
- VER_NDX_LOCAL = 0;
- VER_NDX_GLOBAL = 1;
- { TElfverdef.vd_version }
- VER_DEF_CURRENT = 1;
- { TElfverneed.vn_version }
- VER_NEED_CURRENT = 1;
- { TElfverdef.vn_flags }
- VER_FLG_BASE = 1;
- VER_FLG_WEAK = 2;
- VER_FLG_INFO = 4;
- procedure MayBeSwapHeader(var h : telf32header);
- procedure MayBeSwapHeader(var h : telf64header);
- procedure MayBeSwapHeader(var h : telf32proghdr);
- procedure MayBeSwapHeader(var h : telf64proghdr);
- procedure MaybeSwapSecHeader(var h : telf32sechdr);
- procedure MaybeSwapSecHeader(var h : telf64sechdr);
- procedure MaybeSwapElfSymbol(var h : telf32symbol);
- procedure MaybeSwapElfSymbol(var h : telf64symbol);
- procedure MaybeSwapElfReloc(var h : telf32reloc);
- procedure MaybeSwapElfReloc(var h : telf64reloc);
- procedure MaybeSwapElfDyn(var h : telf32dyn);
- procedure MaybeSwapElfDyn(var h : telf64dyn);
- procedure MaybeSwapElfverdef(var h: TElfverdef);
- procedure MaybeSwapElfverdaux(var h: TElfverdaux);
- procedure MaybeSwapElfverneed(var h: TElfverneed);
- procedure MaybeSwapElfvernaux(var h: TElfvernaux);
- function GetElfSymbolVisibility(other: byte): byte; inline;
- procedure SetElfSymbolVisibility(var other: byte; vis: byte); inline;
- implementation
- uses
- systems;
- procedure MayBeSwapHeader(var h : telf32header);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- e_type:=swapendian(e_type);
- e_machine:=swapendian(e_machine);
- e_version:=swapendian(e_version);
- e_entry:=swapendian(e_entry);
- e_phoff:=swapendian(e_phoff);
- e_shoff:=swapendian(e_shoff);
- e_flags:=swapendian(e_flags);
- e_ehsize:=swapendian(e_ehsize);
- e_phentsize:=swapendian(e_phentsize);
- e_phnum:=swapendian(e_phnum);
- e_shentsize:=swapendian(e_shentsize);
- e_shnum:=swapendian(e_shnum);
- e_shstrndx:=swapendian(e_shstrndx);
- end;
- end;
- procedure MayBeSwapHeader(var h : telf64header);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- e_type:=swapendian(e_type);
- e_machine:=swapendian(e_machine);
- e_version:=swapendian(e_version);
- e_entry:=swapendian(e_entry);
- e_phoff:=swapendian(e_phoff);
- e_shoff:=swapendian(e_shoff);
- e_flags:=swapendian(e_flags);
- e_ehsize:=swapendian(e_ehsize);
- e_phentsize:=swapendian(e_phentsize);
- e_phnum:=swapendian(e_phnum);
- e_shentsize:=swapendian(e_shentsize);
- e_shnum:=swapendian(e_shnum);
- e_shstrndx:=swapendian(e_shstrndx);
- end;
- end;
- procedure MayBeSwapHeader(var h : telf32proghdr);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- p_align:=swapendian(p_align);
- p_filesz:=swapendian(p_filesz);
- p_flags:=swapendian(p_flags);
- p_memsz:=swapendian(p_memsz);
- p_offset:=swapendian(p_offset);
- p_paddr:=swapendian(p_paddr);
- p_type:=swapendian(p_type);
- p_vaddr:=swapendian(p_vaddr);
- end;
- end;
- procedure MayBeSwapHeader(var h : telf64proghdr);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- p_align:=swapendian(p_align);
- p_filesz:=swapendian(p_filesz);
- p_flags:=swapendian(p_flags);
- p_memsz:=swapendian(p_memsz);
- p_offset:=swapendian(p_offset);
- p_paddr:=swapendian(p_paddr);
- p_type:=swapendian(p_type);
- p_vaddr:=swapendian(p_vaddr);
- end;
- end;
- procedure MaybeSwapSecHeader(var h : telf32sechdr);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- sh_name:=swapendian(sh_name);
- sh_type:=swapendian(sh_type);
- sh_flags:=swapendian(sh_flags);
- sh_addr:=swapendian(sh_addr);
- sh_offset:=swapendian(sh_offset);
- sh_size:=swapendian(sh_size);
- sh_link:=swapendian(sh_link);
- sh_info:=swapendian(sh_info);
- sh_addralign:=swapendian(sh_addralign);
- sh_entsize:=swapendian(sh_entsize);
- end;
- end;
- procedure MaybeSwapSecHeader(var h : telf64sechdr);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- sh_name:=swapendian(sh_name);
- sh_type:=swapendian(sh_type);
- sh_flags:=swapendian(sh_flags);
- sh_addr:=swapendian(sh_addr);
- sh_offset:=swapendian(sh_offset);
- sh_size:=swapendian(sh_size);
- sh_link:=swapendian(sh_link);
- sh_info:=swapendian(sh_info);
- sh_addralign:=swapendian(sh_addralign);
- sh_entsize:=swapendian(sh_entsize);
- end;
- end;
- procedure MaybeSwapElfSymbol(var h : telf32symbol);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- st_name:=swapendian(st_name);
- st_value:=swapendian(st_value);
- st_size:=swapendian(st_size);
- st_shndx:=swapendian(st_shndx);
- end;
- end;
- procedure MaybeSwapElfSymbol(var h : telf64symbol);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- st_name:=swapendian(st_name);
- st_value:=swapendian(st_value);
- st_size:=swapendian(st_size);
- st_shndx:=swapendian(st_shndx);
- end;
- end;
- procedure MaybeSwapElfReloc(var h : telf32reloc);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- address:=swapendian(address);
- info:=swapendian(info);
- addend:=swapendian(addend);
- end;
- end;
- procedure MaybeSwapElfReloc(var h : telf64reloc);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- address:=swapendian(address);
- info:=swapendian(info);
- addend:=swapendian(addend);
- end;
- end;
- procedure MaybeSwapElfDyn(var h : telf32dyn);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- d_tag:=swapendian(d_tag);
- d_val:=swapendian(d_val);
- end;
- end;
- procedure MaybeSwapElfDyn(var h : telf64dyn);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- d_tag:=swapendian(d_tag);
- d_val:=swapendian(d_val);
- end;
- end;
- procedure MaybeSwapElfverdef(var h: TElfverdef);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- vd_version:=swapendian(vd_version);
- vd_flags:=swapendian(vd_flags);
- vd_ndx:=swapendian(vd_ndx);
- vd_cnt:=swapendian(vd_cnt);
- vd_hash:=swapendian(vd_hash);
- vd_aux:=swapendian(vd_aux);
- vd_next:=swapendian(vd_next);
- end;
- end;
- procedure MaybeSwapElfverdaux(var h: TElfverdaux);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- vda_name:=swapendian(vda_name);
- vda_next:=swapendian(vda_next);
- end;
- end;
- procedure MaybeSwapElfverneed(var h: TElfverneed);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- vn_version:=swapendian(vn_version);
- vn_cnt:=swapendian(vn_cnt);
- vn_file:=swapendian(vn_file);
- vn_aux:=swapendian(vn_aux);
- vn_next:=swapendian(vn_next);
- end;
- end;
- procedure MaybeSwapElfvernaux(var h: TElfvernaux);
- begin
- if source_info.endian<>target_info.endian then
- with h do
- begin
- vna_hash:=swapendian(vna_hash);
- vna_flags:=swapendian(vna_flags);
- vna_other:=swapendian(vna_other);
- vna_name:=swapendian(vna_name);
- vna_next:=swapendian(vna_next);
- end;
- end;
- function GetElfSymbolVisibility(other: byte): byte; inline;
- begin
- result:=other and 3;
- end;
- procedure SetElfSymbolVisibility(var other: byte; vis: byte);
- begin
- other:=(other and not(3)) or vis;
- end;
- end.
|