20 #include "pedigree/kernel/linker/KernelElf.h" 21 #include "pedigree/kernel/BootstrapInfo.h" 22 #include "pedigree/kernel/LockGuard.h" 23 #include "pedigree/kernel/Log.h" 24 #include "pedigree/kernel/linker/SymbolTable.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/MemoryCount.h" 30 #include "pedigree/kernel/utilities/String.h" 31 #include "pedigree/kernel/utilities/utility.h" 39 #define THREADED_MODULE_LOADING 0 41 #define TRACK_HIDDEN_SYMBOLS 1 49 #define EXTENSION_ADDEND 0xFFFFFFFF00000000ULL 52 static T *extend(T *p)
54 #if defined(X86_COMMON) && !defined(BITS_32) 55 uintptr_t u =
reinterpret_cast<uintptr_t
>(p);
56 if (u < EXTENSION_ADDEND)
57 u += EXTENSION_ADDEND;
58 return reinterpret_cast<T *
>(u);
65 static uintptr_t extend(T p)
67 #if defined(X86_COMMON) && !defined(BITS_32) 70 if (u < EXTENSION_ADDEND)
71 u += EXTENSION_ADDEND;
79 static T *retract(T *p)
81 #if defined(X86_COMMON) && !defined(BITS_32) 82 uintptr_t u =
reinterpret_cast<uintptr_t
>(p);
83 if (u >= EXTENSION_ADDEND)
84 u -= EXTENSION_ADDEND;
85 return reinterpret_cast<T *
>(u);
92 static uintptr_t retract(T p)
94 #if defined(X86_COMMON) && !defined(BITS_32) 97 if (u >= EXTENSION_ADDEND)
98 u -= EXTENSION_ADDEND;
108 if (pBootstrap.getSectionHeaderCount() == 0)
110 WARNING(
"No ELF object available to extract symbol table from.");
111 #ifdef STATIC_DRIVERS 125 m_AdditionalSectionHeaders =
new MemoryRegion(
"Kernel ELF Section Headers");
128 size_t sectionHeadersLength = pBootstrap.getSectionHeaderCount() *
129 pBootstrap.getSectionHeaderEntrySize();
130 if ((sectionHeadersLength % pageSz) > 0)
132 sectionHeadersLength += pageSz;
135 *m_AdditionalSectionHeaders, sectionHeadersLength / pageSz,
138 pBootstrap.getSectionHeaders()) ==
false)
140 ERROR(
"KernelElf::initialise failed to allocate for " 141 "m_AdditionalSectionHeaders");
146 physical_uintptr_t start = ~0;
147 physical_uintptr_t end = 0;
148 for (
size_t i = 1; i < pBootstrap.getSectionHeaderCount(); i++)
152 uintptr_t shdr_addr = pBootstrap.getSectionHeaders() +
153 i * pBootstrap.getSectionHeaderEntrySize();
154 Elf32SectionHeader_t *pSh =
155 m_AdditionalSectionHeaders
156 ->convertPhysicalPointer<Elf32SectionHeader_t>(shdr_addr);
158 if ((pSh->flags & SHF_ALLOC) != SHF_ALLOC)
160 if (pSh->addr <= start)
165 if ((pSh->addr + pSh->size) >= end)
167 end = pSh->addr + pSh->size;
173 if ((start & ~(pageSz - 1)) ==
174 (pBootstrap.getSectionHeaders() & ~(pageSz - 1)))
178 delete m_AdditionalSectionHeaders;
179 m_AdditionalSectionHeaders = &m_AdditionalSectionContents;
183 uintptr_t alignedStart = start & ~(pageSz - 1);
184 uintptr_t allocSize = end - alignedStart;
185 if ((allocSize % pageSz) > 0)
189 size_t additionalContentsPages = allocSize / pageSz;
191 m_AdditionalSectionContents, additionalContentsPages,
196 ERROR(
"KernelElf::initialise failed to allocate for " 197 "m_AdditionalSectionContents");
203 uintptr_t stringTableHeader =
204 (pBootstrap.getSectionHeaders() +
205 pBootstrap.getSectionHeaderStringTableIndex() *
206 pBootstrap.getSectionHeaderEntrySize());
207 KernelElfSectionHeader_t *stringTableShdr =
208 reinterpret_cast<KernelElfSectionHeader_t *
>(stringTableHeader);
211 const char *tmpStringTable =
212 m_AdditionalSectionContents.convertPhysicalPointer<
const char>(
213 stringTableShdr->addr);
215 const char *tmpStringTable =
216 reinterpret_cast<const char *
>(stringTableShdr->addr);
220 for (
size_t i = 1; i < pBootstrap.getSectionHeaderCount(); i++)
222 uintptr_t shdr_addr = pBootstrap.getSectionHeaders() +
223 i * pBootstrap.getSectionHeaderEntrySize();
226 KernelElfSectionHeader_t *pTruncatedSh =
227 m_AdditionalSectionHeaders
228 ->convertPhysicalPointer<KernelElfSectionHeader_t>(shdr_addr);
232 sh.name = pTruncatedSh->name;
233 sh.type = pTruncatedSh->type;
234 sh.flags = pTruncatedSh->flags;
235 sh.addr = pTruncatedSh->addr;
236 sh.offset = pTruncatedSh->offset;
237 sh.size = pTruncatedSh->size;
238 sh.link = pTruncatedSh->link;
239 sh.info = pTruncatedSh->info;
240 sh.addralign = pTruncatedSh->addralign;
241 sh.entsize = pTruncatedSh->entsize;
245 KernelElfSectionHeader_t *pSh = 0;
246 pSh =
reinterpret_cast<KernelElfSectionHeader_t *
>(shdr_addr);
251 if ((pSh->flags & SHF_ALLOC) != SHF_ALLOC)
254 "Converting shdr " <<
Hex << pSh->addr <<
" -> " 255 << pSh->addr + pSh->size);
256 pSh->addr =
reinterpret_cast<uintptr_t
>(
257 m_AdditionalSectionContents.convertPhysicalPointer<
void>(
260 pSh->offset = pSh->addr;
265 const char *pStr = tmpStringTable + pSh->name;
267 if (pSh->type == SHT_SYMTAB)
270 m_nSymbolTableSize = pSh->size;
272 else if (!StringCompare(pStr,
".strtab"))
274 m_pStringTable =
reinterpret_cast<char *
>(pSh->addr);
276 else if (!StringCompare(pStr,
".shstrtab"))
278 m_pShstrtab =
reinterpret_cast<char *
>(pSh->addr);
280 else if (!StringCompare(pStr,
".debug_frame"))
282 m_pDebugTable =
reinterpret_cast<uint32_t *
>(pSh->addr);
283 m_nDebugTableSize = pSh->size;
289 pBootstrap.getSectionHeaders());
290 m_nSectionHeaders = pBootstrap.getSectionHeaderCount();
293 if (m_pSymbolTable && m_pStringTable)
301 const char *pStrtab =
reinterpret_cast<const char *
>(m_pStringTable);
306 size_t numGlobal = 0;
307 for (
size_t i = 0; i < m_nSymbolTableSize /
sizeof(*pSymbol); i++)
309 switch (ST_BIND(m_pSymbolTable[i].info))
326 "KERNELELF: preallocating symbol table with " 327 << numGlobal <<
" global " << numWeak <<
" weak and " << numLocal
328 <<
" local symbols.");
329 m_SymbolTable.
preallocate(numGlobal, numWeak,
this, numLocal);
331 for (
size_t i = 1; i < m_nSymbolTableSize /
sizeof(*pSymbol); i++)
333 const char *pStr = 0;
335 if (ST_TYPE(pSymbol->info) == STT_SECTION)
339 KernelElfSectionHeader_t *pSh =
343 if (!(pSh->flags & SHF_ALLOC))
349 pStr =
reinterpret_cast<const char *
>(m_pShstrtab) + pSh->name;
353 pStr = pStrtab + pSymbol->name;
358 switch (ST_BIND(pSymbol->info))
361 binding = SymbolTable::Local;
364 binding = SymbolTable::Global;
367 binding = SymbolTable::Weak;
370 binding = SymbolTable::Global;
373 #ifndef TRACK_HIDDEN_SYMBOLS 375 if (pSymbol->other == STV_HIDDEN)
382 if (pStr && (*pStr !=
'\0'))
387 if (!StringCompareN(pStr,
"__wrap_", 7))
393 String(pStr), binding,
this, extend(pSymbol->value));
406 m_AdditionalSectionContents(
"Kernel ELF Section Data"),
407 m_AdditionalSectionHeaders(0),
420 delete m_AdditionalSectionHeaders;
426 m_pSymbolTable =
nullptr;
427 m_pStringTable =
nullptr;
428 m_pShstrtab =
nullptr;
429 m_pDebugTable =
nullptr;
450 module->elf =
new Elf();
451 module->buffer = pModule;
452 module->buflen = len;
454 if (!module->elf->
create(pModule, len))
456 FATAL(
"Module load failed (1)");
462 pModule, len, module->loadBase, module->loadSize, &m_SymbolTable))
464 FATAL(
"Module load failed (2)");
470 if (module->elf->debugFrameTableLength())
472 size_t sz = m_nDebugTableSize + module->elf->debugFrameTableLength();
473 if (sz %
sizeof(uint32_t))
474 sz +=
sizeof(uint32_t);
475 uint32_t *pDebug =
new uint32_t[sz /
sizeof(uint32_t)];
478 ERROR(
"Could not load module debug frame information.");
482 MemoryCopy(pDebug, m_pDebugTable, m_nDebugTableSize);
484 pDebug + m_nDebugTableSize,
485 reinterpret_cast<const void *>(module->elf->debugFrameTable()),
486 module->elf->debugFrameTableLength());
487 m_nDebugTableSize += module->elf->debugFrameTableLength();
488 m_pDebugTable = pDebug;
489 NOTICE(
"Added debug module debug frame information.");
494 const char **pName =
reinterpret_cast<const char **
>(
498 ERROR(
"KERNELELF: Hit an invalid module, ignoring");
501 module->name =
rebase(module, *pName);
502 module->elf->
setName(module->name);
503 auto entryPoint = *
reinterpret_cast<bool (**)()
>(
505 auto exitPoint = *
reinterpret_cast<void (**)()
>(
510 entryPoint = adjust_pointer(entryPoint, module->loadBase);
514 exitPoint = adjust_pointer(exitPoint, module->loadBase);
516 module->entry = entryPoint;
517 module->exit = exitPoint;
519 reinterpret_cast<const char **
>(module->elf->
lookupSymbol(
"g_pDepends"));
520 module->depends_opt =
reinterpret_cast<const char **
>(
523 "KERNELELF: Preloaded module " 524 << module->name <<
" at " <<
Hex << module->loadBase <<
" to " 525 << (module->loadBase + module->loadSize));
527 "KERNELELF: Module " << module->name <<
" consumes " <<
Dec 528 << (module->loadSize / 1024) <<
Hex 531 #ifdef DUMP_DEPENDENCIES 533 while (module->depends_opt &&
rebase(module, module->depends_opt[i]))
536 "KERNELELF: Module " << module->name <<
" optdepends on " 537 <<
rebase(module, module->depends_opt[i]));
542 while (module->depends &&
rebase(module, module->depends[i]))
545 "KERNELELF: Module " << module->name <<
" depends on " 546 <<
rebase(module, module->depends[i]));
551 #ifdef MEMORY_TRACING 554 reinterpret_cast<void *>(module->loadBase),
555 reinterpret_cast<void *>(module->loadBase + module->loadSize));
558 g_BootProgressCurrent++;
559 if (g_BootProgressUpdate && !silent)
560 g_BootProgressUpdate(
"moduleload");
562 module->status = Module::Preloaded;
574 bool executedModule =
true;
575 while (executedModule)
577 executedModule =
false;
581 if (module->wasAttempted())
586 bool dependenciesSatisfied = moduleDependenciesSatisfied(module);
589 if (dependenciesSatisfied)
591 executeModule(module);
593 g_BootProgressCurrent++;
594 if (g_BootProgressUpdate && !silent)
595 g_BootProgressUpdate(
"moduleexec");
597 executedModule =
true;
603 #ifdef STATIC_DRIVERS 611 module->name = info->name;
612 module->entry = info->entry;
613 module->exit = info->exit;
614 module->depends = info->dependencies;
615 DEBUG_LOG(
"KERNELELF: Preloaded module " << module->name);
617 g_BootProgressCurrent++;
618 if (g_BootProgressUpdate && !silent)
619 g_BootProgressUpdate(
"moduleload");
624 if (moduleDependenciesSatisfied(module))
626 executeModule(module);
628 g_BootProgressCurrent++;
629 if (g_BootProgressUpdate && !silent)
630 g_BootProgressUpdate(
"moduleexec");
633 bool somethingLoaded =
true;
634 while (somethingLoaded)
636 somethingLoaded =
false;
638 it != m_PendingModules.end();)
640 if (moduleDependenciesSatisfied(*it))
643 g_BootProgressCurrent++;
644 if (g_BootProgressUpdate && !silent)
645 g_BootProgressUpdate(
"moduleexec");
647 it = m_PendingModules.erase(it);
648 somethingLoaded =
true;
658 m_PendingModules.pushBack(module);
670 if (it->name == findName)
676 ERROR(
"KERNELELF: Module " << name <<
" not found");
681 NOTICE(
"KERNELELF: Unloading module " << module->name);
685 g_BootProgressCurrent--;
686 if (g_BootProgressUpdate && !silent)
687 g_BootProgressUpdate(
"moduleunload");
695 #ifndef STATIC_DRIVERS 696 uintptr_t startDtors = module->elf->
lookupSymbol(
"start_dtors");
697 uintptr_t endDtors = module->elf->
lookupSymbol(
"end_dtors");
699 if (startDtors && endDtors)
701 uintptr_t *iterator =
reinterpret_cast<uintptr_t *
>(startDtors);
702 while (iterator < reinterpret_cast<uintptr_t *>(endDtors))
704 if (static_cast<intptr_t>(*iterator) == -1)
709 else if ((*iterator) == 0)
715 uintptr_t dtor = *iterator;
716 void (*fp)(void) =
reinterpret_cast<void (*)(
void)
>(dtor);
722 m_SymbolTable.eraseByElf(module->elf);
727 g_BootProgressCurrent--;
728 if (g_BootProgressUpdate && !silent)
729 g_BootProgressUpdate(
"moduleunloaded");
732 NOTICE(
"KERNELELF: Module " << module->name <<
" unloaded.");
734 #ifndef STATIC_DRIVERS 737 (module->loadSize / pageSz) + (module->loadSize % pageSz ? 1 : 0);
741 for (
size_t i = 0; i < numPages; i++)
744 reinterpret_cast<void *
>(module->loadBase + (i * pageSz));
748 physical_uintptr_t phys = 0;
762 module->elf =
nullptr;
767 if (!module->isFailed())
769 module->status = Module::Unloaded;
775 if (g_BootProgressUpdate)
776 g_BootProgressUpdate(
"unload");
780 if (!it->isUnloaded())
797 if (module->isLoaded())
799 if (module->name == compName)
813 if (!module->isLoaded())
818 else if (module->depends == 0)
824 while (module->depends[i])
826 const char *rebased =
rebase(module, module->depends[i]);
827 if (!StringCompare(rebased, name))
829 return const_cast<char *
>(
static_cast<const char *
>(module->name));
839 bool KernelElf::moduleDependenciesSatisfied(
Module *module)
844 if (module->depends_opt)
846 while (module->depends_opt[i])
851 bool attempted =
false;
854 if (mod->name == depname)
857 attempted = mod->wasAttempted();
870 #ifdef DUMP_DEPENDENCIES 873 WARNING(
"KernelElf: optional dependency '" << depname <<
"' (wanted by '" << module->name <<
"') doesn't even exist, skipping.");
883 if (!module->depends)
888 while (module->depends[i])
894 if (mod->name == depname)
896 if (!mod->isActive())
909 static int executeModuleThread(
void *mod)
912 module->status = Module::Executing;
919 "KERNELELF: Module relocation failed for module " 925 uintptr_t startCtors = module->elf->
lookupSymbol(
"start_ctors");
926 uintptr_t endCtors = module->elf->
lookupSymbol(
"end_ctors");
928 if (startCtors && endCtors)
930 uintptr_t *iterator =
reinterpret_cast<uintptr_t *
>(startCtors);
931 while (iterator < reinterpret_cast<uintptr_t *>(endCtors))
933 if (static_cast<intptr_t>(*iterator) == -1)
938 else if ((*iterator) == 0)
944 uintptr_t ctor = *iterator;
945 void (*fp)(void) =
reinterpret_cast<void (*)(
void)
>(ctor);
952 WARNING(
"KERNELELF: Module " << module->name <<
" had no ctors!");
956 NOTICE(
"KERNELELF: Executing module " << module->name);
958 bool bSuccess =
false;
959 String moduleName(module->name);
962 bSuccess = module->entry();
970 bool KernelElf::executeModule(
Module *module)
972 #if defined(THREADS) && THREADED_MODULE_LOADING 974 Thread *pThread =
new Thread(me, executeModuleThread, module);
977 executeModuleThread(module);
985 String moduleName(module->name);
988 NOTICE(
"KERNELELF: Module " << moduleName <<
" finished executing");
989 module->status = Module::Active;
993 NOTICE(
"KERNELELF: Module " << moduleName <<
" failed, unloading.");
994 module->status = Module::Failed;
1012 NOTICE(
"SUCCESSFUL MODULES:");
1017 NOTICE(
" - " << it->name);
1021 NOTICE(
"UNSUCCESSFUL MODULES:");
1022 for (
auto it : m_Modules)
1026 NOTICE(
" - " << it->name);
1042 if ((ret =
lookupSymbol(retract(addr), startAddr, m_pSymbolTable)))
1051 if (!(it->isActive() || it->isExecuting()))
1058 if ((ret = it->elf->lookupSymbol(addr, startAddr)))
1067 "KERNELELF: GlobalLookupSymbol(" <<
Hex << addr <<
") failed.");
1073 bool hasPending =
false;
1076 if (it->isPending())
1078 NOTICE(
"Pending module: " << *it->name);
1087 m_ModuleAdjustmentLock.
acquire();
1094 m_ModuleAdjustmentLock.
release();
Bootstrap structure passed to the kernel entry point.
Elf32SectionHeader_t * m_pSectionHeaders
Vector< Module * > m_Modules
void pushBack(const T &value)
uintptr_t EXPORTED_PUBLIC lookup(const HashedStringView &name, Elf *pElf, Policy policy=LocalFirst, Binding *pBinding=0)
virtual void unmap(void *virtualAddress)=0
static KernelElf m_Instance
static size_t getPageSize() PURE
static PhysicalMemoryManager & instance()
bool initialise(const BootstrapStruct_t &pBootstrap) INITIALISATION_ONLY
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
static const size_t continuous
virtual void getMapping(void *virtualAddress, physical_uintptr_t &physicalAddress, size_t &flags)=0
virtual uintptr_t getKernelModulesEnd() const =0
A vector / dynamic array.
MemoryAllocator m_ModuleAllocator
Module * loadModule(uint8_t *pModule, size_t len, bool silent=false)
virtual bool isMapped(void *virtualAddress)=0
void waitForModulesToLoad()
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
bool acquire(bool recurse=false, bool safe=true)
void free(T address, T length, bool merge=true)
const char * lookupSymbol(uintptr_t addr, uintptr_t *startAddr, T *symbolTable)
static ProcessorInformation & information()
static KernelElf & instance()
static T * rebase(Module *module, T *ptr)
KernelElf() INITIALISATION_ONLY
static const size_t Write
bool hasPendingModules() const
static const size_t KernelMode
void insert(const String &name, Binding binding, Elf *pParent, uintptr_t value)
void updateModuleStatus(Module *module, bool status)
Special memory entity in the kernel's virtual address space.
bool finaliseModule(uint8_t *pBuffer, uintptr_t length)
uintptr_t globalLookupSymbol(const char *pName)
bool create(uint8_t *pBuffer, size_t length)
void unloadModule(const char *name, bool silent=false, bool progress=true)
Semaphore m_ModuleProgress
char * getDependingModule(char *name)
bool loadModule(uint8_t *pBuffer, size_t length, uintptr_t &loadBase, size_t &loadSize, SymbolTable *pSymbolTableCopy=0)
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1)=0
virtual void freePage(physical_uintptr_t page)=0
bool moduleIsLoaded(char *name)
virtual uintptr_t getKernelModulesStart() const =0
void executeModules(bool silent=false, bool progress=true)
void preallocate(size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
void setName(const String &s)