The Pedigree Project  0.1
linker/Elf.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/Elf.h"
21 #include "pedigree/kernel/Log.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"
33 
34 #define TRACK_HIDDEN_SYMBOLS 1
35 
36 static void resolveNeeded()
37 {
38  FATAL("ELF: resolveNeeded() called but binary should have been fully "
39  "relocated.");
40 }
41 
44 template <typename T>
45 static T *copy(T *buff, size_t numBytes)
46 {
47  T *ret = new T[numBytes / sizeof(T)];
48  MemoryCopy(ret, buff, numBytes);
49  return ret;
50 }
51 
54 template <typename T>
56  uint8_t *pBuffer, Elf::ElfProgramHeader_t *pProgramHeaders,
57  size_t nProgramHeaders, T *pCurrent, size_t size)
58 {
59  for (size_t i = 0; i < nProgramHeaders; i++)
60  {
61  Elf::ElfProgramHeader_t ph = pProgramHeaders[i];
62  if ((ph.vaddr <= reinterpret_cast<uintptr_t>(pCurrent)) &&
63  (reinterpret_cast<uintptr_t>(pCurrent) < ph.vaddr + ph.filesz))
64  {
65  uintptr_t loc = reinterpret_cast<uintptr_t>(pCurrent) - ph.vaddr;
66  pCurrent = new T[size / sizeof(T)];
67  MemoryCopy(
68  reinterpret_cast<uint8_t *>(pCurrent), &pBuffer[loc], size);
69  return pCurrent;
70  }
71  }
72  return 0;
73 }
74 
76  : m_pSymbolTable(0), m_nSymbolTableSize(0), m_pStringTable(0),
77  m_nStringTableSize(0), m_pShstrtab(0), m_nShstrtabSize(0), m_pGotTable(0),
78  m_pRelTable(0), m_pRelaTable(0), m_nRelTableSize(0), m_nRelaTableSize(0),
79  m_pPltRelTable(0), m_pPltRelaTable(0), m_bUsesRela(false),
80  m_pDebugTable(0), m_nDebugTableSize(0), m_pDynamicSymbolTable(0),
81  m_nDynamicSymbolTableSize(0), m_pDynamicStringTable(0),
82  m_nDynamicStringTableSize(0), m_pSectionHeaders(0), m_nSectionHeaders(0),
83  m_pProgramHeaders(0), m_nProgramHeaders(0), m_nPltSize(0), m_nEntry(0),
84  m_NeededLibraries(), m_SymbolTable(this), m_InitFunc(0), m_FiniFunc(0)
85 {
86 }
87 
89 {
90  delete[] m_pSymbolTable;
91  delete[] m_pStringTable;
92  delete[] m_pShstrtab;
93  // delete m_pGotTable;
94  delete[] m_pRelTable;
95  delete[] m_pRelaTable;
96  delete[] m_pPltRelTable;
97  delete[] m_pPltRelaTable;
98  delete[] m_pDebugTable;
99  delete[] m_pDynamicSymbolTable;
100  delete[] m_pDynamicStringTable;
101  delete[] m_pSectionHeaders;
102  delete[] m_pProgramHeaders;
103 }
104 
105 Elf::Elf(const Elf &elf)
106  : m_pSymbolTable(0), m_nSymbolTableSize(elf.m_nSymbolTableSize),
107  m_pStringTable(), m_nStringTableSize(elf.m_nStringTableSize),
108  m_pShstrtab(0), m_nShstrtabSize(elf.m_nShstrtabSize),
109  m_pGotTable(elf.m_pGotTable), m_pRelTable(0), m_pRelaTable(0),
110  m_nRelTableSize(elf.m_nRelTableSize),
111  m_nRelaTableSize(elf.m_nRelaTableSize), m_pPltRelTable(0),
112  m_pPltRelaTable(0), m_bUsesRela(elf.m_bUsesRela), m_pDebugTable(0),
113  m_nDebugTableSize(elf.m_nDebugTableSize), m_pDynamicSymbolTable(0),
114  m_nDynamicSymbolTableSize(elf.m_nDynamicSymbolTableSize),
115  m_pDynamicStringTable(0),
116  m_nDynamicStringTableSize(elf.m_nDynamicStringTableSize),
117  m_pSectionHeaders(0), m_nSectionHeaders(elf.m_nSectionHeaders),
118  m_pProgramHeaders(0), m_nProgramHeaders(elf.m_nProgramHeaders),
119  m_nPltSize(elf.m_nPltSize), m_nEntry(elf.m_nEntry),
120  m_NeededLibraries(elf.m_NeededLibraries), m_SymbolTable(this),
121  m_InitFunc(elf.m_InitFunc), m_FiniFunc(elf.m_FiniFunc)
122 {
123  // Copy the symbol table
124  m_pSymbolTable = copy(elf.m_pSymbolTable, m_nSymbolTableSize);
125 
126  // Copy the string table, somehow?
127  m_pStringTable = copy(elf.m_pStringTable, m_nStringTableSize);
128 
129  // Copy the section header string table, somehow?
130  m_pShstrtab = copy(elf.m_pShstrtab, m_nShstrtabSize);
131 
132  // Copy the REL and RELA tables
133  m_pRelTable = copy(elf.m_pRelTable, m_nRelTableSize);
134  m_pRelaTable = copy(elf.m_pRelaTable, m_nRelaTableSize);
135 
136  // Copy the PLT
137  if (m_bUsesRela)
138  m_pPltRelaTable = copy(elf.m_pPltRelaTable, m_nPltSize);
139  else
140  m_pPltRelTable = copy(elf.m_pPltRelTable, m_nPltSize);
141 
142  // Copy the debug table
143  m_pDebugTable = copy(elf.m_pDebugTable, m_nDebugTableSize);
144 
145  // Copy the dynamic symbol table
146  m_pDynamicSymbolTable =
147  copy(elf.m_pDynamicSymbolTable, m_nDynamicSymbolTableSize);
148 
149  // Copy the dynamic string table, somehow?
150  m_pDynamicStringTable =
151  copy(elf.m_pDynamicStringTable, m_nDynamicStringTableSize);
152 
153  // Copy the section headers
154  m_pSectionHeaders = copy(
155  elf.m_pSectionHeaders, m_nSectionHeaders * sizeof(ElfSectionHeader_t));
156 
157  // Copy the program headers
158  m_pProgramHeaders = copy(
159  elf.m_pProgramHeaders, m_nProgramHeaders * sizeof(ElfProgramHeader_t));
160 
161  // Copy needed libraries info, modifying pointers as we go
162  intptr_t diff = reinterpret_cast<uintptr_t>(m_pDynamicStringTable) -
163  reinterpret_cast<uintptr_t>(elf.m_pDynamicStringTable);
164  for (List<char *>::Iterator it = m_NeededLibraries.begin();
165  it != m_NeededLibraries.end(); it++)
166  {
167  *it = *it + diff;
168  }
169 
170  // Copy symbol table
171  m_SymbolTable.copyTable(this, elf.m_SymbolTable);
172 }
173 
174 bool Elf::createNeededOnly(uint8_t *pBuffer, size_t length)
175 {
176 #ifdef VERBOSE_KERNEL
177  NOTICE(
178  "Elf::createNeededOnly: buffer at "
179  << Hex << reinterpret_cast<uintptr_t>(pBuffer) << ", len " << length);
180 #endif
181  if (!pBuffer || !length)
182  return false;
183 
184  // The main header will be at pBuffer[0].
185  ElfHeader_t *pHeader = reinterpret_cast<ElfHeader_t *>(pBuffer);
186 
187  // Check the ident.
188  if ((pHeader->ident[1] != 'E') || (pHeader->ident[2] != 'L') ||
189  (pHeader->ident[3] != 'F') || (pHeader->ident[0] != 127))
190  {
191  ERROR(
192  "ELF file: ident check failed ["
193  << String(reinterpret_cast<const char *>(pHeader->ident)) << "]!");
194  return false;
195  }
196 
197  // Check the bit-length.
198  if (pHeader->ident[4] !=
199 #ifdef BITS_32
200  1 /* ELFCLASS32 */
201 #else
202  2 /* ELFCLASS64 */
203 #endif
204  )
205  {
206  ERROR("ELF file: wrong bit length!");
207  }
208 
209  // Attempt to load in some program headers, if they exist.
210  if (pHeader->phnum > 0)
211  {
212  m_nProgramHeaders = pHeader->phnum;
213  m_pProgramHeaders = new ElfProgramHeader_t[pHeader->phnum];
214  MemoryCopy(
215  reinterpret_cast<uint8_t *>(m_pProgramHeaders),
216  &pBuffer[pHeader->phoff],
217  sizeof(ElfProgramHeader_t) * pHeader->phnum);
218 
219  size_t nDynamicStringTableSize = 0;
220 
221  // Look for the dynamic program header.
222  for (size_t i = 0; i < m_nProgramHeaders; i++)
223  {
224  if (m_pProgramHeaders[i].type == PT_DYNAMIC)
225  {
226  ElfProgramHeader_t *pDynamic = &m_pProgramHeaders[i];
227  ElfDyn_t *pDyn =
228  reinterpret_cast<ElfDyn_t *>(&pBuffer[pDynamic->offset]);
229 
230  // Cycle through all dynamic entries until the NULL entry.
231  while (pDyn->tag != DT_NULL)
232  {
233  switch (pDyn->tag)
234  {
235  case DT_NEEDED:
236  m_NeededLibraries.pushBack(
237  reinterpret_cast<char *>(pDyn->un.ptr));
238  break;
239  case DT_STRTAB:
240  m_pDynamicStringTable =
241  reinterpret_cast<char *>(pDyn->un.ptr);
242  break;
243  case DT_STRSZ:
244  nDynamicStringTableSize = pDyn->un.val;
245  break;
246  }
247 
248  pDyn++;
249  }
250  }
251  else if (m_pProgramHeaders[i].type == PT_INTERP)
252  {
253  ElfProgramHeader_t *pInterp = &m_pProgramHeaders[i];
254  m_sInterpreter =
255  String(reinterpret_cast<char *>(&pBuffer[pInterp->offset]));
256 
257 #ifdef VERBOSE_KERNEL
258  NOTICE(
259  "ELF::createNeededOnly interpreter is " << m_sInterpreter);
260 #endif
261  }
262  }
263 
264  if (m_pDynamicStringTable)
265  {
266  m_pDynamicStringTable = elfCopy(
267  pBuffer, m_pProgramHeaders, m_nProgramHeaders,
268  m_pDynamicStringTable, nDynamicStringTableSize);
269 
270  // Make sure the string references to needed libraries actually work
271  // as pointers...
272  for (List<char *>::Iterator it = m_NeededLibraries.begin();
273  it != m_NeededLibraries.end(); it++)
274  {
275  *it = *it + reinterpret_cast<uintptr_t>(m_pDynamicStringTable);
276  }
277  }
278  }
279 
280  // Success.
281  return true;
282 }
283 
284 bool Elf::validate(uint8_t *pBuffer, size_t length)
285 {
286  ElfHeader_t *pHeader = reinterpret_cast<ElfHeader_t *>(pBuffer);
287 
288  if (length < sizeof(ElfHeader_t))
289  {
290  return false;
291  }
292 
293  if ((pHeader->ident[1] != 'E') || (pHeader->ident[2] != 'L') ||
294  (pHeader->ident[3] != 'F') || (pHeader->ident[0] != 127))
295  {
296  return false;
297  }
298 
299  if (pHeader->ident[4] !=
300 #ifdef BITS_32
301  1 /* ELFCLASS32 */
302 #else
303  2 /* ELFCLASS64 */
304 #endif
305  )
306  {
307  return false;
308  }
309 
310  return true;
311 }
312 
313 bool Elf::create(uint8_t *pBuffer, size_t length)
314 {
315  NOTICE(
316  "Elf::create: buffer at " << Hex << reinterpret_cast<uintptr_t>(pBuffer)
317  << ", len " << length);
318  // The main header will be at pBuffer[0].
319  ElfHeader_t *pHeader = reinterpret_cast<ElfHeader_t *>(pBuffer);
320 
321  // Check the ident.
322  if ((pHeader->ident[1] != 'E') || (pHeader->ident[2] != 'L') ||
323  (pHeader->ident[3] != 'F') || (pHeader->ident[0] != 127))
324  {
325  ERROR(
326  "ELF file: ident check failed ["
327  << String(reinterpret_cast<const char *>(pHeader->ident)) << "]!");
328  return false;
329  }
330 
331  // Check the bit-length.
332  if (pHeader->ident[4] !=
333 #ifdef BITS_32
334  1 /* ELFCLASS32 */
335 #else
336  2 /* ELFCLASS64 */
337 #endif
338  )
339  {
340  ERROR("ELF file: wrong bit length!");
341  }
342 
343  // Load in the section headers.
344  m_nSectionHeaders = pHeader->shnum;
345  m_pSectionHeaders = new ElfSectionHeader_t[pHeader->shnum];
346  MemoryCopy(
347  reinterpret_cast<uint8_t *>(m_pSectionHeaders),
348  &pBuffer[pHeader->shoff], pHeader->shnum * sizeof(ElfSectionHeader_t));
349 
350  // Find the section header string table.
351  ElfSectionHeader_t *pShstrtab = &m_pSectionHeaders[pHeader->shstrndx];
352 
353  // Load the section header string table.
354  m_nShstrtabSize = pShstrtab->size;
355  m_pShstrtab = new char[m_nShstrtabSize];
356  MemoryCopy(
357  reinterpret_cast<uint8_t *>(m_pShstrtab), &pBuffer[pShstrtab->offset],
358  m_nShstrtabSize);
359 
360  ElfSectionHeader_t *pSymbolTable = 0, *pStringTable = 0;
361  // Go through each section header, trying to find .symtab.
362  for (int i = 0; i < pHeader->shnum; i++)
363  {
364  const char *pStr = m_pShstrtab + m_pSectionHeaders[i].name;
365  if (!StringCompare(pStr, ".symtab"))
366  pSymbolTable = &m_pSectionHeaders[i];
367  if (!StringCompare(pStr, ".strtab"))
368  pStringTable = &m_pSectionHeaders[i];
369  }
370 
371  if (pSymbolTable == 0)
372  {
373  WARNING("ELF: symbol table not found!");
374  }
375  else
376  {
377  m_nSymbolTableSize = pSymbolTable->size;
378  m_pSymbolTable =
379  new ElfSymbol_t[m_nSymbolTableSize / sizeof(ElfSymbol_t)];
380  MemoryCopy(
381  reinterpret_cast<uint8_t *>(m_pSymbolTable),
382  &pBuffer[pSymbolTable->offset], pSymbolTable->size);
383  }
384 
385  if (pStringTable == 0)
386  {
387  WARNING("ELF: string table not found!");
388  }
389  else
390  {
391  m_nStringTableSize = pStringTable->size;
392  m_pStringTable = new char[m_nStringTableSize];
393  MemoryCopy(
394  reinterpret_cast<uint8_t *>(m_pStringTable),
395  &pBuffer[pStringTable->offset], m_nStringTableSize);
396  }
397 
398  // Attempt to load in some program headers, if they exist.
399  if (pHeader->phnum > 0)
400  {
401  m_nProgramHeaders = pHeader->phnum;
402  m_pProgramHeaders = new ElfProgramHeader_t[pHeader->phnum];
403  MemoryCopy(
404  reinterpret_cast<uint8_t *>(m_pProgramHeaders),
405  &pBuffer[pHeader->phoff],
406  sizeof(ElfProgramHeader_t) * pHeader->phnum);
407 
408  // size_t nDynamicStringTableSize = 0;
409 
410  // Look for the dynamic program header.
411  for (size_t i = 0; i < m_nProgramHeaders; i++)
412  {
413  if (m_pProgramHeaders[i].type == PT_DYNAMIC)
414  {
415  ElfProgramHeader_t *pDynamic = &m_pProgramHeaders[i];
416  ElfDyn_t *pDyn =
417  reinterpret_cast<ElfDyn_t *>(&pBuffer[pDynamic->offset]);
418 
419  // Cycle through all dynamic entries until the NULL entry.
420  while (pDyn->tag != DT_NULL)
421  {
422  switch (pDyn->tag)
423  {
424  case DT_NEEDED:
425  m_NeededLibraries.pushBack(
426  reinterpret_cast<char *>(pDyn->un.ptr));
427  break;
428  case DT_SYMTAB:
429  m_pDynamicSymbolTable =
430  reinterpret_cast<ElfSymbol_t *>(pDyn->un.ptr);
431  break;
432  case DT_STRTAB:
433  m_pDynamicStringTable =
434  reinterpret_cast<char *>(pDyn->un.ptr);
435  break;
436  case DT_SYMENT:
437  // This gives the size of *each entity*, not the
438  // table as a whole.
439  // m_nDynamicSymbolTableSize = pDyn->un.val;
440  break;
441  case DT_STRSZ:
442  m_nDynamicStringTableSize = pDyn->un.val;
443  break;
444  case DT_RELA:
445  m_pRelaTable =
446  reinterpret_cast<ElfRela_t *>(pDyn->un.ptr);
447  break;
448  case DT_REL:
449  m_pRelTable =
450  reinterpret_cast<ElfRel_t *>(pDyn->un.ptr);
451  break;
452  case DT_RELSZ:
453  m_nRelTableSize = pDyn->un.val;
454  break;
455  case DT_RELASZ:
456  m_nRelaTableSize = pDyn->un.val;
457  break;
458  case DT_PLTGOT:
459  m_pGotTable =
460  reinterpret_cast<uintptr_t *>(pDyn->un.ptr);
461  break;
462  case DT_JMPREL:
463  {
464  if (m_bUsesRela)
465  m_pPltRelaTable =
466  reinterpret_cast<ElfRela_t *>(pDyn->un.ptr);
467  else
468  m_pPltRelTable =
469  reinterpret_cast<ElfRel_t *>(pDyn->un.ptr);
470  break;
471  }
472  case DT_PLTREL:
473  {
474  if (pDyn->un.val == DT_RELA)
475  {
476  m_bUsesRela = true;
477  }
478  break;
479  }
480  case DT_PLTRELSZ:
481  m_nPltSize = pDyn->un.val;
482  break;
483  case DT_INIT:
484  m_InitFunc = pDyn->un.val;
485  break;
486  case DT_FINI:
487  m_FiniFunc = pDyn->un.val;
488  break;
489  }
490 
491  pDyn++;
492  }
493  }
494  else if (m_pProgramHeaders[i].type == PT_INTERP)
495  {
496  ElfProgramHeader_t *pInterp = &m_pProgramHeaders[i];
497  m_sInterpreter =
498  String(reinterpret_cast<char *>(&pBuffer[pInterp->offset]));
499 
500  NOTICE("ELF::create interpreter is " << m_sInterpreter);
501  }
502  }
503 
504  m_nDynamicSymbolTableSize =
505  reinterpret_cast<uintptr_t>(m_pDynamicStringTable) -
506  reinterpret_cast<uintptr_t>(m_pDynamicSymbolTable);
507 
508  // If we found a dynamic symbol table, string table and Rel(a) table,
509  // attempt to find the segment they reside in and copy them locally.
510  if (m_pDynamicSymbolTable)
511  m_pDynamicSymbolTable = elfCopy(
512  pBuffer, m_pProgramHeaders, m_nProgramHeaders,
513  m_pDynamicSymbolTable, m_nDynamicSymbolTableSize);
514  if (m_pDynamicStringTable)
515  {
516  m_pDynamicStringTable = elfCopy(
517  pBuffer, m_pProgramHeaders, m_nProgramHeaders,
518  m_pDynamicStringTable, m_nDynamicStringTableSize);
519 
520  // Make sure the string references to needed libraries actually work
521  // as pointers...
522  for (List<char *>::Iterator it = m_NeededLibraries.begin();
523  it != m_NeededLibraries.end(); it++)
524  {
525  *it = *it + reinterpret_cast<uintptr_t>(m_pDynamicStringTable);
526  }
527  }
528  if (m_pRelTable)
529  m_pRelTable = elfCopy(
530  pBuffer, m_pProgramHeaders, m_nProgramHeaders, m_pRelTable,
531  m_nRelTableSize);
532  if (m_pRelaTable)
533  m_pRelaTable = elfCopy(
534  pBuffer, m_pProgramHeaders, m_nProgramHeaders, m_pRelaTable,
535  m_nRelaTableSize);
536  if (m_pPltRelTable)
537  m_pPltRelTable = elfCopy(
538  pBuffer, m_pProgramHeaders, m_nProgramHeaders, m_pPltRelTable,
539  m_nPltSize);
540  if (m_pPltRelaTable)
541  m_pPltRelaTable = elfCopy(
542  pBuffer, m_pProgramHeaders, m_nProgramHeaders, m_pPltRelaTable,
543  m_nPltSize);
544  }
545 
546  m_nEntry = pHeader->entry;
547 
548  // Success.
549  return true;
550 }
551 
553  uint8_t *pBuffer, size_t length, uintptr_t &loadBase, size_t &loadSize,
554  SymbolTable *pSymbolTableCopy)
555 {
556  const size_t pageSz = PhysicalMemoryManager::getPageSize();
557  const size_t pageSzMask = PhysicalMemoryManager::getPageSize() - 1;
558  VirtualAddressSpace &va = Processor::information().getVirtualAddressSpace();
559 
560  // Run through the sections to calculate the size required.
561  loadSize = 0;
562  for (size_t i = 0; i < m_nProgramHeaders; ++i)
563  {
564  if (m_pProgramHeaders[i].type == PT_LOAD)
565  {
566  loadSize += m_pProgramHeaders[i].vaddr + m_pProgramHeaders[i].memsz;
567  }
568  }
569  if (loadSize & pageSzMask)
570  {
571  loadSize = (loadSize & ~pageSzMask) + pageSz;
572  }
573 
574  NOTICE("ELF: need " << loadSize << " bytes!");
575 
576  if (!KernelElf::instance().getModuleAllocator().allocate(
577  loadSize, loadBase))
578  {
579  ERROR(
580  "ELF: could not allocate space for this module [loadSize="
581  << loadSize << "]");
582  return false;
583  }
584 
585  m_LoadBase = loadBase;
586 
587  for (size_t i = 0; i < m_nProgramHeaders; ++i)
588  {
589  if (m_pProgramHeaders[i].type == PT_LOAD)
590  {
591  m_pProgramHeaders[i].vaddr += loadBase;
592  uintptr_t baseAddr = m_pProgramHeaders[i].vaddr;
593  uintptr_t loadEnd = baseAddr + m_pProgramHeaders[i].memsz;
594  if (loadEnd & pageSzMask)
595  {
596  loadEnd = (loadEnd & ~pageSzMask) + pageSz;
597  }
598 
599  for (uintptr_t addr = baseAddr; addr < loadEnd; addr += pageSz)
600  {
601  void *virt = reinterpret_cast<void *>(addr);
602  if (!va.isMapped(virt))
603  {
604  physical_uintptr_t phys =
606  va.map(
607  phys, virt,
610  }
611  }
612 
615  MemoryCopy(
616  reinterpret_cast<void *>(baseAddr),
617  pBuffer + m_pProgramHeaders[i].offset,
618  m_pProgramHeaders[i].filesz);
619  if (m_pProgramHeaders[i].memsz > m_pProgramHeaders[i].filesz)
620  {
621  ByteSet(
622  reinterpret_cast<void *>(
623  baseAddr + m_pProgramHeaders[i].filesz),
624  0,
625  m_pProgramHeaders[i].memsz - m_pProgramHeaders[i].filesz);
626  }
627  }
628  }
629 
630  // Now actually map and populate the sections.
631  for (size_t i = 0; i < m_nSectionHeaders; i++)
632  {
633  // rebase section headers into the loaded program header regions
634  if (m_pSectionHeaders[i].flags & SHF_ALLOC)
635  {
636  m_pSectionHeaders[i].addr += loadBase;
637  }
638 
639  if ((m_pSectionHeaders[i].flags & SHF_ALLOC) == 0)
640  {
641  // Load information from non-allocated sections here
642  const char *pStr = m_pShstrtab + m_pSectionHeaders[i].name;
643  if (!StringCompare(pStr, ".debug_frame"))
644  {
645  m_pDebugTable =
646  reinterpret_cast<uint32_t *>(m_pSectionHeaders[i].addr);
647  uintptr_t *debugTablePointers =
648  reinterpret_cast<uintptr_t *>(m_pSectionHeaders[i].addr);
649  m_nDebugTableSize = m_pSectionHeaders[i].size;
650 
651  /* Go through the debug table relocating debug frame
652  information based on the loadBase.
653  */
654  size_t nIndex = 0;
655  while (nIndex < m_nDebugTableSize)
656  {
657  // Get the length of this entry.
658  assert(!(nIndex % sizeof(uint32_t)));
659  uint32_t nLength = m_pDebugTable[nIndex / sizeof(uint32_t)];
660 
661  nIndex += sizeof(uint32_t);
662 
663  const uint32_t k_nCieId = 0xFFFFFFFF;
664 
665  if (nLength == 0xFFFFFFFF)
666  {
667  ERROR("64-bit DWARF file detected, but not supported!");
668  return false;
669  }
670 
671  // Get the type of this entry (or CIE pointer if this is a
672  // FDE).
673  uint32_t nCie = m_pDebugTable[nIndex / sizeof(uint32_t)];
674  nIndex += sizeof(uint32_t);
675 
676  // Is this a CIE?
677  if (nCie == k_nCieId)
678  {
679  // Skip over everything.
680  nIndex += nLength - sizeof(processor_register_t);
681  continue;
682  }
683 
684  // This is a FDE. Get its initial location.
685  assert(!(nIndex % sizeof(uintptr_t)));
686  uintptr_t *nInitialLocation =
687  &debugTablePointers[nIndex / sizeof(uintptr_t)];
688  *nInitialLocation += loadBase;
689 
690  nIndex += nLength - sizeof(processor_register_t);
691  }
692  }
693  }
694  }
695 
696  // Relocate the dynamic section
697  rebaseDynamic();
698 
699  preallocateSymbols(nullptr, pSymbolTableCopy);
700 
701  if (m_pSymbolTable && m_pStringTable)
702  {
703  ElfSymbol_t *pSymbol = m_pSymbolTable;
704 
705  const char *pStrtab = reinterpret_cast<const char *>(m_pStringTable);
706 
707  for (size_t i = 0; i < m_nSymbolTableSize / sizeof(ElfSymbol_t); i++)
708  {
709  const char *pStr;
710 
711  if (ST_TYPE(pSymbol->info) == STT_SECTION)
712  {
713  // Section type - the name will be the name of the section
714  // header it refers to.
715  ElfSectionHeader_t *pSh = &m_pSectionHeaders[pSymbol->shndx];
716  // If it's not allocated, it's a link-once-only section that we
717  // can ignore.
718  if (!(pSh->flags & SHF_ALLOC))
719  {
720  pSymbol++;
721  continue;
722  }
723  // Grab the shstrtab
724  pStr = reinterpret_cast<const char *>(m_pShstrtab) + pSh->name;
725  }
726  else
727  pStr = pStrtab + pSymbol->name;
728 
729  // Insert the symbol into the symbol table.
730  SymbolTable::Binding binding;
731  switch (ST_BIND(pSymbol->info))
732  {
733  case STB_LOCAL:
734  binding = SymbolTable::Local;
735  break;
736  case STB_GLOBAL:
737  binding = SymbolTable::Global;
738  break;
739  case STB_WEAK:
740  binding = SymbolTable::Weak;
741  break;
742  default:
743  binding = SymbolTable::Global;
744  }
745 
748  if (ST_TYPEOK(pSymbol->info))
749  {
750  // If the shndx == UND (0x0), the symbol is in the table but
751  // undefined!
752  if (*pStr != '\0' && pSymbol->shndx != 0)
753  {
754  String name(pStr);
755  m_SymbolTable.insert(
756  name, binding, this, pSymbol->value + loadBase);
757 #ifndef TRACK_HIDDEN_SYMBOLS
758  if (pSymbol->other != STV_HIDDEN)
759 #endif
760  {
761  // not hidden - add to the copied symbol table
762  pSymbolTableCopy->insert(
763  name, binding, this, pSymbol->value + loadBase);
764  }
765  }
766  }
767  pSymbol++;
768  }
769  }
770 
771  if (pSymbolTableCopy)
772  {
773  // Add global names to the copied table
774  populateSymbolTable(pSymbolTableCopy, loadBase);
775  }
776 
777  if (!relocateModinfo(pBuffer, length))
778  {
779  ERROR("Failed to relocate modinfo!");
780  }
781 
782  // If the module has a GOT, fix it up.
783  if (m_pGotTable)
784  {
785  m_pGotTable[1] = 0;
786  m_pGotTable[2] = reinterpret_cast<uintptr_t>(resolveNeeded);
787  }
788 
789  return true;
790 }
791 
792 bool Elf::finaliseModule(uint8_t *pBuffer, size_t length)
793 {
794  bool bRelocate = relocate(pBuffer, length);
795  if (!bRelocate)
796  {
797  return bRelocate;
798  }
799 
800  const size_t pageSz = PhysicalMemoryManager::getPageSize();
801  const size_t pageSzMask = PhysicalMemoryManager::getPageSize() - 1;
802  VirtualAddressSpace &va = Processor::information().getVirtualAddressSpace();
803 
804  for (size_t i = 0; i < m_nProgramHeaders; ++i)
805  {
806  if (m_pProgramHeaders[i].type == PT_LOAD)
807  {
808  uintptr_t baseAddr = m_pProgramHeaders[i].vaddr;
809  uintptr_t loadEnd = baseAddr + m_pProgramHeaders[i].memsz;
810  if (loadEnd & pageSzMask)
811  {
812  loadEnd = (loadEnd & ~pageSzMask) + pageSz;
813  }
814 
815  // Set flags now that we've relocated
816  size_t flags = VirtualAddressSpace::KernelMode;
817  if (m_pProgramHeaders[i].flags & PF_X)
818  {
820  }
821  if (m_pProgramHeaders[i].flags & PF_W)
822  {
824  }
825 
826  for (uintptr_t addr = baseAddr; addr < loadEnd; addr += pageSz)
827  {
828  void *virt = reinterpret_cast<void *>(addr);
829  va.setFlags(virt, flags);
830  }
831  }
832  }
833 
834  return true;
835 }
836 
838  uint8_t *pBuffer, size_t length, uintptr_t &loadBase, SymbolTable *pSymtab,
839  bool bAllocate, size_t *pSize)
840 {
841 #ifdef THREADS
842  NOTICE(
843  "Elf::allocate: buffer at "
844  << Hex << reinterpret_cast<uintptr_t>(pBuffer) << ", len " << length);
845 
846  Process *pProcess =
847  Processor::information().getCurrentThread()->getParent();
848 
849  // Scan the segments to find the size.
850  uintptr_t size = 0;
851  uintptr_t start = ~0;
852  for (size_t i = 0; i < m_nProgramHeaders; i++)
853  {
854  if (m_pProgramHeaders[i].type == PT_LOAD)
855  {
856  size = m_pProgramHeaders[i].vaddr + m_pProgramHeaders[i].memsz;
857  if (m_pProgramHeaders[i].vaddr < start)
858  start = m_pProgramHeaders[i].vaddr;
859  }
860  }
861  // Currently size is actually the last loaded address - subtract the first
862  // loaded address to make it valid.
863  size -= start;
864 
865  if (pSize)
866  *pSize = (size + 0x1000) & 0xFFFFF000;
867 
868  // Here we use an atrocious heuristic for determining if the Elf needs
869  // relocating - if its entry point is < 1MB, it is likely that it needs
870  // relocation.
871  if (m_nEntry < 0x100000)
872  {
873  if (!pProcess->getDynamicSpaceAllocator().allocate(
874  (size + 0x1000) & 0xFFFFF000, loadBase))
875  {
876  if (!pProcess->getSpaceAllocator().allocate(
877  (size + 0x1000) & 0xFFFFF000, loadBase))
878  {
879  return false;
880  }
881  }
882  }
883  else
884  {
885  loadBase = start;
886 
887  // Make sure the Process knows that we've just plonked an Elf at a
888  // specific place, and doesn't try to allocate mmaps or libraries over
889  // it!
890  if (!pProcess->getSpaceAllocator().allocateSpecific(
891  start, (size + 0x1000) & 0xFFFFF000))
892  return false;
893  }
894 
895  m_LoadBase = loadBase;
896 
897  if (bAllocate)
898  {
899  uintptr_t loadAddr = (loadBase == 0) ? start : loadBase;
900  for (uintptr_t j = loadAddr; j < loadAddr + size + 0x1000; j += 0x1000)
901  {
902  physical_uintptr_t phys =
904  bool b = Processor::information().getVirtualAddressSpace().map(
905  phys,
906  reinterpret_cast<void *>(
909  if (!b)
910  WARNING("map() failed for address " << Hex << j);
911  }
912  }
913 
914  preallocateSymbols(nullptr, pSymtab);
915 
916  if (m_pDynamicSymbolTable && m_pDynamicStringTable)
917  {
918  ElfSymbol_t *pSymbol = m_pDynamicSymbolTable;
919 
920  const char *pStrtab = m_pDynamicStringTable;
921 
923  while (reinterpret_cast<uintptr_t>(pSymbol) <
924  reinterpret_cast<uintptr_t>(m_pDynamicSymbolTable) +
925  m_nDynamicSymbolTableSize)
926  {
927  const char *pStr = pStrtab + pSymbol->name;
928 
929  SymbolTable::Binding binding;
930  switch (ST_BIND(pSymbol->info))
931  {
932  case STB_LOCAL:
933  binding = SymbolTable::Local;
934  break;
935  case STB_GLOBAL:
936  binding = SymbolTable::Global;
937  break;
938  case STB_WEAK:
939  binding = SymbolTable::Weak;
940  break;
941  default:
942  binding = SymbolTable::Global;
943  }
944 
945  // Don't let hidden symbols work for lookups
946 #ifndef TRACK_HIDDEN_SYMBOLS
947  if (pSymbol->other != STV_HIDDEN)
948 #endif
949  {
950  if (ST_TYPEOK(pSymbol->info))
951  {
952  // If the shndx == UND (0x0), the symbol is in the table but
953  // undefined!
954  if (pSymbol->shndx != 0)
955  {
956  if (*pStr != 0)
957  {
958  m_SymbolTable.insert(
959  String(pStr), binding, this, pSymbol->value);
960  if (pSymtab)
961  {
962  // Add loadBase in when adding to the
963  // user-defined symtab, to give the user a
964  // "real" value.
965  pSymtab->insert(
966  String(pStr), binding, this,
967  pSymbol->value + loadBase);
968  }
969  }
970  }
971  else
972  {
973  // weak symbol? set it as undefined
974  if (binding == SymbolTable::Weak)
975  {
976  Elf_Xword value = pSymbol->value;
977  if (value == 0)
978  value = ~0;
979  if (*pStr != 0)
980  {
981  m_SymbolTable.insertMultiple(
982  pSymtab, String(pStr), binding, this,
983  value);
984  }
985  }
986  }
987  }
988  }
989  pSymbol++;
990  }
991  }
992 
993  return true;
994 #else
995  ERROR(
996  "Elf::allocate: no thread or process support, cannot allocate memory");
997  return false;
998 #endif
999 }
1000 
1002  uint8_t *pBuffer, size_t length, uintptr_t loadBase, SymbolTable *pSymtab,
1003  uintptr_t nStart, uintptr_t nEnd, bool relocate)
1004 {
1005  NOTICE("LOAD @" << Hex << loadBase);
1006  for (size_t i = 0; i < m_nProgramHeaders; i++)
1007  {
1008  if (m_pProgramHeaders[i].type == PT_LOAD)
1009  {
1010  uintptr_t loadAddr = m_pProgramHeaders[i].vaddr + loadBase;
1011  NOTICE("LOAD[" << i << "]: @" << Hex << loadAddr << ".");
1012 
1013  if (nStart > (loadAddr + m_pProgramHeaders[i].memsz))
1014  continue;
1015  if (nEnd <= loadAddr)
1016  continue;
1017  uintptr_t sectionStart = (loadAddr >= nStart) ? loadAddr : nStart;
1018 
1019  uintptr_t offset =
1020  m_pProgramHeaders[i].offset + (sectionStart - loadAddr);
1021  uintptr_t filesz =
1022  (loadAddr + m_pProgramHeaders[i].filesz >= nEnd) ?
1023  (nEnd - sectionStart) :
1024  (loadAddr + m_pProgramHeaders[i].filesz - sectionStart);
1025  if (loadAddr + m_pProgramHeaders[i].filesz < nStart)
1026  filesz = 0;
1027  uintptr_t memsz =
1028  (loadAddr + m_pProgramHeaders[i].memsz >= nEnd) ?
1029  (nEnd - sectionStart) :
1030  (loadAddr + m_pProgramHeaders[i].memsz - sectionStart);
1031 
1032  // Copy segment data from the file.
1033  MemoryCopy(
1034  reinterpret_cast<uint8_t *>(sectionStart), &pBuffer[offset],
1035  filesz);
1036 
1037  ByteSet(
1038  reinterpret_cast<uint8_t *>(sectionStart + filesz), 0,
1039  memsz - filesz);
1040 
1041 #if defined(PPC_COMMON) || defined(MIPS_COMMON)
1042  Processor::flushDCacheAndInvalidateICache(
1043  loadAddr, loadAddr + m_pProgramHeaders[i].filesz);
1044 #endif
1045  }
1046  }
1047 
1048  if (!relocate)
1049  return true;
1050 
1051  // Apply relocations for the given area.
1052 
1053  // Is it a relocation section?
1054  if (m_pRelTable)
1055  {
1056  // For each relocation entry...
1057  for (ElfRel_t *pRel = m_pRelTable;
1058  pRel < (m_pRelTable + (m_nRelTableSize / sizeof(ElfRel_t)));
1059  pRel++)
1060  {
1061  if ((pRel->offset + loadBase < nStart) ||
1062  (pRel->offset + loadBase >= nEnd))
1063  continue;
1064  if (!applyRelocation(*pRel, 0, pSymtab, loadBase))
1065  return false;
1066  }
1067  }
1068  // How about a relocation with addend?
1069  if (m_pRelaTable)
1070  {
1071  // For each relocation entry...
1072  for (ElfRela_t *pRel = m_pRelaTable;
1073  pRel < (m_pRelaTable + (m_nRelaTableSize / sizeof(ElfRela_t)));
1074  pRel++)
1075  {
1076  if ((pRel->offset + loadBase < nStart) ||
1077  (pRel->offset + loadBase >= nEnd))
1078  continue;
1079  if (!applyRelocation(*pRel, 0, pSymtab, loadBase))
1080  return false;
1081  }
1082  }
1083 
1084  // We must also adjust the values in the GOTPLT, they currently point at
1085  // relative values, we need them to point at absolute ones.
1086  if (m_pPltRelTable)
1087  {
1088  // For each relocation entry...
1089  ElfRel_t *pRel = m_pPltRelTable;
1090  for (size_t i = 0; i < m_nPltSize / sizeof(ElfRel_t); i++, pRel++)
1091  {
1092  if ((pRel->offset + loadBase < nStart) ||
1093  (pRel->offset + loadBase >= nEnd))
1094  continue;
1095  uintptr_t *address =
1096  reinterpret_cast<uintptr_t *>(loadBase + pRel->offset);
1097  *address += loadBase;
1098  }
1099  }
1100  if (m_pPltRelaTable)
1101  {
1102  // For each relocation entry...
1103  ElfRela_t *pRel = m_pPltRelaTable;
1104  for (size_t i = 0; i < m_nPltSize / sizeof(ElfRela_t); i++, pRel++)
1105  {
1106  if ((pRel->offset + loadBase < nStart) ||
1107  (pRel->offset + loadBase >= nEnd))
1108  continue;
1109  uintptr_t *address =
1110  reinterpret_cast<uintptr_t *>(loadBase + pRel->offset);
1111  *address += loadBase;
1112  }
1113  }
1114 
1115  // Success.
1116  return true;
1117 }
1118 
1119 bool Elf::extractEntryPoint(uint8_t *pBuffer, size_t length, uintptr_t &entry)
1120 {
1122  if (length < sizeof(ElfHeader_t))
1123  return false;
1124 
1125  ElfHeader_t *pHeader = reinterpret_cast<ElfHeader_t *>(pBuffer);
1126  entry = pHeader->entry;
1127 
1128  return true;
1129 }
1130 
1132  uint8_t *pBuffer, size_t length, size_t &phdrCount, size_t &phdrEntrySize,
1133  uintptr_t &phdrAddress)
1134 {
1136  if (length < sizeof(ElfHeader_t))
1137  return false;
1138 
1139  ElfHeader_t *pHeader = reinterpret_cast<ElfHeader_t *>(pBuffer);
1140  phdrCount = pHeader->phnum;
1141  phdrEntrySize = pHeader->phentsize;
1142  phdrAddress = reinterpret_cast<uintptr_t>(pBuffer) + pHeader->phoff;
1143 
1144  return true;
1145 }
1146 
1148 {
1149  // TODO
1150  return 0;
1151 }
1152 
1153 const char *Elf::lookupSymbol(uintptr_t addr, uintptr_t *startAddr)
1154 {
1155  if (!m_pSymbolTable || !m_pStringTable)
1156  {
1157  return 0; // Just return null if we haven't got a symbol table.
1158  }
1159  return lookupSymbol(addr, startAddr, m_pSymbolTable);
1160 }
1161 
1162 template <class T>
1163 const char *
1164 Elf::lookupSymbol(uintptr_t addr, uintptr_t *startAddr, T *symbolTable)
1165 {
1166  if (!symbolTable || !m_pStringTable)
1167  {
1168  return 0; // Just return null if we haven't got the needed tables.
1169  }
1170 
1171  T *pSymbol = symbolTable;
1172 
1173  const char *pStrtab = reinterpret_cast<const char *>(m_pStringTable);
1174 
1175  for (size_t i = 0; i < m_nSymbolTableSize / sizeof(T); i++)
1176  {
1177  // Make sure we're looking at an object or function.
1178  if (ST_TYPE(pSymbol->info) != STT_FUNC /* function */ &&
1179  ST_TYPE(pSymbol->info) != STT_NOTYPE /* notype (asm functions) */)
1180  {
1181  pSymbol++;
1182  continue;
1183  }
1184 
1185  // Make sure it's a binding we can use.
1186  // We skip over all non-global symbols to enforce decoration of
1187  // functions with export tags, and to ensure functions are not
1188  // unintentionally exposed.
1189  if (ST_BIND(pSymbol->info) != STB_GLOBAL)
1190  {
1191  ++pSymbol;
1192  continue;
1193  }
1194 
1198 
1199  // If we're checking for a symbol that is apparently zero-sized, add one
1200  // so we can actually count it!
1201  Elf_Xword size = pSymbol->size;
1202  if (size == 0)
1203  size = 0x100;
1204  if ((addr >= pSymbol->value) && (addr < (pSymbol->value + size)))
1205  {
1206  const char *pStr = pStrtab + pSymbol->name;
1207  if (startAddr)
1208  *startAddr = pSymbol->value;
1209  return pStr;
1210  }
1211  pSymbol++;
1212  }
1213  return 0;
1214 }
1215 
1216 uintptr_t Elf::lookupSymbol(const char *pName)
1217 {
1218  return m_SymbolTable.lookup(String(pName), this);
1219 }
1220 
1221 uintptr_t Elf::lookupDynamicSymbolAddress(const char *sym, uintptr_t loadBase)
1222 {
1223  uintptr_t value = m_SymbolTable.lookup(String(sym), this);
1224  if (!value)
1225  return 0;
1226  else
1227  return value + loadBase;
1228 }
1229 
1231 {
1232  return reinterpret_cast<uintptr_t>(m_pGotTable);
1233 }
1234 
1236 {
1237  return m_nEntry;
1238 }
1239 
1240 bool Elf::relocate(uint8_t *pBuffer, uintptr_t length)
1241 {
1242  // For every section...
1243  for (size_t i = 0; i < m_nSectionHeaders; i++)
1244  {
1245  ElfSectionHeader_t *pSh = &m_pSectionHeaders[i];
1246 
1247  if (pSh->type != SHT_REL && pSh->type != SHT_RELA)
1248  continue;
1249 
1250  // Grab the section header that this relocation section refers to.
1251  ElfSectionHeader_t *pLink = &m_pSectionHeaders[pSh->link];
1252 
1253  // Grab the shstrtab
1254  const char *pStr =
1255  reinterpret_cast<const char *>(m_pShstrtab) + pLink->name;
1256  if (!StringCompare(pStr, ".modinfo"))
1257  {
1258  // Don't relocate the modinfo section now
1259  continue;
1260  }
1261 
1262  // Is it a relocation section?
1263  if (pSh->type == SHT_REL)
1264  {
1265  // For each relocation entry...
1266  for (ElfRel_t *pRel =
1267  reinterpret_cast<ElfRel_t *>(&pBuffer[pSh->offset]);
1268  pRel < reinterpret_cast<ElfRel_t *>(
1269  &pBuffer[pSh->offset + pSh->size]);
1270  pRel++)
1271  {
1272  if (!applyRelocation(*pRel, pLink))
1273  return false;
1274  }
1275  }
1276  // How about a relocation with addend?
1277  else if (pSh->type == SHT_RELA)
1278  {
1279  // For each relocation entry...
1280  for (ElfRela_t *pRel =
1281  reinterpret_cast<ElfRela_t *>(&pBuffer[pSh->offset]);
1282  pRel < reinterpret_cast<ElfRela_t *>(
1283  &pBuffer[pSh->offset + pSh->size]);
1284  pRel++)
1285  {
1286  if (!applyRelocation(*pRel, pLink))
1287  {
1288  return false;
1289  }
1290  }
1291  }
1292  }
1293 
1294  // Success!
1295  return true;
1296 }
1297 
1298 bool Elf::relocateModinfo(uint8_t *pBuffer, uintptr_t length)
1299 {
1300  // For every section...
1301  for (size_t i = 0; i < m_nSectionHeaders; i++)
1302  {
1303  ElfSectionHeader_t *pSh = &m_pSectionHeaders[i];
1304  if (pSh->type != SHT_REL && pSh->type != SHT_RELA)
1305  {
1306  continue;
1307  }
1308  // Grab the section header that this relocation section refers to.
1309  ElfSectionHeader_t *pLink = &m_pSectionHeaders[pSh->link];
1310 
1311  // Grab the shstrtab
1312  const char *pStr =
1313  reinterpret_cast<const char *>(m_pShstrtab) + pLink->name;
1314  if (StringCompare(pStr, ".modinfo"))
1315  {
1316  continue;
1317  }
1318 
1319  // Is it a relocation section?
1320  if (pSh->type == SHT_REL)
1321  {
1322  // For each relocation entry...
1323  for (ElfRel_t *pRel =
1324  reinterpret_cast<ElfRel_t *>(&pBuffer[pSh->offset]);
1325  pRel < reinterpret_cast<ElfRel_t *>(
1326  &pBuffer[pSh->offset + pSh->size]);
1327  pRel++)
1328  {
1329  if (!applyRelocation(*pRel, pLink))
1330  return false;
1331  }
1332  }
1333  // How about a relocation with addend?
1334  else if (pSh->type == SHT_RELA)
1335  {
1336  // For each relocation entry...
1337  for (ElfRela_t *pRel =
1338  reinterpret_cast<ElfRela_t *>(&pBuffer[pSh->offset]);
1339  pRel < reinterpret_cast<ElfRela_t *>(
1340  &pBuffer[pSh->offset + pSh->size]);
1341  pRel++)
1342  {
1343  if (!applyRelocation(*pRel, pLink))
1344  return false;
1345  }
1346  }
1347  }
1348 
1349  // Success!
1350  return true;
1351 }
1352 
1354  uintptr_t off, SymbolTable *pSymtab, uintptr_t loadBase,
1355  SymbolTable::Policy policy)
1356 {
1357  // Is it a relocation section?
1358  if (m_pPltRelTable)
1359  {
1360  // For each relocation entry...
1361  ElfRel_t *pRel = adjust_pointer(m_pPltRelTable, off);
1362 
1363  applyRelocation(*pRel, 0, pSymtab, loadBase, policy);
1364 
1365  uintptr_t address = loadBase + pRel->offset;
1366 
1367  return *reinterpret_cast<uintptr_t *>(address);
1368  }
1369  // How about a relocation with addend?
1370  if (m_pPltRelaTable)
1371  {
1372  // For each relocation entry...
1373  ElfRela_t pRel = m_pPltRelaTable[off];
1374  applyRelocation(pRel, 0, pSymtab, loadBase, policy);
1375 
1376  uintptr_t address = loadBase + pRel.offset;
1377 
1378  return *reinterpret_cast<uintptr_t *>(address);
1379  }
1380  return 0;
1381 }
1382 
1383 uintptr_t Elf::debugFrameTable()
1384 {
1385  return reinterpret_cast<uintptr_t>(m_pDebugTable);
1386 }
1387 
1388 uintptr_t Elf::debugFrameTableLength()
1389 {
1390  return m_nDebugTableSize;
1391 }
1392 
1394 {
1395  return m_NeededLibraries;
1396 }
1397 
1399 {
1400  return m_sInterpreter;
1401 }
1402 
1404 {
1405  return m_nPltSize;
1406 }
1407 
1408 void Elf::populateSymbolTable(SymbolTable *pSymtab, uintptr_t loadBase)
1409 {
1410  preallocateSymbols(pSymtab);
1411 
1412  if (m_pDynamicSymbolTable && m_pDynamicStringTable)
1413  {
1414  ElfSymbol_t *pSymbol = m_pDynamicSymbolTable;
1415 
1416  const char *pStrtab = m_pDynamicStringTable;
1417 
1419  while (reinterpret_cast<uintptr_t>(pSymbol) <
1420  reinterpret_cast<uintptr_t>(m_pDynamicSymbolTable) +
1421  m_nDynamicSymbolTableSize)
1422  {
1423  const char *pStr = pStrtab + pSymbol->name;
1424 
1425  // If the shndx == UND (0x0), the symbol is in the table but
1426  // undefined!
1427  if (pSymbol->shndx != 0)
1428  {
1429  SymbolTable::Binding binding;
1430  switch (ST_BIND(pSymbol->info))
1431  {
1432  case STB_LOCAL:
1433  binding = SymbolTable::Local;
1434  break;
1435  case STB_GLOBAL:
1436  binding = SymbolTable::Global;
1437  break;
1438  case STB_WEAK:
1439  binding = SymbolTable::Weak;
1440  break;
1441  default:
1442  binding = SymbolTable::Global;
1443  }
1444 
1445  // Don't insert hidden symbols
1446 #ifndef TRACK_HIDDEN_SYMBOLS
1447  if (pSymbol->other != STV_HIDDEN)
1448 #endif
1449  {
1450  if (ST_TYPEOK(pSymbol->info))
1451  {
1452  if (*pStr != 0)
1453  {
1454  if (pSymtab)
1455  {
1456  pSymtab->insert(
1457  String(pStr), binding, this,
1458  pSymbol->value + loadBase);
1459  }
1460  }
1461  }
1462  }
1463  }
1464  pSymbol++;
1465  }
1466  }
1467 }
1468 
1470  SymbolTable *pSymtabOverride, SymbolTable *pAdditionalSymtab)
1471 {
1472  if (!pSymtabOverride)
1473  {
1474  pSymtabOverride = &m_SymbolTable;
1475  }
1476 
1477  size_t numLocal = 0;
1478  size_t numWeak = 0;
1479  size_t numGlobal = 0;
1480 
1481  if (m_pSymbolTable)
1482  {
1483  // quick pass to preallocate for the symbol table
1484  for (size_t i = 0; i < m_nSymbolTableSize / sizeof(ElfSymbol_t); i++)
1485  {
1486  switch (ST_BIND(m_pSymbolTable[i].info))
1487  {
1488  case STB_LOCAL:
1489  ++numLocal;
1490  break;
1491  case STB_GLOBAL:
1492  ++numGlobal;
1493  break;
1494  case STB_WEAK:
1495  ++numWeak;
1496  break;
1497  default:
1498  ++numGlobal;
1499  }
1500  }
1501  }
1502 
1503  if (m_pDynamicSymbolTable)
1504  {
1505  // quick pass to preallocate for the symbol table
1506  for (size_t i = 0; i < m_nDynamicSymbolTableSize / sizeof(ElfSymbol_t);
1507  i++)
1508  {
1509  switch (ST_BIND(m_pDynamicSymbolTable[i].info))
1510  {
1511  case STB_LOCAL:
1512  ++numLocal;
1513  break;
1514  case STB_GLOBAL:
1515  ++numGlobal;
1516  break;
1517  case STB_WEAK:
1518  ++numWeak;
1519  break;
1520  default:
1521  ++numGlobal;
1522  }
1523  }
1524  }
1525 
1526  if (numLocal || numWeak || numGlobal)
1527  {
1528  NOTICE(
1529  "ELF: preallocating symbol table with "
1530  << numGlobal << " global " << numWeak << " weak and " << numLocal
1531  << " local symbols.");
1532  pSymtabOverride->preallocate(numGlobal, numWeak, this, numLocal);
1533  if (pAdditionalSymtab)
1534  {
1535  pAdditionalSymtab->preallocateAdditional(
1536  numGlobal, numWeak, this, numLocal);
1537  }
1538  }
1539 }
1540 
1542 {
1543  // Only rebase things that are not elfCopy'd
1544  if (m_pGotTable)
1545  {
1546  m_pGotTable = adjust_pointer(m_pGotTable, m_LoadBase);
1547  }
1548  if (m_InitFunc)
1549  {
1550  m_InitFunc += m_LoadBase;
1551  }
1552  if (m_FiniFunc)
1553  {
1554  m_FiniFunc += m_LoadBase;
1555  }
1556 }
1557 
1559 template const char *Elf::lookupSymbol<Elf::ElfSymbol_t>(
1560  uintptr_t addr, uintptr_t *startAddr = 0, ElfSymbol_t *symbolTable = 0);
1561 #ifdef BITS_64
1562 template const char *Elf::lookupSymbol<Elf::Elf32Symbol_t>(
1563  uintptr_t addr, uintptr_t *startAddr = 0, Elf32Symbol_t *symbolTable = 0);
1564 #endif
uintptr_t getLastAddress()
Definition: linker/Elf.cc:1147
void pushBack(const T &value)
Definition: List.h:232
uintptr_t EXPORTED_PUBLIC lookup(const HashedStringView &name, Elf *pElf, Policy policy=LocalFirst, Binding *pBinding=0)
Definition: SymbolTable.cc:126
void preallocateAdditional(size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
Definition: SymbolTable.cc:86
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)
Definition: linker/Elf.cc:1001
uintptr_t lookupDynamicSymbolAddress(const char *str, uintptr_t loadBase)
Definition: linker/Elf.cc:1221
static PhysicalMemoryManager & instance()
virtual void setFlags(void *virtualAddress, size_t newFlags)=0
virtual physical_uintptr_t allocatePage(size_t pageConstraints=0)=0
Elf()
Definition: linker/Elf.cc:75
virtual bool isMapped(void *virtualAddress)=0
virtual bool map(physical_uintptr_t physicalAddress, void *virtualAddress, size_t flags)=0
static T * elfCopy(uint8_t *, ElfProgramHeader_t *, size_t, T *, size_t)
Definition: linker/Elf.cc:55
Definition: String.h:49
const char * lookupSymbol(uintptr_t addr, uintptr_t *startAddr, T *symbolTable)
Definition: linker/Elf.cc:1164
static ProcessorInformation & information()
Definition: Processor.cc:45
bool allocate(uint8_t *pBuffer, size_t length, uintptr_t &loadBase, SymbolTable *pSymtab=0, bool bAllocate=true, size_t *pSize=0)
Definition: linker/Elf.cc:837
bool allocate(T length, T &address)
Definition: RangeList.h:222
static KernelElf & instance()
Definition: KernelElf.h:129
bool createNeededOnly(uint8_t *pBuffer, size_t length)
Definition: linker/Elf.cc:174
#define WARNING(text)
Definition: Log.h:78
static bool extractEntryPoint(uint8_t *pBuffer, size_t length, uintptr_t &entry)
Definition: linker/Elf.cc:1119
Definition: List.h:64
void insert(const String &name, Binding binding, Elf *pParent, uintptr_t value)
Definition: SymbolTable.cc:51
MemoryAllocator & getDynamicSpaceAllocator()
Definition: Process.h:183
size_t getPltSize()
Definition: linker/Elf.cc:1403
#define NOTICE(text)
Definition: Log.h:74
Definition: Log.h:136
bool allocateSpecific(T address, T length)
Definition: RangeList.h:280
#define assert(x)
Definition: assert.h:37
bool finaliseModule(uint8_t *pBuffer, uintptr_t length)
Definition: linker/Elf.cc:792
Iterator begin()
Definition: List.h:123
uintptr_t applySpecificRelocation(uintptr_t off, SymbolTable *pSymtab, uintptr_t loadBase, SymbolTable::Policy policy=SymbolTable::LocalFirst)
Definition: linker/Elf.cc:1353
void populateSymbolTable(SymbolTable *pSymtab, uintptr_t loadBase)
Definition: linker/Elf.cc:1408
uintptr_t getGlobalOffsetTable()
Definition: linker/Elf.cc:1230
bool create(uint8_t *pBuffer, size_t length)
Definition: linker/Elf.cc:313
String & getInterpreter()
Definition: linker/Elf.cc:1398
virtual ~Elf()
Definition: linker/Elf.cc:88
static bool extractInformation(uint8_t *pBuffer, size_t length, size_t &phdrCount, size_t &phdrEntrySize, uintptr_t &phdrAddress)
Definition: linker/Elf.cc:1131
void rebaseDynamic()
Definition: linker/Elf.cc:1541
bool loadModule(uint8_t *pBuffer, size_t length, uintptr_t &loadBase, size_t &loadSize, SymbolTable *pSymbolTableCopy=0)
Definition: linker/Elf.cc:552
bool applyRelocation(ElfRel_t rel, ElfSectionHeader_t *pSh, SymbolTable *pSymtab=0, uintptr_t loadBase=0, SymbolTable::Policy policy=SymbolTable::LocalFirst)
Definition: Elf.h:201
#define ERROR(text)
Definition: Log.h:82
void copyTable(Elf *pNewElf, const SymbolTable &newSymtab)
Definition: SymbolTable.cc:40
bool validate(uint8_t *pBuffer, size_t length)
Definition: linker/Elf.cc:284
void insertMultiple(SymbolTable *pOther, const String &name, Binding binding, Elf *pParent, uintptr_t value)
Definition: SymbolTable.cc:59
#define FATAL(text)
Definition: Log.h:89
List< char * > & neededLibraries()
Definition: linker/Elf.cc:1393
Iterator end()
Definition: List.h:135
void preallocateSymbols(SymbolTable *pSymtabOverride=nullptr, SymbolTable *pAdditionalSymtab=nullptr)
Definition: linker/Elf.cc:1469
uintptr_t getEntryPoint()
Definition: linker/Elf.cc:1235
void preallocate(size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
Definition: SymbolTable.cc:73
MemoryAllocator & getSpaceAllocator()
Definition: Process.h:178