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