The Pedigree Project  0.1
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/File.h"
24 #include "modules/system/vfs/Symlink.h"
25 #include "modules/system/vfs/VFS.h"
26 #include "pedigree/kernel/Log.h"
27 #include "pedigree/kernel/linker/Elf.h"
28 #include "pedigree/kernel/linker/SymbolTable.h"
29 #include "pedigree/kernel/process/Process.h"
30 #include "pedigree/kernel/process/Thread.h"
31 #include "pedigree/kernel/processor/KernelCoreSyscallManager.h"
32 #include "pedigree/kernel/processor/PhysicalMemoryManager.h"
33 #include "pedigree/kernel/processor/Processor.h"
34 #include "pedigree/kernel/processor/ProcessorInformation.h"
35 #include "pedigree/kernel/processor/VirtualAddressSpace.h"
36 #include "pedigree/kernel/processor/state.h"
37 #include "pedigree/kernel/utilities/Iterator.h"
38 #include "pedigree/kernel/utilities/List.h"
39 #include "pedigree/kernel/utilities/Result.h"
40 #include "pedigree/kernel/utilities/utility.h"
41 
42 DLTrapHandler DLTrapHandler::m_Instance;
43 
44 uintptr_t DynamicLinker::resolvePlt(SyscallState &state)
45 {
46  Process *pProcess =
47  Processor::information().getCurrentThread()->getParent();
48 
49  return pProcess->getLinker()->resolvePltSymbol(
50  state.getSyscallParameter(0), state.getSyscallParameter(1));
51 }
52 
54  : m_pProgramElf(0), m_ProgramStart(0), m_ProgramSize(0), m_ProgramBuffer(0),
55  m_LoadedObjects(), m_Objects()
56 {
57 }
58 
60  : m_pProgramElf(other.m_pProgramElf), m_ProgramStart(other.m_ProgramStart),
61  m_ProgramSize(other.m_ProgramSize),
62  m_ProgramBuffer(other.m_ProgramBuffer),
63  m_LoadedObjects(other.m_LoadedObjects), m_Objects()
64 {
65  m_pProgramElf = new Elf(*other.m_pProgramElf);
66  for (Tree<uintptr_t, SharedObject *>::Iterator it = other.m_Objects.begin();
67  it != other.m_Objects.end(); it++)
68  {
69  uintptr_t key = it.key();
70  SharedObject *pSo = it.value();
71  m_Objects.insert(
72  key, new SharedObject(
73  new Elf(*pSo->elf), pSo->file, pSo->buffer, pSo->address,
74  pSo->size));
75  }
76 }
77 
78 DynamicLinker::~DynamicLinker()
79 {
80  // VirtualAddressSpace &va =
81  // Processor::information().getVirtualAddressSpace();
82 
83  for (Tree<uintptr_t, SharedObject *>::Iterator it = m_Objects.begin();
84  it != m_Objects.end(); it++)
85  {
86  SharedObject *pSo = it.value();
87  delete pSo->elf;
88  delete pSo;
89  }
90 
91  delete m_pProgramElf;
92 }
93 
95  File *pFile, bool bDryRun, bool bInterpreter, String *sInterpreter)
96 {
97  if (!pFile)
98  return false;
99 
100  uintptr_t buffer = 0;
102  pFile, buffer, pFile->getSize(), MemoryMappedObject::Read);
103 
104  String fileName;
105  pFile->getName(fileName);
106 #ifdef VERBOSE_KERNEL
107  NOTICE("DynamicLinker::loadProgram(" << fileName << ")");
108 #endif
109 
110  Elf *programElf = new Elf();
111 
112  if (!bDryRun)
113  {
114  delete m_pProgramElf;
115  m_pProgramElf = programElf;
116  if (!m_pProgramElf->create(
117  reinterpret_cast<uint8_t *>(buffer), pFile->getSize()))
118  {
119  ERROR(
120  "DynamicLinker: Main program ELF failed to create: `"
121  << fileName << "' at " << buffer);
123 
124  delete m_pProgramElf;
125  m_pProgramElf = 0;
126  return false;
127  }
128 
129  if (!m_pProgramElf->allocate(
130  reinterpret_cast<uint8_t *>(buffer), pFile->getSize(),
131  m_ProgramStart, 0, false, &m_ProgramSize))
132  {
133  ERROR(
134  "DynamicLinker: Main program ELF failed to load: `" << fileName
135  << "'");
137 
138  delete m_pProgramElf;
139  m_pProgramElf = 0;
140  return false;
141  }
142 
143  m_ProgramBuffer = buffer;
144  }
145  else
146  {
147  if (!programElf->createNeededOnly(
148  reinterpret_cast<uint8_t *>(buffer), pFile->getSize()))
149  {
150  ERROR(
151  "DynamicLinker: Main program ELF failed to create: `"
152  << fileName << "' at " << buffer);
154 
155  if (!bDryRun)
156  {
157  delete m_pProgramElf;
158  m_pProgramElf = 0;
159  }
160  else
161  delete programElf;
162  return false;
163  }
164  }
165 
166  if (bInterpreter)
167  {
168  if (!sInterpreter)
169  return false;
170  *sInterpreter = programElf->getInterpreter();
171  bool hasInterpreter = sInterpreter->length() > 0;
172  if (bDryRun)
173  {
174  // Clean up the ELF
175  delete programElf;
176  m_pProgramElf = 0;
177 
178  // Unmap this file - any future loadProgram will map it again.
180  }
181  return hasInterpreter;
182  }
183 
184  List<char *> &dependencies = programElf->neededLibraries();
185 
186  // Load all dependencies
187  for (List<char *>::Iterator it = dependencies.begin();
188  it != dependencies.end(); it++)
189  {
190  // Extreme validation
191  if (!*it)
192  continue;
193  if (m_LoadedObjects.lookup(String(*it)).hasValue())
194  {
195  WARNING("Object `" << *it << "' has already been loaded");
196  continue;
197  }
198 
199  String filename;
200  filename += "root»/libraries/";
201  filename += *it;
202  File *pDependencyFile = VFS::instance().find(filename);
203  if (!pDependencyFile)
204  {
205  ERROR("DynamicLinker: Dependency `" << filename << "' not found!");
206  if (!bDryRun)
207  {
208  delete m_pProgramElf;
209  m_pProgramElf = 0;
210  }
211  else
212  delete programElf;
213  return false;
214  }
215  while (pDependencyFile && pDependencyFile->isSymlink())
216  pDependencyFile = Symlink::fromFile(pDependencyFile)->followLink();
217  if (!pDependencyFile || !loadObject(pDependencyFile, bDryRun))
218  {
219  ERROR(
220  "DynamicLinker: Dependency `" << filename
221  << "' failed to load!");
222  if (!bDryRun)
223  {
224  delete m_pProgramElf;
225  m_pProgramElf = 0;
226  }
227  else
228  delete programElf;
229  return false;
230  }
231 
232  // Success! Add the filename of the library (NOT WITH LIBRARIES
233  // DIRECTORY) to the known loaded objects list.
234  if (!bDryRun)
235  m_LoadedObjects.insert(String(*it), reinterpret_cast<void *>(1));
236  }
237 
238  if (!bDryRun)
239  initPlt(m_pProgramElf, 0);
240  else
241  delete programElf;
242 
243  return true;
244 }
245 
246 bool DynamicLinker::loadObject(File *pFile, bool bDryRun)
247 {
248  uintptr_t buffer = 0;
249  size_t size;
250  uintptr_t loadBase = 0;
252  pFile, buffer, pFile->getSize(), MemoryMappedObject::Read);
253 
254  Elf *pElf = new Elf();
255  SharedObject *pSo = 0;
256 
257  String fileName;
258  pFile->getName(fileName);
259  NOTICE("DynamicLinker::loadObject(" << fileName << ")");
260 
261  if (!bDryRun)
262  {
263  if (!pElf->create(
264  reinterpret_cast<uint8_t *>(buffer), pFile->getSize()))
265  {
266  ERROR(
267  "DynamicLinker: ELF creation failed for file `"
268  << pFile->getName() << "'");
269  delete pElf;
270  return false;
271  }
272 
273  if (!pElf->allocate(
274  reinterpret_cast<uint8_t *>(buffer), pFile->getSize(), loadBase,
275  m_pProgramElf->getSymbolTable(), false, &size))
276  {
277  ERROR(
278  "DynamicLinker: ELF allocate failed for file `"
279  << pFile->getName() << "'");
280  delete pElf;
281  return false;
282  }
283 
284  pSo = new SharedObject(pElf, pMmFile, buffer, loadBase, size);
285 
286  m_Objects.insert(loadBase, pSo);
287  }
288  else
289  {
290  if (!pElf->createNeededOnly(
291  reinterpret_cast<uint8_t *>(buffer), pFile->getSize()))
292  {
293  ERROR(
294  "DynamicLinker: ELF creation failed for file `"
295  << pFile->getName() << "'");
296  delete pElf;
297  return false;
298  }
299  }
300 
301  List<char *> &dependencies = pElf->neededLibraries();
302 
303  // Load all dependencies
304  for (List<char *>::Iterator it = dependencies.begin();
305  it != dependencies.end(); it++)
306  {
307  // Extreme validation
308  if (!*it)
309  continue;
310  if (m_LoadedObjects.lookup(String(*it)).hasValue())
311  {
312  WARNING("Object `" << *it << "' has already been loaded");
313  continue;
314  }
315 
316  String filename;
317  filename += "root»/libraries/";
318  filename += *it;
319  File *_pFile = VFS::instance().find(filename);
320  if (!_pFile)
321  {
322  ERROR("DynamicLinker: Dependency `" << filename << "' not found!");
323  if (!bDryRun)
324  {
325  if (loadBase)
326  {
327  m_Objects.remove(loadBase);
328  }
329  delete pSo;
330  }
331  delete pElf;
332  return false;
333  }
334  while (_pFile && _pFile->isSymlink())
335  _pFile = Symlink::fromFile(_pFile)->followLink();
336  if (!_pFile || !loadObject(_pFile, bDryRun))
337  {
338  ERROR(
339  "DynamicLinker: Dependency `" << filename
340  << "' failed to load!");
341  if (!bDryRun)
342  {
343  if (loadBase)
344  {
345  m_Objects.remove(loadBase);
346  }
347  delete pSo;
348  }
349  delete pElf;
350  return false;
351  }
352 
353  // Success! Add the filename of the library (NOT WITH LIBRARIES
354  // DIRECTORY) to the known loaded objects list.
355  if (!bDryRun)
356  m_LoadedObjects.insert(String(*it), reinterpret_cast<void *>(1));
357  }
358 
359  if (!bDryRun)
360  initPlt(pElf, loadBase);
361  else
362  delete pElf;
363 
364  return true;
365 }
366 
367 bool DynamicLinker::trap(uintptr_t address)
368 {
369  Elf *pElf = 0;
370  uintptr_t offset = 0;
371  uintptr_t buffer = 0;
372  size_t size = 0;
373 
374  if (address >= m_ProgramStart && address < m_ProgramStart + m_ProgramSize)
375  {
376  pElf = m_pProgramElf;
377  offset = 0;
378  buffer = m_ProgramBuffer;
379  size = m_ProgramSize;
380  }
381  else
382  {
383  for (Tree<uintptr_t, SharedObject *>::Iterator it = m_Objects.begin();
384  it != m_Objects.end(); it++)
385  {
386  SharedObject *pSo = it.value();
387 
388 // Totally pedantic
389 #ifdef ADDITIONAL_CHECKS
390  if (!pSo)
391  {
392  ERROR("A null shared object was in the object list.");
393  continue;
394  }
395 #endif
396 
397  if (address >= pSo->address && address < pSo->address + pSo->size)
398  {
399  pElf = pSo->elf;
400  offset = pSo->address;
401  buffer = pSo->buffer;
402  size = pSo->size;
403  break;
404  }
405  }
406  }
407 
408  if (!pElf)
409  return false;
410 
411  VirtualAddressSpace &va = Processor::information().getVirtualAddressSpace();
412 
413  uintptr_t v = address & ~(PhysicalMemoryManager::getPageSize() - 1);
414 
415  // Grab a physical page.
416  physical_uintptr_t p = PhysicalMemoryManager::instance().allocatePage();
417  // Map it into the address space.
418  if (!va.map(
419  p, reinterpret_cast<void *>(v),
421  {
422  WARNING("IMAGE: map() failed in ElfImage::trap(): vaddr: " << v);
423  return false;
424  }
425 
426  // Now that it's mapped, load the ELF region.
427  if (pElf->load(
428  reinterpret_cast<uint8_t *>(buffer), size, offset,
429  m_pProgramElf->getSymbolTable(), v,
430  v + PhysicalMemoryManager::getPageSize()) == false)
431  {
432  WARNING("LINKER: load() failed in DynamicLinker::trap()");
433  return false;
434  }
435 
436  return true;
437 }
438 
440 {
441  return m_pProgramElf->getSymbolTable()->lookup(name, m_pProgramElf);
442 }
443 
445 {
447 }
448 
450 {
451 }
452 
454  InterruptState &state, uintptr_t address, bool bIsWrite)
455 {
456  DynamicLinker *pL =
457  Processor::information().getCurrentThread()->getParent()->getLinker();
458  if (!pL)
459  return false;
460  return pL->trap(address);
461 }
462 
463 static bool init()
464 {
467  return true;
468 }
469 
470 static void destroy()
471 {
472 }
473 
474 MODULE_INFO("linker", &init, &destroy, "vfs");
File * find(const String &path, File *pStartNode=0)
Definition: VFS.cc:243
uintptr_t EXPORTED_PUBLIC lookup(const HashedStringView &name, Elf *pElf, Policy policy=LocalFirst, Binding *pBinding=0)
Definition: SymbolTable.cc:126
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)
Definition: linker/Elf.cc:1001
static PhysicalMemoryManager & instance()
bool loadProgram(File *pFile, bool bDryRun=false, bool bInterpreter=false, String *sInterpreter=0)
virtual bool trap(InterruptState &state, uintptr_t address, bool bIsWrite)
virtual physical_uintptr_t allocatePage(size_t pageConstraints=0)=0
virtual bool map(physical_uintptr_t physicalAddress, void *virtualAddress, size_t flags)=0
void insert(const String &key, const T &value)
Definition: RadixTree.h:347
Definition: String.h:49
static ProcessorInformation & information()
Definition: Processor.cc:45
bool allocate(uint8_t *pBuffer, size_t length, uintptr_t &loadBase, SymbolTable *pSymtab=0, bool bAllocate=true, size_t *pSize=0)
Definition: linker/Elf.cc:837
static VFS & instance()
Definition: VFS.cc:56
void unmap(MemoryMappedObject *pObj)
bool createNeededOnly(uint8_t *pBuffer, size_t length)
Definition: linker/Elf.cc:174
virtual bool isSymlink()
Definition: File.cc:431
uintptr_t registerSyscall(Function_t function, SyscallCallback func)
static PageFaultHandler & instance()
#define WARNING(text)
Definition: Log.h:78
Result< T, bool > lookup(const String &key) const
Definition: RadixTree.h:462
uintptr_t resolvePltSymbol(uintptr_t libraryId, uintptr_t symIdx)
Memory-mapped file interface.
#define NOTICE(text)
Definition: Log.h:74
static MemoryMapManager & instance()
Iterator begin()
Definition: List.h:123
bool loadObject(File *pFile, bool bDryRun=false)
static KernelCoreSyscallManager & instance()
bool create(uint8_t *pBuffer, size_t length)
Definition: linker/Elf.cc:313
static uintptr_t resolvePlt(SyscallState &state)
MemoryMappedObject * mapFile(File *pFile, uintptr_t &address, size_t length, MemoryMappedObject::Permissions perms, size_t offset=0, bool bCopyOnWrite=true)
void registerHandler(MemoryTrapHandler *pHandler)
String & getInterpreter()
Definition: linker/Elf.cc:1398
String getName() const
Definition: File.cc:411
Definition: Elf.h:201
#define ERROR(text)
Definition: Log.h:82
uintptr_t resolve(String name)
bool trap(uintptr_t address)
An iterator applicable for many data structures.
Definition: Iterator.h:180
List< char * > & neededLibraries()
Definition: linker/Elf.cc:1393
Definition: File.h:66
Iterator end()
Definition: List.h:135
void initPlt(Elf *pElf, uintptr_t value)