The Pedigree Project  0.1
KernelElf.cc
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 #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"
32 
34 
35 // Define to dump each module's dependencies in the serial log.
36 // #undef DUMP_DEPENDENCIES
37 
38 // Define to 1 to load modules using threads.
39 #define THREADED_MODULE_LOADING 0
40 
41 #define TRACK_HIDDEN_SYMBOLS 1
42 
49 #define EXTENSION_ADDEND 0xFFFFFFFF00000000ULL
50 
51 template <class T>
52 static T *extend(T *p)
53 {
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);
59 #else
60  return p;
61 #endif
62 }
63 
64 template <class T>
65 static uintptr_t extend(T p)
66 {
67 #if defined(X86_COMMON) && !defined(BITS_32)
68  // Must assign to a possibly-larger type before arithmetic.
69  uintptr_t u = p;
70  if (u < EXTENSION_ADDEND)
71  u += EXTENSION_ADDEND;
72  return u;
73 #else
74  return p;
75 #endif
76 }
77 
78 template <class T>
79 static T *retract(T *p)
80 {
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);
86 #else
87  return p;
88 #endif
89 }
90 
91 template <class T>
92 static uintptr_t retract(T p)
93 {
94 #if defined(X86_COMMON) && !defined(BITS_32)
95  // Must assign to a possibly-larger type before arithmetic.
96  uintptr_t u = p;
97  if (u >= EXTENSION_ADDEND)
98  u -= EXTENSION_ADDEND;
99  return u;
100 #else
101  return p;
102 #endif
103 }
104 
106 {
107  // Do we even have section headers to peek at?
108  if (pBootstrap.getSectionHeaderCount() == 0)
109  {
110  WARNING("No ELF object available to extract symbol table from.");
111 #ifdef STATIC_DRIVERS
112  // Don't need the ELF object to load modules.
113  return true;
114 #else
115  // Need the ELF object to load modules.
116  return false;
117 #endif
118  }
119 
120 #ifdef X86_COMMON
121  PhysicalMemoryManager &physicalMemoryManager =
123  size_t pageSz = PhysicalMemoryManager::getPageSize();
124 
125  m_AdditionalSectionHeaders = new MemoryRegion("Kernel ELF Section Headers");
126 
127  // Map in section headers.
128  size_t sectionHeadersLength = pBootstrap.getSectionHeaderCount() *
129  pBootstrap.getSectionHeaderEntrySize();
130  if ((sectionHeadersLength % pageSz) > 0)
131  {
132  sectionHeadersLength += pageSz;
133  }
134  if (physicalMemoryManager.allocateRegion(
135  *m_AdditionalSectionHeaders, sectionHeadersLength / pageSz,
138  pBootstrap.getSectionHeaders()) == false)
139  {
140  ERROR("KernelElf::initialise failed to allocate for "
141  "m_AdditionalSectionHeaders");
142  return false;
143  }
144 
145  // Determine the layout of the contents of non-code sections.
146  physical_uintptr_t start = ~0;
147  physical_uintptr_t end = 0;
148  for (size_t i = 1; i < pBootstrap.getSectionHeaderCount(); i++)
149  {
150  // Force 32-bit section header type as we are a 32-bit ELF object
151  // even on 64-bit targets.
152  uintptr_t shdr_addr = pBootstrap.getSectionHeaders() +
153  i * pBootstrap.getSectionHeaderEntrySize();
154  Elf32SectionHeader_t *pSh =
155  m_AdditionalSectionHeaders
156  ->convertPhysicalPointer<Elf32SectionHeader_t>(shdr_addr);
157 
158  if ((pSh->flags & SHF_ALLOC) != SHF_ALLOC)
159  {
160  if (pSh->addr <= start)
161  {
162  start = pSh->addr;
163  }
164 
165  if ((pSh->addr + pSh->size) >= end)
166  {
167  end = pSh->addr + pSh->size;
168  }
169  }
170  }
171 
172  // Is there an overlap between headers and section data?
173  if ((start & ~(pageSz - 1)) ==
174  (pBootstrap.getSectionHeaders() & ~(pageSz - 1)))
175  {
176  // Yes, there is. Point the section headers MemoryRegion to the
177  // Contents.
178  delete m_AdditionalSectionHeaders;
179  m_AdditionalSectionHeaders = &m_AdditionalSectionContents;
180  }
181 
182  // Map in all non-alloc sections.
183  uintptr_t alignedStart = start & ~(pageSz - 1);
184  uintptr_t allocSize = end - alignedStart;
185  if ((allocSize % pageSz) > 0)
186  {
187  allocSize += pageSz;
188  }
189  size_t additionalContentsPages = allocSize / pageSz;
190  if (physicalMemoryManager.allocateRegion(
191  m_AdditionalSectionContents, additionalContentsPages,
194  start) == false)
195  {
196  ERROR("KernelElf::initialise failed to allocate for "
197  "m_AdditionalSectionContents");
198  return false;
199  }
200 #endif
201 
202  // Get the string table
203  uintptr_t stringTableHeader =
204  (pBootstrap.getSectionHeaders() +
205  pBootstrap.getSectionHeaderStringTableIndex() *
206  pBootstrap.getSectionHeaderEntrySize());
207  KernelElfSectionHeader_t *stringTableShdr =
208  reinterpret_cast<KernelElfSectionHeader_t *>(stringTableHeader);
209 
210 #ifdef X86_COMMON
211  const char *tmpStringTable =
212  m_AdditionalSectionContents.convertPhysicalPointer<const char>(
213  stringTableShdr->addr);
214 #else
215  const char *tmpStringTable =
216  reinterpret_cast<const char *>(stringTableShdr->addr);
217 #endif
218 
219  // Search for the symbol/string table and adjust sections
220  for (size_t i = 1; i < pBootstrap.getSectionHeaderCount(); i++)
221  {
222  uintptr_t shdr_addr = pBootstrap.getSectionHeaders() +
223  i * pBootstrap.getSectionHeaderEntrySize();
224 
225 #ifdef X86_COMMON
226  KernelElfSectionHeader_t *pTruncatedSh =
227  m_AdditionalSectionHeaders
228  ->convertPhysicalPointer<KernelElfSectionHeader_t>(shdr_addr);
229 
230  // Copy into larger format for analysis
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;
242 
243  ElfSectionHeader_t *pSh = &sh;
244 #else
245  KernelElfSectionHeader_t *pSh = 0;
246  pSh = reinterpret_cast<KernelElfSectionHeader_t *>(shdr_addr);
247 #endif
248 
249 #ifdef X86_COMMON
250  // Adjust the section
251  if ((pSh->flags & SHF_ALLOC) != SHF_ALLOC)
252  {
253  NOTICE(
254  "Converting shdr " << Hex << pSh->addr << " -> "
255  << pSh->addr + pSh->size);
256  pSh->addr = reinterpret_cast<uintptr_t>(
257  m_AdditionalSectionContents.convertPhysicalPointer<void>(
258  pSh->addr));
259  NOTICE(" to " << Hex << pSh->addr);
260  pSh->offset = pSh->addr;
261  }
262 #endif
263 
264  // Save the symbol/string table
265  const char *pStr = tmpStringTable + pSh->name;
266 
267  if (pSh->type == SHT_SYMTAB)
268  {
269  m_pSymbolTable = reinterpret_cast<KernelElfSymbol_t *>(pSh->addr);
270  m_nSymbolTableSize = pSh->size;
271  }
272  else if (!StringCompare(pStr, ".strtab"))
273  {
274  m_pStringTable = reinterpret_cast<char *>(pSh->addr);
275  }
276  else if (!StringCompare(pStr, ".shstrtab"))
277  {
278  m_pShstrtab = reinterpret_cast<char *>(pSh->addr);
279  }
280  else if (!StringCompare(pStr, ".debug_frame"))
281  {
282  m_pDebugTable = reinterpret_cast<uint32_t *>(pSh->addr);
283  m_nDebugTableSize = pSh->size;
284  }
285  }
286 
287  // Initialise remaining member variables
288  m_pSectionHeaders = reinterpret_cast<KernelElfSectionHeader_t *>(
289  pBootstrap.getSectionHeaders());
290  m_nSectionHeaders = pBootstrap.getSectionHeaderCount();
291 
292 #ifdef DEBUGGER
293  if (m_pSymbolTable && m_pStringTable)
294  {
295 #ifdef X86_COMMON
296  KernelElfSymbol_t *pSymbol = m_pSymbolTable;
297 #else
298  KernelElfSymbol_t *pSymbol = m_pSymbolTable;
299 #endif
300 
301  const char *pStrtab = reinterpret_cast<const char *>(m_pStringTable);
302 
303  // quick pass to preallocate for the symbol table
304  size_t numLocal = 0;
305  size_t numWeak = 0;
306  size_t numGlobal = 0;
307  for (size_t i = 0; i < m_nSymbolTableSize / sizeof(*pSymbol); i++)
308  {
309  switch (ST_BIND(m_pSymbolTable[i].info))
310  {
311  case STB_LOCAL:
312  ++numLocal;
313  break;
314  case STB_GLOBAL:
315  ++numGlobal;
316  break;
317  case STB_WEAK:
318  ++numWeak;
319  break;
320  default:
321  ++numGlobal;
322  }
323  }
324 
325  NOTICE(
326  "KERNELELF: preallocating symbol table with "
327  << numGlobal << " global " << numWeak << " weak and " << numLocal
328  << " local symbols.");
329  m_SymbolTable.preallocate(numGlobal, numWeak, this, numLocal);
330 
331  for (size_t i = 1; i < m_nSymbolTableSize / sizeof(*pSymbol); i++)
332  {
333  const char *pStr = 0;
334 
335  if (ST_TYPE(pSymbol->info) == STT_SECTION)
336  {
337  // Section type - the name will be the name of the section
338  // header it refers to.
339  KernelElfSectionHeader_t *pSh =
340  &m_pSectionHeaders[pSymbol->shndx];
341  // If it's not allocated, it's a link-once-only section that we
342  // can ignore.
343  if (!(pSh->flags & SHF_ALLOC))
344  {
345  pSymbol++;
346  continue;
347  }
348  // Grab the shstrtab
349  pStr = reinterpret_cast<const char *>(m_pShstrtab) + pSh->name;
350  }
351  else
352  {
353  pStr = pStrtab + pSymbol->name;
354  }
355 
356  // Insert the symbol into the symbol table.
357  SymbolTable::Binding binding;
358  switch (ST_BIND(pSymbol->info))
359  {
360  case STB_LOCAL:
361  binding = SymbolTable::Local;
362  break;
363  case STB_GLOBAL:
364  binding = SymbolTable::Global;
365  break;
366  case STB_WEAK:
367  binding = SymbolTable::Weak;
368  break;
369  default:
370  binding = SymbolTable::Global;
371  }
372 
373 #ifndef TRACK_HIDDEN_SYMBOLS
374  // Don't insert hidden symbols to the main symbol table.
375  if (pSymbol->other == STV_HIDDEN)
376  {
377  ++pSymbol;
378  continue;
379  }
380 #endif
381 
382  if (pStr && (*pStr != '\0'))
383  {
384 #ifdef HOSTED
385  // If name starts with __wrap_, rewrite it in flight as it's
386  // a wrapped symbol on hosted systems.
387  if (!StringCompareN(pStr, "__wrap_", 7))
388  {
389  pStr += 7;
390  }
391 #endif
392  m_SymbolTable.insert(
393  String(pStr), binding, this, extend(pSymbol->value));
394  }
395  pSymbol++;
396  }
397  }
398 #endif
399 
400  return true;
401 }
402 
404  :
405 #ifdef X86_COMMON
406  m_AdditionalSectionContents("Kernel ELF Section Data"),
407  m_AdditionalSectionHeaders(0),
408 #endif
409  m_Modules(), m_ModuleAllocator(), m_pSectionHeaders(0), m_pSymbolTable(0)
410 #ifdef THREADS
411  ,
412  m_ModuleProgress(0), m_ModuleAdjustmentLock(false)
413 #endif
414 {
415 }
416 
418 {
419 #ifdef X86_COMMON
420  delete m_AdditionalSectionHeaders;
421 #endif
422 
423  // All of these non-alloc sections are just pointers into the loaded kernel
424  // ELF, which is not heap allocated. In normal Elf objects these are
425  // allocated and then copied into. Not so here.
426  m_pSymbolTable = nullptr;
427  m_pStringTable = nullptr;
428  m_pShstrtab = nullptr;
429  m_pDebugTable = nullptr;
430 }
431 
432 Module *KernelElf::loadModule(uint8_t *pModule, size_t len, bool silent)
433 {
434  MemoryCount guard(__PRETTY_FUNCTION__);
435 
436  // The module memory allocator requires dynamic memory - this isn't
437  // initialised until after our constructor is called, so check here if we've
438  // loaded any modules yet. If not, we can initialise our memory allocator.
439  if (m_Modules.count() == 0)
440  {
443  uintptr_t end =
445  m_ModuleAllocator.free(start, end - start);
446  }
447 
448  Module *module = new Module;
449 
450  module->elf = new Elf();
451  module->buffer = pModule;
452  module->buflen = len;
453 
454  if (!module->elf->create(pModule, len))
455  {
456  FATAL("Module load failed (1)");
457  delete module;
458  return 0;
459  }
460 
461  if (!module->elf->loadModule(
462  pModule, len, module->loadBase, module->loadSize, &m_SymbolTable))
463  {
464  FATAL("Module load failed (2)");
465  delete module;
466  return 0;
467  }
468 
469  // Load the module debug table (if any)
470  if (module->elf->debugFrameTableLength())
471  {
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)];
476  if (UNLIKELY(!pDebug))
477  {
478  ERROR("Could not load module debug frame information.");
479  }
480  else
481  {
482  MemoryCopy(pDebug, m_pDebugTable, m_nDebugTableSize);
483  MemoryCopy(
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.");
490  }
491  }
492 
493  // Look up the module's name and entry/exit functions, and dependency list.
494  const char **pName = reinterpret_cast<const char **>(
495  module->elf->lookupSymbol("g_pModuleName"));
496  if (!pName)
497  {
498  ERROR("KERNELELF: Hit an invalid module, ignoring");
499  return 0;
500  }
501  module->name = rebase(module, *pName);
502  module->elf->setName(module->name);
503  auto entryPoint = *reinterpret_cast<bool (**)()>(
504  module->elf->lookupSymbol("g_pModuleEntry"));
505  auto exitPoint = *reinterpret_cast<void (**)()>(
506  module->elf->lookupSymbol("g_pModuleExit"));
507  // Readjust entry/exit functions for the loaded module if needed
508  if (entryPoint)
509  {
510  entryPoint = adjust_pointer(entryPoint, module->loadBase);
511  }
512  if (exitPoint)
513  {
514  exitPoint = adjust_pointer(exitPoint, module->loadBase);
515  }
516  module->entry = entryPoint;
517  module->exit = exitPoint;
518  module->depends =
519  reinterpret_cast<const char **>(module->elf->lookupSymbol("g_pDepends"));
520  module->depends_opt = reinterpret_cast<const char **>(
521  module->elf->lookupSymbol("g_pOptionalDepends"));
522  DEBUG_LOG(
523  "KERNELELF: Preloaded module "
524  << module->name << " at " << Hex << module->loadBase << " to "
525  << (module->loadBase + module->loadSize));
526  DEBUG_LOG(
527  "KERNELELF: Module " << module->name << " consumes " << Dec
528  << (module->loadSize / 1024) << Hex
529  << "K of memory");
530 
531 #ifdef DUMP_DEPENDENCIES
532  size_t i = 0;
533  while (module->depends_opt && rebase(module, module->depends_opt[i]))
534  {
535  DEBUG_LOG(
536  "KERNELELF: Module " << module->name << " optdepends on "
537  << rebase(module, module->depends_opt[i]));
538  ++i;
539  }
540 
541  i = 0;
542  while (module->depends && rebase(module, module->depends[i]))
543  {
544  DEBUG_LOG(
545  "KERNELELF: Module " << module->name << " depends on "
546  << rebase(module, module->depends[i]));
547  ++i;
548  }
549 #endif
550 
551 #ifdef MEMORY_TRACING
552  traceMetadata(
553  NormalStaticString(module->name),
554  reinterpret_cast<void *>(module->loadBase),
555  reinterpret_cast<void *>(module->loadBase + module->loadSize));
556 #endif
557 
558  g_BootProgressCurrent++;
559  if (g_BootProgressUpdate && !silent)
560  g_BootProgressUpdate("moduleload");
561 
562  module->status = Module::Preloaded;
563 
564  m_Modules.pushBack(module);
565 
566  return module;
567 }
568 
569 void KernelElf::executeModules(bool silent, bool progress)
570 {
571  NOTICE("KERNELELF: executing " << m_Modules.count() << " modules...");
572 
573  // keep trying until all modules were invoked
574  bool executedModule = true;
575  while (executedModule)
576  {
577  executedModule = false;
578 
579  for (auto module : m_Modules)
580  {
581  if (module->wasAttempted())
582  {
583  continue;
584  }
585 
586  bool dependenciesSatisfied = moduleDependenciesSatisfied(module);
587 
588  // Can we load this module yet?
589  if (dependenciesSatisfied)
590  {
591  executeModule(module);
592 
593  g_BootProgressCurrent++;
594  if (g_BootProgressUpdate && !silent)
595  g_BootProgressUpdate("moduleexec");
596 
597  executedModule = true;
598  }
599  }
600  }
601 }
602 
603 #ifdef STATIC_DRIVERS
604 Module *KernelElf::loadModule(struct ModuleInfo *info, bool silent)
605 {
606  Module *module = new Module;
607 
608  module->buffer = 0;
609  module->buflen = 0;
610 
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);
616 
617  g_BootProgressCurrent++;
618  if (g_BootProgressUpdate && !silent)
619  g_BootProgressUpdate("moduleload");
620 
621  m_Modules.pushBack(module);
622 
623  // Can we load this module yet?
624  if (moduleDependenciesSatisfied(module))
625  {
626  executeModule(module);
627 
628  g_BootProgressCurrent++;
629  if (g_BootProgressUpdate && !silent)
630  g_BootProgressUpdate("moduleexec");
631 
632  // Now check if we've allowed any currently pending modules to load.
633  bool somethingLoaded = true;
634  while (somethingLoaded)
635  {
636  somethingLoaded = false;
637  for (Vector<Module *>::Iterator it = m_PendingModules.begin();
638  it != m_PendingModules.end();)
639  {
640  if (moduleDependenciesSatisfied(*it))
641  {
642  executeModule(*it);
643  g_BootProgressCurrent++;
644  if (g_BootProgressUpdate && !silent)
645  g_BootProgressUpdate("moduleexec");
646 
647  it = m_PendingModules.erase(it);
648  somethingLoaded = true;
649  break;
650  }
651  else
652  ++it;
653  }
654  }
655  }
656  else
657  {
658  m_PendingModules.pushBack(module);
659  }
660 
661  return module;
662 }
663 #endif
664 
665 void KernelElf::unloadModule(const char *name, bool silent, bool progress)
666 {
667  String findName(name);
668  for (auto it : m_Modules)
669  {
670  if (it->name == findName)
671  {
672  unloadModule(it, silent, progress);
673  return;
674  }
675  }
676  ERROR("KERNELELF: Module " << name << " not found");
677 }
678 
679 void KernelElf::unloadModule(Module *module, bool silent, bool progress)
680 {
681  NOTICE("KERNELELF: Unloading module " << module->name);
682 
683  if (progress)
684  {
685  g_BootProgressCurrent--;
686  if (g_BootProgressUpdate && !silent)
687  g_BootProgressUpdate("moduleunload");
688  }
689 
690  if (module->exit)
691  module->exit();
692 
693 // Check for a destructors list and execute.
694 // Note: static drivers have their ctors/dtors all shared.
695 #ifndef STATIC_DRIVERS
696  uintptr_t startDtors = module->elf->lookupSymbol("start_dtors");
697  uintptr_t endDtors = module->elf->lookupSymbol("end_dtors");
698 
699  if (startDtors && endDtors)
700  {
701  uintptr_t *iterator = reinterpret_cast<uintptr_t *>(startDtors);
702  while (iterator < reinterpret_cast<uintptr_t *>(endDtors))
703  {
704  if (static_cast<intptr_t>(*iterator) == -1)
705  {
706  ++iterator;
707  continue;
708  }
709  else if ((*iterator) == 0)
710  {
711  // End of table.
712  break;
713  }
714 
715  uintptr_t dtor = *iterator;
716  void (*fp)(void) = reinterpret_cast<void (*)(void)>(dtor);
717  fp();
718  iterator++;
719  }
720  }
721 
722  m_SymbolTable.eraseByElf(module->elf);
723 #endif
724 
725  if (progress)
726  {
727  g_BootProgressCurrent--;
728  if (g_BootProgressUpdate && !silent)
729  g_BootProgressUpdate("moduleunloaded");
730  }
731 
732  NOTICE("KERNELELF: Module " << module->name << " unloaded.");
733 
734 #ifndef STATIC_DRIVERS
735  size_t pageSz = PhysicalMemoryManager::getPageSize();
736  size_t numPages =
737  (module->loadSize / pageSz) + (module->loadSize % pageSz ? 1 : 0);
738 
739  // Unmap!
740  VirtualAddressSpace &va = Processor::information().getVirtualAddressSpace();
741  for (size_t i = 0; i < numPages; i++)
742  {
743  void *unmapAddr =
744  reinterpret_cast<void *>(module->loadBase + (i * pageSz));
745  if (va.isMapped(unmapAddr))
746  {
747  // Unmap the virtual address
748  physical_uintptr_t phys = 0;
749  size_t flags = 0;
750  va.getMapping(unmapAddr, phys, flags);
751  va.unmap(unmapAddr);
752 
753  // Free the physical page
755  }
756  }
757 
758  m_ModuleAllocator.free(module->loadBase, module->loadSize);
759 #endif
760 
761  delete module->elf;
762  module->elf = nullptr;
763 
764  // Failed also means unloaded - it just reports a particular status.
765  // A module unloaded intentionally (i.e. by the user) that was successfully
766  // active and running goes into Unloaded mode on unload.
767  if (!module->isFailed())
768  {
769  module->status = Module::Unloaded;
770  }
771 }
772 
774 {
775  if (g_BootProgressUpdate)
776  g_BootProgressUpdate("unload");
777 
778  for (auto it : m_Modules)
779  {
780  if (!it->isUnloaded())
781  {
782  unloadModule(it);
783  delete it;
784  }
785  }
786 
787  m_Modules.clear();
788 }
789 
791 {
792  // this should hash the name and make comparisons super fast
793  String compName(name);
794 
795  for (auto module : m_Modules)
796  {
797  if (module->isLoaded())
798  {
799  if (module->name == compName)
800  {
801  return true;
802  }
803  }
804  }
805 
806  return false;
807 }
808 
810 {
811  for (auto module : m_Modules)
812  {
813  if (!module->isLoaded())
814  {
815  // can't depend on unloaded modules - might be unmapped
816  continue;
817  }
818  else if (module->depends == 0)
819  {
820  continue;
821  }
822 
823  size_t i = 0;
824  while (module->depends[i])
825  {
826  const char *rebased = rebase(module, module->depends[i]);
827  if (!StringCompare(rebased, name))
828  {
829  return const_cast<char *>(static_cast<const char *>(module->name));
830  }
831 
832  ++i;
833  }
834  }
835 
836  return 0;
837 }
838 
839 bool KernelElf::moduleDependenciesSatisfied(Module *module)
840 {
841  int i = 0;
842 
843  // First pass: optional dependencies.
844  if (module->depends_opt)
845  {
846  while (module->depends_opt[i])
847  {
848  String depname(rebase(module, module->depends_opt[i]));
849 
850  bool exists = false;
851  bool attempted = false;
852  for (auto mod : m_Modules)
853  {
854  if (mod->name == depname)
855  {
856  exists = true;
857  attempted = mod->wasAttempted();
858  break;
859  }
860  }
861 
862  if (exists)
863  {
864  if (!attempted)
865  {
866  // optional dependency hasn't yet been tried
867  return false;
868  }
869  }
870 #ifdef DUMP_DEPENDENCIES
871  else
872  {
873  WARNING("KernelElf: optional dependency '" << depname << "' (wanted by '" << module->name << "') doesn't even exist, skipping.");
874  }
875 #endif
876 
877  ++i;
878  }
879  }
880 
881  // Second pass: mandatory dependencies.
882  i = 0;
883  if (!module->depends)
884  {
885  return true;
886  }
887 
888  while (module->depends[i])
889  {
890  String depname(rebase(module, module->depends[i]));
891 
892  for (auto mod : m_Modules)
893  {
894  if (mod->name == depname)
895  {
896  if (!mod->isActive())
897  {
898  // module dependency is not yet active
899  return false;
900  }
901  }
902  }
903 
904  ++i;
905  }
906  return true;
907 }
908 
909 static int executeModuleThread(void *mod)
910 {
911  Module *module = reinterpret_cast<Module *>(mod);
912  module->status = Module::Executing;
913 
914  if (module->buffer)
915  {
916  if (!module->elf->finaliseModule(module->buffer, module->buflen))
917  {
918  FATAL(
919  "KERNELELF: Module relocation failed for module "
920  << module->name);
921  return false;
922  }
923 
924  // Check for a constructors list and execute.
925  uintptr_t startCtors = module->elf->lookupSymbol("start_ctors");
926  uintptr_t endCtors = module->elf->lookupSymbol("end_ctors");
927 
928  if (startCtors && endCtors)
929  {
930  uintptr_t *iterator = reinterpret_cast<uintptr_t *>(startCtors);
931  while (iterator < reinterpret_cast<uintptr_t *>(endCtors))
932  {
933  if (static_cast<intptr_t>(*iterator) == -1)
934  {
935  ++iterator;
936  continue;
937  }
938  else if ((*iterator) == 0)
939  {
940  // End of table.
941  break;
942  }
943 
944  uintptr_t ctor = *iterator;
945  void (*fp)(void) = reinterpret_cast<void (*)(void)>(ctor);
946  fp();
947  iterator++;
948  }
949  }
950  else
951  {
952  WARNING("KERNELELF: Module " << module->name << " had no ctors!");
953  }
954  }
955 
956  NOTICE("KERNELELF: Executing module " << module->name);
957 
958  bool bSuccess = false;
959  String moduleName(module->name);
960  if (module->entry)
961  {
962  bSuccess = module->entry();
963  }
964 
965  KernelElf::instance().updateModuleStatus(module, bSuccess);
966 
967  return 0;
968 }
969 
970 bool KernelElf::executeModule(Module *module)
971 {
972 #if defined(THREADS) && THREADED_MODULE_LOADING
973  Process *me = Processor::information().getCurrentThread()->getParent();
974  Thread *pThread = new Thread(me, executeModuleThread, module);
975  pThread->detach();
976 #else
977  executeModuleThread(module);
978 #endif
979 
980  return true;
981 }
982 
983 void KernelElf::updateModuleStatus(Module *module, bool status)
984 {
985  String moduleName(module->name);
986  if (status)
987  {
988  NOTICE("KERNELELF: Module " << moduleName << " finished executing");
989  module->status = Module::Active;
990  }
991  else
992  {
993  NOTICE("KERNELELF: Module " << moduleName << " failed, unloading.");
994  module->status = Module::Failed;
995  unloadModule(moduleName, true, false);
996  }
997 
998 #ifdef THREADS
1000 #endif
1001 }
1002 
1004 {
1005 #ifdef THREADS
1006  for (size_t i = 0; i < m_Modules.count(); ++i)
1007  {
1009  }
1010 #endif
1011 
1012  NOTICE("SUCCESSFUL MODULES:");
1013  for (auto it : m_Modules)
1014  {
1015  if (it->isActive())
1016  {
1017  NOTICE(" - " << it->name);
1018  }
1019  }
1020 
1021  NOTICE("UNSUCCESSFUL MODULES:");
1022  for (auto it : m_Modules)
1023  {
1024  if (it->isFailed())
1025  {
1026  NOTICE(" - " << it->name);
1027  }
1028  }
1029 }
1030 
1031 uintptr_t KernelElf::globalLookupSymbol(const char *pName)
1032 {
1033  return m_SymbolTable.lookup(String(pName), this);
1034 }
1035 
1036 const char *KernelElf::globalLookupSymbol(uintptr_t addr, uintptr_t *startAddr)
1037 {
1039 
1040  // Try a lookup in the kernel.
1041  const char *ret;
1042  if ((ret = lookupSymbol(retract(addr), startAddr, m_pSymbolTable)))
1043  {
1044  return ret;
1045  }
1046 
1047  // OK, that didn't work. Try every module.
1048  lockModules();
1049  for (auto it : m_Modules)
1050  {
1051  if (!(it->isActive() || it->isExecuting()))
1052  {
1053  continue;
1054  }
1055 
1056  unlockModules();
1057 
1058  if ((ret = it->elf->lookupSymbol(addr, startAddr)))
1059  {
1060  return ret;
1061  }
1062 
1063  lockModules();
1064  }
1065  unlockModules();
1066  WARNING_NOLOCK(
1067  "KERNELELF: GlobalLookupSymbol(" << Hex << addr << ") failed.");
1068  return 0;
1069 }
1070 
1072 {
1073  bool hasPending = false;
1074  for (auto it : m_Modules)
1075  {
1076  if (it->isPending())
1077  {
1078  NOTICE("Pending module: " << *it->name);
1079  }
1080  }
1081  return hasPending;
1082 }
1083 
1085 {
1086 #ifdef THREADS
1087  m_ModuleAdjustmentLock.acquire();
1088 #endif
1089 }
1090 
1092 {
1093 #ifdef THREADS
1094  m_ModuleAdjustmentLock.release();
1095 #endif
1096 }
Bootstrap structure passed to the kernel entry point.
Elf32SectionHeader_t * m_pSectionHeaders
Definition: KernelElf.h:231
void release()
Definition: Spinlock.cc:273
Vector< Module * > m_Modules
Definition: KernelElf.h:225
void pushBack(const T &value)
Definition: Vector.h:270
uintptr_t EXPORTED_PUBLIC lookup(const HashedStringView &name, Elf *pElf, Policy policy=LocalFirst, Binding *pBinding=0)
Definition: SymbolTable.cc:126
virtual void unmap(void *virtualAddress)=0
Iterator begin()
Definition: Vector.h:148
static KernelElf m_Instance
Definition: KernelElf.h:222
size_t count() const
Definition: Vector.h:264
static PhysicalMemoryManager & instance()
bool initialise(const BootstrapStruct_t &pBootstrap) INITIALISATION_ONLY
Definition: KernelElf.cc:105
bool acquire(size_t n=1, size_t timeoutSecs=0, size_t timeoutUsecs=0)
Definition: Semaphore.h:62
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
Definition: KernelElf.h:227
Elf()
Definition: linker/Elf.cc:75
Module * loadModule(uint8_t *pModule, size_t len, bool silent=false)
Definition: KernelElf.cc:432
virtual bool isMapped(void *virtualAddress)=0
void waitForModulesToLoad()
Definition: KernelElf.cc:1003
static EXPORTED_PUBLIC VirtualAddressSpace & getKernelAddressSpace()
bool acquire(bool recurse=false, bool safe=true)
Definition: Spinlock.cc:43
void unloadModules()
Definition: KernelElf.cc:773
Definition: String.h:49
void free(T address, T length, bool merge=true)
Definition: RangeList.h:163
const char * lookupSymbol(uintptr_t addr, uintptr_t *startAddr, T *symbolTable)
Definition: linker/Elf.cc:1164
static ProcessorInformation & information()
Definition: Processor.cc:45
void unlockModules()
Definition: KernelElf.cc:1091
static KernelElf & instance()
Definition: KernelElf.h:129
static T * rebase(Module *module, T *ptr)
Definition: KernelElf.h:205
KernelElf() INITIALISATION_ONLY
Definition: KernelElf.cc:403
#define WARNING(text)
Definition: Log.h:78
bool hasPendingModules() const
Definition: KernelElf.cc:1071
void insert(const String &name, Binding binding, Elf *pParent, uintptr_t value)
Definition: SymbolTable.cc:51
void release(size_t n=1)
Definition: Semaphore.cc:239
#define NOTICE(text)
Definition: Log.h:74
void updateModuleStatus(Module *module, bool status)
Definition: KernelElf.cc:983
Special memory entity in the kernel&#39;s virtual address space.
Definition: MemoryRegion.h:35
Definition: Log.h:136
bool finaliseModule(uint8_t *pBuffer, uintptr_t length)
Definition: linker/Elf.cc:792
uintptr_t globalLookupSymbol(const char *pName)
Definition: KernelElf.cc:1031
bool create(uint8_t *pBuffer, size_t length)
Definition: linker/Elf.cc:313
void lockModules()
Definition: KernelElf.cc:1084
void unloadModule(const char *name, bool silent=false, bool progress=true)
Definition: KernelElf.cc:665
Semaphore m_ModuleProgress
Definition: KernelElf.h:246
Definition: Thread.h:54
char * getDependingModule(char *name)
Definition: KernelElf.cc:809
bool loadModule(uint8_t *pBuffer, size_t length, uintptr_t &loadBase, size_t &loadSize, SymbolTable *pSymbolTableCopy=0)
Definition: linker/Elf.cc:552
virtual bool allocateRegion(MemoryRegion &Region, size_t cPages, size_t pageConstraints, size_t Flags, physical_uintptr_t start=-1)=0
#define ERROR(text)
Definition: Log.h:82
virtual void freePage(physical_uintptr_t page)=0
bool detach()
Definition: Thread.cc:885
Definition: Log.h:138
bool moduleIsLoaded(char *name)
Definition: KernelElf.cc:790
#define FATAL(text)
Definition: Log.h:89
virtual uintptr_t getKernelModulesStart() const =0
#define DEBUG_LOG(text)
Definition: Log.h:69
void executeModules(bool silent=false, bool progress=true)
Definition: KernelElf.cc:569
void preallocate(size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
Definition: SymbolTable.cc:73
void setName(const String &s)
Definition: Elf.h:352
virtual ~KernelElf()
Definition: KernelElf.cc:417