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