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