20#include "pedigree/kernel/Log.h"
21#include "pedigree/kernel/linker/Elf.h"
22#include "pedigree/kernel/linker/KernelElf.h"
23#include "pedigree/kernel/process/Process.h"
24#include "pedigree/kernel/process/Thread.h"
25#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
26#include "pedigree/kernel/processor/Processor.h"
27#include "pedigree/kernel/processor/ProcessorInformation.h"
28#include "pedigree/kernel/processor/VirtualAddressSpace.h"
29#include "pedigree/kernel/utilities/Iterator.h"
30#include "pedigree/kernel/utilities/MemoryAllocator.h"
31#include "pedigree/kernel/utilities/assert.h"
32#include "pedigree/kernel/utilities/utility.h"
39#define VERBOSE_NOTICE(x) NOTICE(x)
41#define VERBOSE_NOTICE(x)
44static void resolveNeeded() {
46 "ELF: resolveNeeded() called but binary should have been fully "
53static T* copy(T* buff,
size_t numBytes) {
54 T* ret =
new T[(numBytes +
sizeof(T) - 1) /
sizeof(T)];
55 MemoryCopy(ret, buff, numBytes);
63 T* pCurrent,
size_t size) {
64 for (
size_t i = 0; i < nProgramHeaders; i++) {
66 if ((ph.vaddr <=
reinterpret_cast<uintptr_t
>(pCurrent)) &&
67 (
reinterpret_cast<uintptr_t
>(pCurrent) < ph.vaddr + ph.filesz)) {
68 uintptr_t loc = (
reinterpret_cast<uintptr_t
>(pCurrent) - ph.vaddr) + ph.offset;
69 pCurrent =
new T[(size +
sizeof(T) - 1) /
sizeof(T)];
70 MemoryCopy(
reinterpret_cast<uint8_t*
>(pCurrent), &pBuffer[loc], size);
79 m_nSymbolTableSize(0),
81 m_nStringTableSize(0),
94 m_pDynamicSymbolTable(0),
95 m_nDynamicSymbolTableSize(0),
96 m_pDynamicStringTable(0),
97 m_nDynamicStringTableSize(0),
100 m_pProgramHeaders(0),
101 m_nProgramHeaders(0),
111 delete[] m_pSymbolTable;
112 delete[] m_pStringTable;
113 delete[] m_pShstrtab;
115 delete[] m_pRelTable;
116 delete[] m_pRelaTable;
117 delete[] m_pPltRelTable;
118 delete[] m_pPltRelaTable;
119 delete[] m_pDebugTable;
120 delete[] m_pDynamicSymbolTable;
121 delete[] m_pDynamicStringTable;
122 delete[] m_pSectionHeaders;
123 delete[] m_pProgramHeaders;
128 m_nSymbolTableSize(elf.m_nSymbolTableSize),
130 m_nStringTableSize(elf.m_nStringTableSize),
132 m_nShstrtabSize(elf.m_nShstrtabSize),
133 m_pGotTable(elf.m_pGotTable),
136 m_nRelTableSize(elf.m_nRelTableSize),
137 m_nRelaTableSize(elf.m_nRelaTableSize),
140 m_bUsesRela(elf.m_bUsesRela),
142 m_nDebugTableSize(elf.m_nDebugTableSize),
143 m_pDynamicSymbolTable(0),
144 m_nDynamicSymbolTableSize(elf.m_nDynamicSymbolTableSize),
145 m_pDynamicStringTable(0),
146 m_nDynamicStringTableSize(elf.m_nDynamicStringTableSize),
147 m_pSectionHeaders(0),
148 m_nSectionHeaders(elf.m_nSectionHeaders),
149 m_pProgramHeaders(0),
150 m_nProgramHeaders(elf.m_nProgramHeaders),
151 m_nPltSize(elf.m_nPltSize),
152 m_nEntry(elf.m_nEntry),
153 m_NeededLibraries(elf.m_NeededLibraries),
155 m_InitFunc(elf.m_InitFunc),
156 m_FiniFunc(elf.m_FiniFunc),
157 m_LoadBase(elf.m_LoadBase) {
159 m_pSymbolTable = copy(elf.m_pSymbolTable, m_nSymbolTableSize);
162 m_pStringTable = copy(elf.m_pStringTable, m_nStringTableSize);
165 m_pShstrtab = copy(elf.m_pShstrtab, m_nShstrtabSize);
168 m_pRelTable = copy(elf.m_pRelTable, m_nRelTableSize);
169 m_pRelaTable = copy(elf.m_pRelaTable, m_nRelaTableSize);
173 m_pPltRelaTable = copy(elf.m_pPltRelaTable, m_nPltSize);
175 m_pPltRelTable = copy(elf.m_pPltRelTable, m_nPltSize);
178 m_pDebugTable = copy(elf.m_pDebugTable, m_nDebugTableSize);
181 m_pDynamicSymbolTable = copy(elf.m_pDynamicSymbolTable, m_nDynamicSymbolTableSize);
184 m_pDynamicStringTable = copy(elf.m_pDynamicStringTable, m_nDynamicStringTableSize);
187 m_pSectionHeaders = copy(elf.m_pSectionHeaders, m_nSectionHeaders *
sizeof(
ElfSectionHeader_t));
190 m_pProgramHeaders = copy(elf.m_pProgramHeaders, m_nProgramHeaders *
sizeof(
ElfProgramHeader_t));
193 intptr_t diff =
reinterpret_cast<uintptr_t
>(m_pDynamicStringTable) -
194 reinterpret_cast<uintptr_t
>(elf.m_pDynamicStringTable);
200 m_SymbolTable.
copyTable(
this, elf.m_SymbolTable);
205 VERBOSE_NOTICE(
"Elf::createNeededOnly: buffer at "
206 <<
Hex <<
reinterpret_cast<uintptr_t
>(pBuffer) <<
", len " << length);
208 if (!pBuffer || !length)
215 if ((pHeader->ident[1] !=
'E') || (pHeader->ident[2] !=
'L') || (pHeader->ident[3] !=
'F') ||
216 (pHeader->ident[0] != 127)) {
217 ERROR(
"ELF file: ident check failed [" <<
String(
reinterpret_cast<const char*
>(pHeader->ident))
223 if (pHeader->ident[4] != (BITS_32 == 1 ? 1 : 2 )) {
224 ERROR(
"ELF file: wrong bit length!");
228 if (pHeader->phnum > 0) {
229 m_nProgramHeaders = pHeader->phnum;
231 MemoryCopy(
reinterpret_cast<uint8_t*
>(m_pProgramHeaders), &pBuffer[pHeader->phoff],
234 size_t nDynamicStringTableSize = 0;
237 for (
size_t i = 0; i < m_nProgramHeaders; i++) {
238 if (m_pProgramHeaders[i].type == PT_DYNAMIC) {
243 while (pDyn->tag != DT_NULL) {
246 m_NeededLibraries.
pushBack(
reinterpret_cast<char*
>(pDyn->un.ptr));
249 m_pDynamicStringTable =
reinterpret_cast<char*
>(pDyn->un.ptr);
252 nDynamicStringTableSize = pDyn->un.val;
258 }
else if (m_pProgramHeaders[i].type == PT_INTERP) {
260 m_sInterpreter =
String(
reinterpret_cast<char*
>(&pBuffer[pInterp->offset]));
263 VERBOSE_NOTICE(
"ELF::createNeededOnly interpreter is " << m_sInterpreter);
268 if (m_pDynamicStringTable) {
269 m_pDynamicStringTable =
elfCopy(pBuffer, m_pProgramHeaders, m_nProgramHeaders,
270 m_pDynamicStringTable, nDynamicStringTableSize);
276 *it = *it +
reinterpret_cast<uintptr_t
>(m_pDynamicStringTable);
292 if ((pHeader->ident[1] !=
'E') || (pHeader->ident[2] !=
'L') || (pHeader->ident[3] !=
'F') ||
293 (pHeader->ident[0] != 127)) {
297 if (pHeader->ident[4] != (BITS_32 == 1 ? 1 : 2 )) {
305 VERBOSE_NOTICE(
"Elf::create: buffer at " <<
Hex <<
reinterpret_cast<uintptr_t
>(pBuffer)
306 <<
", len " << length);
311 if ((pHeader->ident[1] !=
'E') || (pHeader->ident[2] !=
'L') || (pHeader->ident[3] !=
'F') ||
312 (pHeader->ident[0] != 127)) {
313 ERROR(
"ELF file: ident check failed [" <<
String(
reinterpret_cast<const char*
>(pHeader->ident))
319 if (pHeader->ident[4] != (BITS_32 == 1 ? 1 : 2 )) {
320 ERROR(
"ELF file: wrong bit length!");
324 m_nSectionHeaders = pHeader->shnum;
326 MemoryCopy(
reinterpret_cast<uint8_t*
>(m_pSectionHeaders), &pBuffer[pHeader->shoff],
333 m_nShstrtabSize = pShstrtab->size;
334 m_pShstrtab =
new char[m_nShstrtabSize];
335 MemoryCopy(
reinterpret_cast<uint8_t*
>(m_pShstrtab), &pBuffer[pShstrtab->offset], m_nShstrtabSize);
339 for (
int i = 0; i < pHeader->shnum; i++) {
340 const char* pStr = m_pShstrtab + m_pSectionHeaders[i].name;
341 if (!StringCompare(pStr,
".symtab"))
342 pSymbolTable = &m_pSectionHeaders[i];
343 if (!StringCompare(pStr,
".strtab"))
344 pStringTable = &m_pSectionHeaders[i];
347 if (pSymbolTable == 0) {
348 WARNING(
"ELF: symbol table not found!");
350 m_nSymbolTableSize = pSymbolTable->size;
352 MemoryCopy(
reinterpret_cast<uint8_t*
>(m_pSymbolTable), &pBuffer[pSymbolTable->offset],
356 if (pStringTable == 0) {
357 WARNING(
"ELF: string table not found!");
359 m_nStringTableSize = pStringTable->size;
360 m_pStringTable =
new char[m_nStringTableSize];
361 MemoryCopy(
reinterpret_cast<uint8_t*
>(m_pStringTable), &pBuffer[pStringTable->offset],
366 if (pHeader->phnum > 0) {
367 m_nProgramHeaders = pHeader->phnum;
369 MemoryCopy(
reinterpret_cast<uint8_t*
>(m_pProgramHeaders), &pBuffer[pHeader->phoff],
375 for (
size_t i = 0; i < m_nProgramHeaders; i++) {
376 if (m_pProgramHeaders[i].type == PT_DYNAMIC) {
381 while (pDyn->tag != DT_NULL) {
384 VERBOSE_NOTICE(
"DT_NEEDED");
385 m_NeededLibraries.
pushBack(
reinterpret_cast<char*
>(pDyn->un.ptr));
388 VERBOSE_NOTICE(
"DT_SYMTAB");
389 m_pDynamicSymbolTable =
reinterpret_cast<ElfSymbol_t*
>(pDyn->un.ptr);
390 VERBOSE_NOTICE(
" -> " <<
reinterpret_cast<void*
>(m_pDynamicSymbolTable));
393 VERBOSE_NOTICE(
"DT_STRTAB");
394 m_pDynamicStringTable =
reinterpret_cast<char*
>(pDyn->un.ptr);
395 VERBOSE_NOTICE(
" -> " <<
reinterpret_cast<void*
>(m_pDynamicStringTable));
398 VERBOSE_NOTICE(
"DT_SYMENT");
404 VERBOSE_NOTICE(
"DT_STRSZ");
405 m_nDynamicStringTableSize = pDyn->un.val;
408 VERBOSE_NOTICE(
"DT_RELA");
409 m_pRelaTable =
reinterpret_cast<ElfRela_t*
>(pDyn->un.ptr);
412 VERBOSE_NOTICE(
"DT_REL");
413 m_pRelTable =
reinterpret_cast<ElfRel_t*
>(pDyn->un.ptr);
416 VERBOSE_NOTICE(
"DT_RELSZ");
417 m_nRelTableSize = pDyn->un.val;
420 VERBOSE_NOTICE(
"DT_RELASZ");
421 m_nRelaTableSize = pDyn->un.val;
424 VERBOSE_NOTICE(
"DT_PLTGOT");
425 VERBOSE_NOTICE(
"GOT A GOT");
426 m_pGotTable =
reinterpret_cast<uintptr_t*
>(pDyn->un.ptr);
429 VERBOSE_NOTICE(
"DT_JMPREL");
431 m_pPltRelaTable =
reinterpret_cast<ElfRela_t*
>(pDyn->un.ptr);
433 m_pPltRelTable =
reinterpret_cast<ElfRel_t*
>(pDyn->un.ptr);
437 VERBOSE_NOTICE(
"DT_PLTREL");
438 if (pDyn->un.val == DT_RELA) {
444 VERBOSE_NOTICE(
"DT_PLTRELSZ");
445 m_nPltSize = pDyn->un.val;
448 VERBOSE_NOTICE(
"DT_INIT");
449 m_InitFunc = pDyn->un.val;
452 VERBOSE_NOTICE(
"DT_FINI");
453 m_FiniFunc = pDyn->un.val;
460 case DT_INIT_ARRAYSZ:
461 case DT_FINI_ARRAYSZ:
463 VERBOSE_NOTICE(
"ELF: skipped dynamic metadata tag " <<
Hex << pDyn->tag);
466 ERROR(
"ELF: unhandled dynamic tag " <<
Hex << pDyn->tag);
471 }
else if (m_pProgramHeaders[i].type == PT_INTERP) {
473 m_sInterpreter =
String(
reinterpret_cast<char*
>(&pBuffer[pInterp->offset]));
475 VERBOSE_NOTICE(
"ELF::create interpreter is " << m_sInterpreter);
479 m_nDynamicSymbolTableSize =
reinterpret_cast<uintptr_t
>(m_pDynamicStringTable) -
480 reinterpret_cast<uintptr_t
>(m_pDynamicSymbolTable);
484 if (m_pDynamicSymbolTable) {
485 m_pDynamicSymbolTable =
elfCopy(pBuffer, m_pProgramHeaders, m_nProgramHeaders,
486 m_pDynamicSymbolTable, m_nDynamicSymbolTableSize);
488 if (m_pDynamicStringTable) {
489 m_pDynamicStringTable =
elfCopy(pBuffer, m_pProgramHeaders, m_nProgramHeaders,
490 m_pDynamicStringTable, m_nDynamicStringTableSize);
496 *it = *it +
reinterpret_cast<uintptr_t
>(m_pDynamicStringTable);
501 elfCopy(pBuffer, m_pProgramHeaders, m_nProgramHeaders, m_pRelTable, m_nRelTableSize);
504 elfCopy(pBuffer, m_pProgramHeaders, m_nProgramHeaders, m_pRelaTable, m_nRelaTableSize);
507 elfCopy(pBuffer, m_pProgramHeaders, m_nProgramHeaders, m_pPltRelTable, m_nPltSize);
510 elfCopy(pBuffer, m_pProgramHeaders, m_nProgramHeaders, m_pPltRelaTable, m_nPltSize);
513 m_nEntry = pHeader->entry;
519bool Elf::loadModule(uint8_t* pBuffer,
size_t length, uintptr_t& loadBase,
size_t& loadSize,
527 for (
size_t i = 0; i < m_nProgramHeaders; ++i) {
528 if (m_pProgramHeaders[i].type == PT_LOAD) {
529 loadSize += m_pProgramHeaders[i].vaddr + m_pProgramHeaders[i].memsz;
534 for (
size_t i = 0; i < m_nSectionHeaders; i++) {
535 if (m_pSectionHeaders[i].flags & SHF_ALLOC) {
536 loadSize += m_pSectionHeaders[i].addr;
538 while ((loadSize % m_pSectionHeaders[i].addralign) != 0)
540 loadSize += m_pSectionHeaders[i].size;
544 if (loadSize & pageSzMask) {
545 loadSize = (loadSize & ~pageSzMask) + pageSz;
548 VERBOSE_NOTICE(
"ELF: need " << loadSize <<
" bytes!");
551 ERROR(
"ELF: could not allocate space for this module [loadSize=" << loadSize <<
"]");
555 m_LoadBase = loadBase;
557 for (
size_t i = 0; i < m_nProgramHeaders; ++i) {
558 if (m_pProgramHeaders[i].type == PT_LOAD) {
559 m_pProgramHeaders[i].vaddr += loadBase;
560 uintptr_t baseAddr = m_pProgramHeaders[i].vaddr;
561 uintptr_t loadEnd = baseAddr + m_pProgramHeaders[i].memsz;
562 if (loadEnd & pageSzMask) {
563 loadEnd = (loadEnd & ~pageSzMask) + pageSz;
566 for (uintptr_t addr = baseAddr; addr < loadEnd; addr += pageSz) {
567 void* virt =
reinterpret_cast<void*
>(addr);
571 ERROR(
"mapping " <<
Hex << virt <<
" to " << phys <<
" failed...");
579 MemoryCopy(
reinterpret_cast<void*
>(baseAddr), pBuffer + m_pProgramHeaders[i].offset,
580 m_pProgramHeaders[i].filesz);
581 if (m_pProgramHeaders[i].memsz > m_pProgramHeaders[i].filesz) {
582 ByteSet(
reinterpret_cast<void*
>(baseAddr + m_pProgramHeaders[i].filesz), 0,
583 m_pProgramHeaders[i].memsz - m_pProgramHeaders[i].filesz);
589 for (
size_t i = 0; i < m_nSectionHeaders; i++) {
591 if (m_pSectionHeaders[i].flags & SHF_ALLOC) {
592 m_pSectionHeaders[i].addr += loadBase;
595 if ((m_pSectionHeaders[i].flags & SHF_ALLOC) == 0) {
597 const char* pStr = m_pShstrtab + m_pSectionHeaders[i].name;
598 if (!StringCompare(pStr,
".debug_frame")) {
599 m_pDebugTable =
reinterpret_cast<uint32_t*
>(m_pSectionHeaders[i].addr);
600 uintptr_t* debugTablePointers =
reinterpret_cast<uintptr_t*
>(m_pSectionHeaders[i].addr);
601 m_nDebugTableSize = m_pSectionHeaders[i].size;
607 while (nIndex < m_nDebugTableSize) {
609 assert(!(nIndex %
sizeof(uint32_t)));
610 uint32_t nLength = m_pDebugTable[nIndex /
sizeof(uint32_t)];
612 nIndex +=
sizeof(uint32_t);
614 const uint32_t k_nCieId = 0xFFFFFFFF;
616 if (nLength == 0xFFFFFFFF) {
617 ERROR(
"64-bit DWARF file detected, but not supported!");
623 uint32_t nCie = m_pDebugTable[nIndex /
sizeof(uint32_t)];
624 nIndex +=
sizeof(uint32_t);
627 if (nCie == k_nCieId) {
629 nIndex += nLength -
sizeof(processor_register_t);
634 assert(!(nIndex %
sizeof(uintptr_t)));
635 uintptr_t* nInitialLocation = &debugTablePointers[nIndex /
sizeof(uintptr_t)];
636 *nInitialLocation += loadBase;
638 nIndex += nLength -
sizeof(processor_register_t);
649 if (m_pSymbolTable && m_pStringTable) {
652 const char* pStrtab =
reinterpret_cast<const char*
>(m_pStringTable);
654 size_t numSymbolTableEntries = m_nSymbolTableSize /
sizeof(
ElfSymbol_t);
655 for (
size_t i = 0; i < numSymbolTableEntries; i++) {
658 size_t nameLengthHint = 0;
661 if ((i + 1) >= numSymbolTableEntries) {
664 if (pNextSymbol->name > pSymbol->name) {
665 nameLengthHint = pNextSymbol->name - pSymbol->name;
669 if (ST_TYPE(pSymbol->info) == STT_SECTION) {
675 if (!(pSh->flags & SHF_ALLOC)) {
680 pStr =
reinterpret_cast<const char*
>(m_pShstrtab) + pSh->name;
682 pStr = pStrtab + pSymbol->name;
686 switch (ST_BIND(pSymbol->info)) {
688 binding = SymbolTable::Local;
691 binding = SymbolTable::Global;
694 binding = SymbolTable::Weak;
697 binding = SymbolTable::Global;
702 if (ST_TYPEOK(pSymbol->info)) {
705 if (*pStr !=
'\0' && pSymbol->shndx != 0) {
706 String name(pStr, nameLengthHint);
707 m_SymbolTable.
insert(name, binding,
this, pSymbol->value + loadBase);
708 if ((pSymbol->other != STV_HIDDEN) || TRACK_HIDDEN_SYMBOLS) {
710 pSymbolTableCopy->
insert(name, binding,
this, pSymbol->value + loadBase);
718 if (pSymbolTableCopy) {
723 if (!relocateModinfo(pBuffer, length)) {
724 ERROR(
"Failed to relocate modinfo!");
730 m_pGotTable[2] =
reinterpret_cast<uintptr_t
>(resolveNeeded);
737 bool bRelocate = relocate(pBuffer, length);
746 if (m_nProgramHeaders == 0) {
747 ERROR(
"TODO: need to do section headers insetad");
750 for (
size_t i = 0; i < m_nProgramHeaders; ++i) {
751 if (m_pProgramHeaders[i].type == PT_LOAD) {
752 uintptr_t baseAddr = m_pProgramHeaders[i].vaddr;
753 uintptr_t loadEnd = baseAddr + m_pProgramHeaders[i].memsz;
754 if (loadEnd & pageSzMask) {
755 loadEnd = (loadEnd & ~pageSzMask) + pageSz;
760 if (m_pProgramHeaders[i].flags & PF_X) {
763 if (m_pProgramHeaders[i].flags & PF_W) {
767 for (uintptr_t addr = baseAddr; addr < loadEnd; addr += pageSz) {
768 void* virt =
reinterpret_cast<void*
>(addr);
778 bool bAllocate,
size_t* pSize) {
779 VERBOSE_NOTICE(
"Elf::allocate: buffer at " <<
Hex <<
reinterpret_cast<uintptr_t
>(pBuffer)
780 <<
", len " << length);
786 uintptr_t start = ~uintptr_t{0};
787 for (
size_t i = 0; i < m_nProgramHeaders; i++) {
788 if (m_pProgramHeaders[i].type == PT_LOAD) {
789 if (m_pProgramHeaders[i].vaddr > (~uintptr_t{0} - m_pProgramHeaders[i].memsz)) {
792 const uintptr_t segmentEnd = m_pProgramHeaders[i].vaddr + m_pProgramHeaders[i].memsz;
793 if (segmentEnd > end)
795 if (m_pProgramHeaders[i].vaddr < start)
796 start = m_pProgramHeaders[i].vaddr;
799 if (start == ~uintptr_t{0} || end < start) {
804 const uintptr_t pageMask = pageSize - 1;
805 const uintptr_t alignedStart = start & ~pageMask;
806 if (end > (~uintptr_t{0} - pageMask)) {
809 const uintptr_t alignedEnd = (end + pageMask) & ~pageMask;
810 const uintptr_t allocationSize = alignedEnd - alignedStart;
811 if (!allocationSize) {
816 *pSize = allocationSize;
821 if (m_nEntry < 0x100000) {
825 if (alignedStart != 0) {
826 ERROR(
"Elf::allocate: non-zero-based dynamic object is unsupported");
829 if (!pProcess->allocateUserRange(Process::UserRegion::Dynamic, allocationSize, loadBase)) {
830 if (!pProcess->allocateUserRange(Process::UserRegion::Normal, allocationSize, loadBase)) {
835 loadBase = alignedStart;
840 if (!pProcess->allocateSpecificUserRange(Process::UserRegion::Normal, alignedStart,
845 m_LoadBase = loadBase;
848 const uintptr_t loadAddr = (m_nEntry < 0x100000) ? loadBase : alignedStart;
849 if (loadAddr > (~uintptr_t{0} - allocationSize)) {
852 for (uintptr_t offset = 0; offset < allocationSize; offset += pageSize) {
853 const uintptr_t j = loadAddr + offset;
856 phys,
reinterpret_cast<void*
>(j),
859 WARNING(
"map() failed for address " <<
Hex << j);
865 if (m_pDynamicSymbolTable && m_pDynamicStringTable) {
868 const char* pStrtab = m_pDynamicStringTable;
871 while (
reinterpret_cast<uintptr_t
>(pSymbol) <
872 reinterpret_cast<uintptr_t
>(m_pDynamicSymbolTable) + m_nDynamicSymbolTableSize) {
873 const char* pStr = pStrtab + pSymbol->name;
876 switch (ST_BIND(pSymbol->info)) {
878 binding = SymbolTable::Local;
881 binding = SymbolTable::Global;
884 binding = SymbolTable::Weak;
887 binding = SymbolTable::Global;
891 if ((pSymbol->other != STV_HIDDEN) || TRACK_HIDDEN_SYMBOLS) {
892 if (ST_TYPEOK(pSymbol->info)) {
895 if (pSymbol->shndx != 0) {
897 m_SymbolTable.
insert(
String(pStr), binding,
this, pSymbol->value);
902 pSymtab->
insert(
String(pStr), binding,
this, pSymbol->value + loadBase);
907 if (binding == SymbolTable::Weak) {
908 Elf_Xword value = pSymbol->value;
926 uintptr_t nStart, uintptr_t nEnd,
bool relocate, uintptr_t destinationBase) {
927 VERBOSE_NOTICE(
"LOAD @" <<
Hex << loadBase);
928 for (
size_t i = 0; i < m_nProgramHeaders; i++) {
929 if (m_pProgramHeaders[i].type == PT_LOAD) {
930 uintptr_t loadAddr = m_pProgramHeaders[i].vaddr + loadBase;
931 VERBOSE_NOTICE(
"LOAD[" << i <<
"]: @" <<
Hex << loadAddr <<
".");
933 if (nStart > (loadAddr + m_pProgramHeaders[i].memsz))
935 if (nEnd <= loadAddr)
937 uintptr_t sectionStart = (loadAddr >= nStart) ? loadAddr : nStart;
939 uintptr_t offset = m_pProgramHeaders[i].offset + (sectionStart - loadAddr);
940 uintptr_t filesz = (loadAddr + m_pProgramHeaders[i].filesz >= nEnd)
941 ? (nEnd - sectionStart)
942 : (loadAddr + m_pProgramHeaders[i].filesz - sectionStart);
943 if (loadAddr + m_pProgramHeaders[i].filesz < nStart)
945 uintptr_t memsz = (loadAddr + m_pProgramHeaders[i].memsz >= nEnd)
946 ? (nEnd - sectionStart)
947 : (loadAddr + m_pProgramHeaders[i].memsz - sectionStart);
949 const uintptr_t destination =
950 destinationBase ? destinationBase + (sectionStart - nStart) : sectionStart;
953 MemoryCopy(
reinterpret_cast<uint8_t*
>(destination), &pBuffer[offset], filesz);
955 ByteSet(
reinterpret_cast<uint8_t*
>(destination + filesz), 0, memsz - filesz);
957 if (!destinationBase) {
971 for (
ElfRel_t* pRel = m_pRelTable; pRel < (m_pRelTable + (m_nRelTableSize /
sizeof(
ElfRel_t)));
973 if ((pRel->offset + loadBase < nStart) || (pRel->offset + loadBase >= nEnd))
975 const uintptr_t logicalAddress = pRel->offset + loadBase;
976 const uintptr_t destinationAddress =
977 destinationBase ? destinationBase + (logicalAddress - nStart) : logicalAddress;
979 destinationBase ? destinationBase + (nEnd - nStart) : 0))
987 pRel < (m_pRelaTable + (m_nRelaTableSize /
sizeof(
ElfRela_t))); pRel++) {
988 if ((pRel->offset + loadBase < nStart) || (pRel->offset + loadBase >= nEnd))
990 const uintptr_t logicalAddress = pRel->offset + loadBase;
991 const uintptr_t destinationAddress =
992 destinationBase ? destinationBase + (logicalAddress - nStart) : logicalAddress;
994 destinationBase ? destinationBase + (nEnd - nStart) : 0))
1001 if (m_pPltRelTable) {
1004 for (
size_t i = 0; i < m_nPltSize /
sizeof(
ElfRel_t); i++, pRel++) {
1005 if ((pRel->offset + loadBase < nStart) || (pRel->offset + loadBase >= nEnd))
1007 const uintptr_t logicalAddress = loadBase + pRel->offset;
1008 if (destinationBase && nEnd - logicalAddress <
sizeof(uintptr_t))
1010 uintptr_t* address =
reinterpret_cast<uintptr_t*
>(
1011 destinationBase ? destinationBase + (logicalAddress - nStart) : logicalAddress);
1012 *address += loadBase;
1015 if (m_pPltRelaTable) {
1018 for (
size_t i = 0; i < m_nPltSize /
sizeof(
ElfRela_t); i++, pRel++) {
1019 if ((pRel->offset + loadBase < nStart) || (pRel->offset + loadBase >= nEnd))
1021 const uintptr_t logicalAddress = loadBase + pRel->offset;
1022 if (destinationBase && nEnd - logicalAddress <
sizeof(uintptr_t))
1024 uintptr_t* address =
reinterpret_cast<uintptr_t*
>(
1025 destinationBase ? destinationBase + (logicalAddress - nStart) : logicalAddress);
1026 *address += loadBase;
1040 entry = pHeader->entry;
1046 size_t& phdrEntrySize, uintptr_t& phdrAddress) {
1052 phdrCount = pHeader->phnum;
1053 phdrEntrySize = pHeader->phentsize;
1054 phdrAddress =
reinterpret_cast<uintptr_t
>(pBuffer) + pHeader->phoff;
1065 if (!m_pSymbolTable || !m_pStringTable) {
1073 if (!symbolTable || !m_pStringTable) {
1077 T* pSymbol = symbolTable;
1079 const char* pStrtab =
reinterpret_cast<const char*
>(m_pStringTable);
1081 for (
size_t i = 0; i < m_nSymbolTableSize /
sizeof(T); i++) {
1083 if (ST_TYPE(pSymbol->info) != STT_FUNC &&
1084 ST_TYPE(pSymbol->info) != STT_NOTYPE ) {
1091 if (!pSymbol->shndx || pSymbol->shndx >= 0xff00 || ST_BIND(pSymbol->info) > STB_WEAK ||
1092 pSymbol->value > ~uintptr_t{0} - m_LoadBase) {
1097 const uintptr_t symbolAddress = pSymbol->value + m_LoadBase;
1100 if (addr >= symbolAddress &&
1101 (pSymbol->size ? addr - symbolAddress < pSymbol->size : addr == symbolAddress) &&
1102 pSymbol->name < m_nStringTableSize) {
1103 const char* pStr = pStrtab + pSymbol->name;
1104 if (!*pStr || BoundedStringLength(pStr, m_nStringTableSize - pSymbol->name) ==
1105 m_nStringTableSize - pSymbol->name) {
1110 *startAddr = symbolAddress;
1123 uintptr_t value = m_SymbolTable.
lookup(
String(sym),
this);
1127 return value + loadBase;
1131 return reinterpret_cast<uintptr_t
>(m_pGotTable);
1138bool Elf::relocate(uint8_t* pBuffer, uintptr_t length) {
1140 for (
size_t i = 0; i < m_nSectionHeaders; i++) {
1143 if (pSh->type != SHT_REL && pSh->type != SHT_RELA)
1152 const char* pStr =
reinterpret_cast<const char*
>(m_pShstrtab) + pTarget->name;
1153 if (!StringCompare(pStr,
".modinfo")) {
1160 if (pSh->type == SHT_REL) {
1163 pRel < reinterpret_cast<ElfRel_t*>(&pBuffer[pSh->offset + pSh->size]); pRel++) {
1171 else if (pSh->type == SHT_RELA) {
1172 for (ElfRela_t* pRel =
reinterpret_cast<ElfRela_t*
>(&pBuffer[pSh->offset]);
1173 pRel < reinterpret_cast<ElfRela_t*>(&pBuffer[pSh->offset + pSh->size]); pRel++) {
1187bool Elf::relocateModinfo(uint8_t* pBuffer, uintptr_t length) {
1189 for (
size_t i = 0; i < m_nSectionHeaders; i++) {
1191 if (pSh->type != SHT_REL && pSh->type != SHT_RELA) {
1204 const char* pStr =
reinterpret_cast<const char*
>(m_pShstrtab) + pTarget->name;
1205 if (StringCompare(pStr,
".modinfo")) {
1210 if (pSh->type == SHT_REL) {
1213 pRel < reinterpret_cast<ElfRel_t*>(&pBuffer[pSh->offset + pSh->size]); pRel++) {
1219 else if (pSh->type == SHT_RELA) {
1221 for (ElfRela_t* pRel =
reinterpret_cast<ElfRela_t*
>(&pBuffer[pSh->offset]);
1222 pRel < reinterpret_cast<ElfRela_t*>(&pBuffer[pSh->offset + pSh->size]); pRel++) {
1236 if (m_pPltRelTable) {
1238 ElfRel_t* pRel = adjust_pointer(m_pPltRelTable, off);
1242 uintptr_t address = loadBase + pRel->offset;
1244 return *
reinterpret_cast<uintptr_t*
>(address);
1247 if (m_pPltRelaTable) {
1252 uintptr_t address = loadBase + pRel.offset;
1254 return *
reinterpret_cast<uintptr_t*
>(address);
1259uintptr_t Elf::debugFrameTable() {
1260 return reinterpret_cast<uintptr_t
>(m_pDebugTable);
1263uintptr_t Elf::debugFrameTableLength() {
1264 return m_nDebugTableSize;
1268 return m_NeededLibraries;
1272 return m_sInterpreter;
1282 if (m_pDynamicSymbolTable && m_pDynamicStringTable) {
1285 const char* pStrtab = m_pDynamicStringTable;
1288 while (
reinterpret_cast<uintptr_t
>(pSymbol) <
1289 reinterpret_cast<uintptr_t
>(m_pDynamicSymbolTable) + m_nDynamicSymbolTableSize) {
1290 const char* pStr = pStrtab + pSymbol->name;
1294 if (pSymbol->shndx != 0) {
1296 switch (ST_BIND(pSymbol->info)) {
1298 binding = SymbolTable::Local;
1301 binding = SymbolTable::Global;
1304 binding = SymbolTable::Weak;
1307 binding = SymbolTable::Global;
1311 if ((pSymbol->other != STV_HIDDEN) || TRACK_HIDDEN_SYMBOLS) {
1312 if (ST_TYPEOK(pSymbol->info)) {
1315 pSymtab->
insert(
String(pStr), binding,
this, pSymbol->value + loadBase);
1327 if (!pSymtabOverride) {
1328 pSymtabOverride = &m_SymbolTable;
1332 VERBOSE_NOTICE(
"no need to preallocate, already done");
1336 size_t numLocal = 0;
1338 size_t numGlobal = 0;
1340 if (m_pSymbolTable) {
1342 for (
size_t i = 0; i < m_nSymbolTableSize /
sizeof(
ElfSymbol_t); i++) {
1343 switch (ST_BIND(m_pSymbolTable[i].info)) {
1359 if (m_pDynamicSymbolTable) {
1361 for (
size_t i = 0; i < m_nDynamicSymbolTableSize /
sizeof(
ElfSymbol_t); i++) {
1362 switch (ST_BIND(m_pDynamicSymbolTable[i].info)) {
1378 if (numLocal || numWeak || numGlobal) {
1379 VERBOSE_NOTICE(
"ELF: preallocating symbol table with " << numGlobal <<
" global " << numWeak
1380 <<
" weak and " << numLocal
1381 <<
" local symbols.");
1382 pSymtabOverride->
preallocate(numGlobal, numWeak,
this, numLocal);
1383 if (pAdditionalSymtab) {
1386 VERBOSE_NOTICE(
"ELF: preallocation has completed");
1393 m_pGotTable = adjust_pointer(m_pGotTable, m_LoadBase);
1396 m_InitFunc += m_LoadBase;
1399 m_FiniFunc += m_LoadBase;
1404template const char* Elf::lookupSymbol<Elf::ElfSymbol_t>(uintptr_t addr, uintptr_t* startAddr = 0,
1407template const char* Elf::lookupSymbol<Elf::Elf32Symbol_t>(uintptr_t addr, uintptr_t* startAddr = 0,
1408 Elf32Symbol_t* symbolTable = 0);
static bool extractEntryPoint(uint8_t *pBuffer, size_t length, uintptr_t &entry)
void populateSymbolTable(SymbolTable *pSymtab, uintptr_t loadBase)
static T * elfCopy(uint8_t *, ElfProgramHeader_t *, size_t, T *, size_t)
String & getInterpreter()
uintptr_t getEntryPoint()
uintptr_t lookupDynamicSymbolAddress(const char *str, uintptr_t loadBase)
bool createNeededOnly(uint8_t *pBuffer, size_t length)
static bool extractInformation(uint8_t *pBuffer, size_t length, size_t &phdrCount, size_t &phdrEntrySize, uintptr_t &phdrAddress)
uintptr_t getLastAddress()
bool create(uint8_t *pBuffer, size_t length)
bool loadModule(uint8_t *pBuffer, size_t length, uintptr_t &loadBase, size_t &loadSize, SymbolTable *pSymbolTableCopy=0)
bool finaliseModule(uint8_t *pBuffer, size_t length)
List< char * > & neededLibraries()
uintptr_t applySpecificRelocation(uintptr_t off, SymbolTable *pSymtab, uintptr_t loadBase, SymbolTable::Policy policy=SymbolTable::LocalFirst)
bool load(uint8_t *pBuffer, size_t length, uintptr_t loadBase, SymbolTable *pSymtab=0, uintptr_t nStart=0, uintptr_t nEnd=~0, bool relocate=true, uintptr_t destinationBase=0)
bool allocate(uint8_t *pBuffer, size_t length, uintptr_t &loadBase, SymbolTable *pSymtab=0, bool bAllocate=true, size_t *pSize=0)
void preallocateSymbols(SymbolTable *pSymtabOverride=nullptr, SymbolTable *pAdditionalSymtab=nullptr)
const char * lookupSymbol(uintptr_t addr, uintptr_t *startAddr, T *symbolTable)
bool applyRelocation(ElfRel_t rel, ElfSectionHeader_t *pSh, SymbolTable *pSymtab=0, uintptr_t loadBase=0, SymbolTable::Policy policy=SymbolTable::LocalFirst, uintptr_t destinationAddress=0, uintptr_t destinationEnd=0)
bool validate(uint8_t *pBuffer, size_t length)
uintptr_t getGlobalOffsetTable()
static KernelElf & instance()
::Iterator< T, node_t > Iterator
virtual physical_uintptr_t allocatePage(size_t pageConstraints=0)=0
static PhysicalMemoryManager & instance()
static constexpr size_t getPageSize() PURE
static ProcessorInformation & information()
static void flushDCacheAndInvalidateICache(uintptr_t startAddr, uintptr_t endAddr)
void insert(const String &name, Binding binding, Elf *pParent, uintptr_t value)
void preallocate(size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
void insertMultiple(SymbolTable *pOther, const String &name, Binding binding, Elf *pParent, uintptr_t value)
void copyTable(Elf *pNewElf, const SymbolTable &newSymtab)
uintptr_t EXPORTED_PUBLIC lookup(const HashedStringView &name, Elf *pElf, Policy policy=LocalFirst, Binding *pBinding=0)
bool hasPreallocated() const
void preallocateAdditional(size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
virtual void setFlags(void *virtualAddress, size_t newFlags)=0
virtual bool map(physical_uintptr_t physicalAddress, void *virtualAddress, size_t flags)=0
virtual bool isMapped(void *virtualAddress)=0
static const size_t KernelMode
static const size_t Write
static const size_t Execute
void pushBack(const T &value)