The Pedigree Project 0.1
amd64/DynamicLinker.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 "modules/system/linker/DynamicLinker.h"
21#include "pedigree/kernel/Log.h"
22#include "pedigree/kernel/linker/Elf.h"
23#include "pedigree/kernel/linker/SymbolTable.h"
24#include "pedigree/kernel/processor/PhysicalMemoryManager.h"
25#include "pedigree/kernel/processor/Processor.h"
26#include "pedigree/kernel/processor/ProcessorInformation.h"
27#include "pedigree/kernel/processor/VirtualAddressSpace.h"
28#include "pedigree/kernel/utilities/utility.h"
29
30extern "C" void resolveSymbol(void);
31
32void DynamicLinker::initPlt(Elf* pElf, uintptr_t value) {
33 // Value == loadBase. If this changes, add an extra parameter to get
34 // loadBase here!
35 NOTICE("Value: " << value);
36 uint64_t* got = reinterpret_cast<uint64_t*>(pElf->getGlobalOffsetTable() + value);
37 if (reinterpret_cast<uintptr_t>(got) == value) {
38 WARNING("DynamicLinker: Global offset table not found!");
39 return;
40 }
41 NOTICE("got: " << reinterpret_cast<uintptr_t>(got));
42 got++; // Go to GOT+8
43 *got = value & 0xFFFFFFFF; // Library ID
44 got++; // Got to GOT+16
45
46 // Check if the resolve function has been set already...
47 if (*got == 0) {
48 uintptr_t resolveLocation = 0;
49
50 // Grab a page to copy the PLT resolve function to.
51 // Start at 0x20000000, looking for the next free page.
53 const size_t pageSize = PhysicalMemoryManager::getPageSize();
54 for (uintptr_t i = 0x40000000; i < 0x50000000; i += pageSize) {
55 if (Processor::information().getVirtualAddressSpace().isMapped(reinterpret_cast<void*>(i))) {
56 continue;
57 }
58
59 resolveLocation = i;
60 break;
61 }
62
63 if (resolveLocation == 0) {
64 ERROR("DynamicLinker: nowhere to put resolve function.");
65 return;
66 }
67
68 physical_uintptr_t physPage = PhysicalMemoryManager::instance().allocatePage();
69 bool b = Processor::information().getVirtualAddressSpace().map(
70 physPage, reinterpret_cast<void*>(resolveLocation),
72
73 if (!b) {
74 ERROR("DynamicLinker: Could not map resolve function.");
75 }
76
77 // Memcpy over the resolve function into the user address space.
78 // resolveSymbol is an ASM function, defined in ./asm-amd64.s
79 MemoryCopy(reinterpret_cast<uint8_t*>(resolveLocation),
80 reinterpret_cast<uint8_t*>(&::resolveSymbol), pageSize);
81
82 *got = resolveLocation;
83 }
84}
85
86uintptr_t DynamicLinker::resolvePltSymbol(uintptr_t libraryId, uintptr_t symIdx) {
87 // Find the correct ELF to patch.
88 Elf* pElf = 0;
89 uintptr_t loadBase = libraryId;
90
91 if (libraryId == 0)
92 pElf = m_pProgramElf;
93 else {
94 SharedObject* pSo = m_Objects.lookup(libraryId);
95 if (pSo)
96 pElf = pSo->elf;
97 }
98
99 if (!pElf) {
100 ERROR("DynamicLinker::resolvePltSymbol: No library found for id `" << Hex << libraryId << "'");
101 return 0;
102 }
103
104 uintptr_t result =
105 pElf->applySpecificRelocation(symIdx, m_pProgramElf->getSymbolTable(), loadBase);
106 if (result == 0)
107 result = pElf->applySpecificRelocation(symIdx, m_pProgramElf->getSymbolTable(), loadBase,
109 NOTICE("Resolve " << symIdx << ", lib: " << libraryId << "; " << result);
110 return result;
111}
void initPlt(Elf *pElf, uintptr_t value)
Definition Elf.h:201
uintptr_t applySpecificRelocation(uintptr_t off, SymbolTable *pSymtab, uintptr_t loadBase, SymbolTable::Policy policy=SymbolTable::LocalFirst)
uintptr_t getGlobalOffsetTable()
virtual physical_uintptr_t allocatePage(size_t pageConstraints=0)=0
static PhysicalMemoryManager & instance()
static ProcessorInformation & information()
@ Hex
Definition Log.h:124