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