The Pedigree Project 0.1
Elf.h
1/*
2 * Copyright (c) 2008-2014, Pedigree Developers
3 *
4 * Please see the CONTRIB file in the root of the source tree for a full
5 * list of contributors.
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#ifndef KERNEL_LINKER_ELF_H
21#define KERNEL_LINKER_ELF_H
22#include <config.h>
23
24#ifdef IN_PEDIGREE_KERNEL
25#include "pedigree/kernel/compiler.h"
26#include "pedigree/kernel/processor/types.h"
27#include "pedigree/kernel/utilities/String.h"
28#include "pedigree/kernel/utilities/new"
29#endif
30
31#include "pedigree/kernel/linker/SymbolTable.h"
32#include "pedigree/kernel/utilities/List.h"
33
37#ifdef VERBOSE_LINKER
38#define DEBUG NOTICE
39#else
40#define DEBUG(...)
41#endif
42
43// Object file types
44#define ET_NONE 0x0
45#define ET_REL 0x1
46#define ET_EXEC 0x2
47#define ET_DYN 0x3
48#define ET_CORE 0x4
49
50// Section header types - common to Elf32 and Elf64.
51#define SHT_PROGBITS 0x1 // The data is contained in the program file.
52#define SHT_SYMTAB 0x2 // Symbol table
53#define SHT_STRTAB 0x3 // String table
54#define SHT_RELA 0x4
55#define SHT_HASH 0x5 // Symbol hash table
56#define SHT_DYNAMIC 0x6 // Dynamic linking information
57#define SHT_NOTE 0x7
58#define SHT_NOBITS 0x8 // The data is not contained in the program file.
59#define SHT_REL 0x9
60#define SHT_DYNSYM 0xb
61#define SHT_INIT_ARRAY 0xe
62#define SHT_FINI_ARRAY 0xf
63#define SHT_PREINIT_ARRAY 0x10
64
65// Section header flags - common to Elf32 and Elf64.
66#define SHF_WRITE 0x1
67#define SHF_ALLOC 0x2
68#define SHF_EXECINSTR 0x4
69#define SHF_MASKPROC 0xf0000000
70
71// Program header flags - common to Elf32 and Elf64.
72#define PF_X 0x1
73#define PF_W 0x2
74#define PF_R 0x4
75
76// Process header flags - common to Elf32 and Elf64.
77#define PT_NULL 0 /* Program header table entry unused */
78#define PT_LOAD 1 /* Loadable program segment */
79#define PT_DYNAMIC 2 /* Dynamic linking information */
80#define PT_INTERP 3 /* Program interpreter */
81#define PT_NOTE 4 /* Auxiliary information */
82#define PT_SHLIB 5 /* Reserved */
83#define PT_PHDR 6 /* Entry for header table itself */
84#define PT_TLS 7 /* Thread-local storage segment */
85#define PT_NUM 8 /* Number of defined types */
86
87// Dynamic table flags - common to Elf32 and Elf64.
88#define DT_NULL 0 /* Marks end of dynamic section */
89#define DT_NEEDED 1 /* Name of needed library */
90#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */
91#define DT_PLTGOT 3 /* Processor defined value */
92#define DT_HASH 4 /* Address of symbol hash table */
93#define DT_STRTAB 5 /* Address of string table */
94#define DT_SYMTAB 6 /* Address of symbol table */
95#define DT_RELA 7 /* Address of Rela relocs */
96#define DT_RELASZ 8 /* Total size of Rela relocs */
97#define DT_RELAENT 9 /* Size of one Rela reloc */
98#define DT_STRSZ 10 /* Size of string table */
99#define DT_SYMENT 11 /* Size of one symbol table entry */
100#define DT_INIT 12 /* Address of init function */
101#define DT_FINI 13 /* Address of termination function */
102#define DT_SONAME 14 /* Name of shared object */
103#define DT_RPATH 15 /* Library search path (deprecated) */
104#define DT_SYMBOLIC 16 /* Start symbol search here */
105#define DT_REL 17 /* Address of Rel relocs */
106#define DT_RELSZ 18 /* Total size of Rel relocs */
107#define DT_RELENT 19 /* Size of one Rel reloc */
108#define DT_PLTREL 20 /* Type of reloc in PLT */
109#define DT_DEBUG 21 /* For debugging; unspecified */
110#define DT_TEXTREL 22 /* Reloc might modify .text */
111#define DT_JMPREL 23 /* Address of PLT relocs */
112#define DT_BIND_NOW 24 /* Process relocations of object */
113#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */
114#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */
115#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */
116#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */
117#define DT_RUNPATH 29 /* Library search path */
118#define DT_FLAGS 30 /* Flags for the object being loaded */
119#define DT_ENCODING 32 /* Start of encoded range */
120#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/
121#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */
122
123// Symbol types
124#define STT_NOTYPE 0
125#define STT_OBJECT 1
126#define STT_FUNC 2
127#define STT_SECTION 3
128#define STT_FILE 4
129#define STT_COMMON 5
130#define STT_TLS 6
131
132// Symbol bindings
133#define STB_LOCAL 0
134#define STB_GLOBAL 1
135#define STB_WEAK 2
136
137// Symbol visibilities
138#define STV_DEFAULT 0
139#define STV_INTERNAL 1
140#define STV_HIDDEN 2
141#define STV_PROTECTED 3
142
143#if BITS_32
144
145#define R_SYM(val) ((val) >> 8)
146#define R_TYPE(val) ((val) & 0xff)
147
148#define ST_BIND(i) ((i) >> 4)
149#define ST_TYPE(i) ((i) & 0xf)
150#define ST_INFO(b, t) (((b) << 4) + ((t) & 0xf))
151
152typedef uint32_t Elf_Addr;
153typedef uint32_t Elf_Off;
154typedef uint16_t Elf_Half;
155typedef uint32_t Elf_Word;
156typedef int32_t Elf_Sword;
157
158// We define the Xword and Sxword types for ELF32 even though they don't exist
159// in the spec for forwards compatibility with ELF64.
160typedef uint32_t Elf_Xword;
161typedef int32_t Elf_Sxword;
162
163#elif BITS_64
164
165#define R_SYM(val) ((val) >> 32)
166#define R_TYPE(val) ((val) & 0xffffffffUL)
167
168#define ST_BIND(i) ((i) >> 4)
169#define ST_TYPE(i) ((i) & 0xf)
170#define ST_INFO(b, t) (((b) << 4) + ((t) & 0xf))
171
172typedef uint64_t Elf_Addr;
173typedef uint64_t Elf_Off;
174typedef uint16_t Elf_Half;
175typedef uint32_t Elf_Word;
176typedef int32_t Elf_Sword;
177typedef uint64_t Elf_Xword;
178typedef int64_t Elf_Sxword;
179
180// Compatibility types for 64-bit kernel, which is actually a 32-bit ELF.
181typedef uint32_t Elf32_Addr;
182typedef uint32_t Elf32_Off;
183typedef uint16_t Elf32_Half;
184typedef uint32_t Elf32_Word;
185typedef int32_t Elf32_Sword;
186typedef uint32_t Elf32_Xword;
187typedef int32_t Elf32_Sxword;
188
189#endif
190
191// Is the symbol type OK to add to the symbol table?
192#define ST_TYPEOK(x) (ST_TYPE((x)) <= STT_FUNC)
193
194#ifndef _NO_ELF_CLASS
195
201class EXPORTED_PUBLIC Elf {
202 // PosixSubsystem can use memory mapped files to do its own (very basic)
203 // ELF loading, which is an improvement on load()'s copies.
204 friend class PosixSubsystem;
205 friend class ModuleImage;
206
207 protected:
208 // Forward declaration of ELF symbol type for lookupSymbol template.
209 struct ElfSymbol_t;
210
211 public:
212 enum class ExecutableValidationResult {
213 Valid,
214 Malformed,
215 WrongArchitecture,
216 UnsupportedType,
217 UnsupportedLayout,
218 MultipleInterpreters,
219 };
220
222 Elf_Half type;
223 uintptr_t entryPoint;
224 size_t programHeaderOffset;
225 size_t programHeaderCount;
226 size_t programHeaderSize;
227 uintptr_t loadStart;
228 uintptr_t loadEnd;
229 size_t interpreterOffset;
230 size_t interpreterSize;
231 bool hasInterpreter;
232 };
233
234 static constexpr size_t MaximumProgramHeaderTableSize = 65536;
235 static constexpr size_t MaximumInterpreterSize = 4096;
236
238 Elf();
239
241 virtual ~Elf();
242
244 Elf(const Elf&);
245
247 bool validate(uint8_t* pBuffer, size_t length);
248
251 static ExecutableValidationResult validateExecutableHeader(const uint8_t* pBuffer, size_t length,
252 size_t fileSize,
253 ExecutableMetadata& metadata);
254
257 static ExecutableValidationResult validateExecutableProgramHeaders(const uint8_t* pBuffer,
258 size_t length, size_t fileSize,
259 ExecutableMetadata& metadata);
260
262 static ExecutableValidationResult validateExecutableInterpreter(
263 const uint8_t* pBuffer, size_t length, const ExecutableMetadata& metadata);
264
267 bool create(uint8_t* pBuffer, size_t length);
268
271 bool createNeededOnly(uint8_t* pBuffer, size_t length);
272
276 bool loadModule(uint8_t* pBuffer, size_t length, uintptr_t& loadBase, size_t& loadSize,
277 SymbolTable* pSymbolTableCopy = 0);
278
284 bool finaliseModule(uint8_t* pBuffer, size_t length);
285
290 bool allocate(uint8_t* pBuffer, size_t length, uintptr_t& loadBase, SymbolTable* pSymtab = 0,
291 bool bAllocate = true, size_t* pSize = 0);
292
302 bool load(uint8_t* pBuffer, size_t length, uintptr_t loadBase, SymbolTable* pSymtab = 0,
303 uintptr_t nStart = 0, uintptr_t nEnd = ~0, bool relocate = true,
304 uintptr_t destinationBase = 0);
305
307 static bool extractEntryPoint(uint8_t* pBuffer, size_t length, uintptr_t& entry);
308
310 static bool extractInformation(uint8_t* pBuffer, size_t length, size_t& phdrCount,
311 size_t& phdrEntrySize, uintptr_t& phdrAddress);
312
314 List<char*>& neededLibraries();
315
318 String& getInterpreter();
319
322 uintptr_t getLastAddress();
323
324 uintptr_t getInitFunc() {
325 return m_InitFunc;
326 }
327 uintptr_t getFiniFunc() {
328 return m_FiniFunc;
329 }
330
336 template <class T = ElfSymbol_t>
337 const char* lookupSymbol(uintptr_t addr, uintptr_t* startAddr, T* symbolTable);
338
341 const char* lookupSymbol(uintptr_t addr, uintptr_t* startAddr);
342
344 uintptr_t lookupSymbol(const char* pName);
345
348 uintptr_t lookupDynamicSymbolAddress(const char* str, uintptr_t loadBase);
349
352 uintptr_t applySpecificRelocation(uintptr_t off, SymbolTable* pSymtab, uintptr_t loadBase,
354
357 uintptr_t getGlobalOffsetTable();
358
360 size_t getPltSize();
361
367 void populateSymbolTable(SymbolTable* pSymtab, uintptr_t loadBase);
368
370 void preallocateSymbols(SymbolTable* pSymtabOverride = nullptr,
371 SymbolTable* pAdditionalSymtab = nullptr);
372
373 SymbolTable* getSymbolTable() {
374 return &m_SymbolTable;
375 }
376
378 uintptr_t getEntryPoint();
379
380 uintptr_t debugFrameTable();
381 uintptr_t debugFrameTableLength();
382
384 void setName(const String& s) {
385 m_Name.assign(s);
386 }
387
389 const String& getName() const {
390 return m_Name;
391 }
392
393 protected:
394#endif
395 struct ElfHeader_t {
396 uint8_t ident[16];
397 Elf_Half type;
398 Elf_Half machine;
399 Elf_Word version;
400 Elf_Addr entry;
401 Elf_Off phoff;
402 Elf_Off shoff;
403 Elf_Word flags;
404 Elf_Half ehsize;
405 Elf_Half phentsize;
406 Elf_Half phnum;
407 Elf_Half shentsize;
408 Elf_Half shnum;
409 Elf_Half shstrndx;
410 } PACKED;
411
413 Elf_Word type;
414#if BITS_64
415 Elf_Word flags;
416#endif
417 Elf_Off offset;
418 Elf_Addr vaddr;
419 Elf_Addr paddr;
420 Elf_Xword filesz;
421 Elf_Xword memsz;
422#if !BITS_64
423 Elf_Word flags;
424#endif
425 Elf_Xword align;
426 } PACKED;
427
429 Elf_Word name;
430 Elf_Word type;
431 Elf_Xword flags;
432 Elf_Addr addr;
433 Elf_Off offset;
434 Elf_Xword size;
435 Elf_Word link;
436 Elf_Word info;
437 Elf_Xword addralign;
438 Elf_Xword entsize;
439 } PACKED;
440
441#if BITS_64
443 Elf32_Word name;
444 Elf32_Word type;
445 Elf32_Xword flags;
446 Elf32_Addr addr;
447 Elf32_Off offset;
448 Elf32_Xword size;
449 Elf32_Word link;
450 Elf32_Word info;
451 Elf32_Xword addralign;
452 Elf32_Xword entsize;
453 } PACKED;
454#else
456#endif
457
458 struct ElfSymbol_t {
459 Elf_Word name;
460#if BITS_64
461 uint8_t info;
462 uint8_t other;
463 Elf_Half shndx;
464#endif
465 Elf_Addr value;
466 Elf_Xword size;
467#if !BITS_64
468 uint8_t info;
469 uint8_t other;
470 Elf_Half shndx;
471#endif
472 } PACKED;
473
474#if BITS_64
476 Elf32_Word name;
477 Elf32_Addr value;
478 Elf32_Xword size;
479 uint8_t info;
480 uint8_t other;
481 Elf32_Half shndx;
482 } PACKED;
483#else
485#endif
486
487 struct ElfHash_t {
488 Elf_Word nbucket;
489 Elf_Word nchain;
490 // buckets follow
491 // chains follow
492 };
493
494 struct ElfDyn_t {
495 Elf_Sxword tag;
496 union {
497 Elf_Xword val;
498 Elf_Addr ptr;
499 } un;
500 } PACKED;
501
502 struct ElfRel_t {
503 Elf_Addr offset;
504 Elf_Xword info;
505 } PACKED;
506
507 struct ElfRela_t {
508 Elf_Addr offset;
509 Elf_Xword info;
510 Elf_Sxword addend;
511 } PACKED;
512
513#ifndef _NO_ELF_CLASS
514 private:
515 template <typename T>
516 static T* elfCopy(uint8_t*, ElfProgramHeader_t*, size_t, T*, size_t);
517
518 bool relocate(uint8_t* pBuffer, uintptr_t length);
519 bool relocateModinfo(uint8_t* pBuffer, uintptr_t length);
520
529 bool applyRelocation(ElfRel_t rel, ElfSectionHeader_t* pSh, SymbolTable* pSymtab = 0,
530 uintptr_t loadBase = 0, SymbolTable::Policy policy = SymbolTable::LocalFirst,
531 uintptr_t destinationAddress = 0, uintptr_t destinationEnd = 0);
532
541 bool applyRelocation(ElfRela_t rela, ElfSectionHeader_t* pSh, SymbolTable* pSymtab = 0,
542 uintptr_t loadBase = 0, SymbolTable::Policy policy = SymbolTable::LocalFirst,
543 uintptr_t destinationAddress = 0, uintptr_t destinationEnd = 0);
544
545#if ARMV7
546 bool applyArmRelocation(Elf_Word type, Elf_Word symbolIndex, uintptr_t offset, intptr_t addend,
547 ElfSectionHeader_t* section, SymbolTable* symbols, uintptr_t loadBase,
548 SymbolTable::Policy policy, uintptr_t destinationAddress,
549 uintptr_t destinationEnd);
550#endif
551
553 void rebaseDynamic();
554
555 protected:
556 ElfSymbol_t* m_pSymbolTable;
557 size_t m_nSymbolTableSize;
558 char* m_pStringTable;
559 size_t m_nStringTableSize;
560 char* m_pShstrtab;
561 size_t m_nShstrtabSize;
562 uintptr_t* m_pGotTable; // Global offset table.
563 ElfRel_t* m_pRelTable; // Dynamic REL relocations.
564 ElfRela_t* m_pRelaTable; // Dynamic RELA relocations.
565 size_t m_nRelTableSize;
566 size_t m_nRelaTableSize;
567 ElfRel_t* m_pPltRelTable;
568 ElfRela_t* m_pPltRelaTable;
569 bool m_bUsesRela; // If PltRelaTable is valid, else PltRelTable is.
570 uint32_t* m_pDebugTable;
571 size_t m_nDebugTableSize;
572 ElfSymbol_t* m_pDynamicSymbolTable;
573 size_t m_nDynamicSymbolTableSize;
574 char* m_pDynamicStringTable;
575 size_t m_nDynamicStringTableSize;
576 ElfSectionHeader_t* m_pSectionHeaders;
577 size_t m_nSectionHeaders;
578 ElfProgramHeader_t* m_pProgramHeaders;
579 size_t m_nProgramHeaders;
580 size_t m_nPltSize;
581 uintptr_t m_nEntry;
582 List<char*> m_NeededLibraries;
583 SymbolTable m_SymbolTable;
584 uintptr_t m_InitFunc;
585 uintptr_t m_FiniFunc;
586 String m_sInterpreter;
587
588 String m_Name;
589 uintptr_t m_LoadBase;
590
591 private:
594 Elf& operator=(const Elf&);
595};
596
598extern template const char* Elf::lookupSymbol<Elf::ElfSymbol_t>(uintptr_t addr,
599 uintptr_t* startAddr = 0,
600 ElfSymbol_t* symbolTable = 0);
601#if BITS_64
602extern template const char* Elf::lookupSymbol<Elf::Elf32Symbol_t>(uintptr_t addr,
603 uintptr_t* startAddr = 0,
604 Elf32Symbol_t* symbolTable = 0);
605#endif
606
607#endif
608
611#endif
Definition Elf.h:201
const String & getName() const
Definition Elf.h:389
void setName(const String &s)
Definition Elf.h:384
Elf & operator=(const Elf &)
Definition List.h:61