The Pedigree Project  0.1
SymbolTable.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 "pedigree/kernel/linker/SymbolTable.h"
21 #include "pedigree/kernel/LockGuard.h"
22 #include "pedigree/kernel/utilities/Iterator.h"
23 
24 #ifdef THREADS
25 #define RAII_LOCK LockGuard<Mutex> guard(m_Lock)
26 #else
27 #define RAII_LOCK
28 #endif
29 
31  : m_LocalSymbols(), m_GlobalSymbols(), m_WeakSymbols(),
32  m_pOriginatingElf(pElf)
33 {
34 }
35 
37 {
38 }
39 
40 void SymbolTable::copyTable(Elf *pNewElf, const SymbolTable &newSymtab)
41 {
42  RAII_LOCK;
43 
44  // Safe to do this, all members are SharedPointers and will be copy
45  // constructed by these operations.
46  m_LocalSymbols = newSymtab.m_LocalSymbols;
47  m_GlobalSymbols = newSymtab.m_GlobalSymbols;
48  m_WeakSymbols = newSymtab.m_WeakSymbols;
49 }
50 
52  const String &name, Binding binding, Elf *pParent, uintptr_t value)
53 {
54  RAII_LOCK;
55 
56  doInsert(name, binding, pParent, value);
57 }
58 
60  SymbolTable *pOther, const String &name, Binding binding, Elf *pParent,
61  uintptr_t value)
62 {
63  RAII_LOCK;
64 #ifdef THREADS
65  LockGuard<Mutex> guard2(pOther->m_Lock);
66 #endif
67 
68  SharedPointer<Symbol> ptr = doInsert(name, binding, pParent, value);
69  if (pOther)
70  pOther->insertShared(name, ptr);
71 }
72 
74  size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
75 {
76  auto tree = getOrInsertTree(localElf);
77  tree->reserve(numLocal);
78 
79  tree = getOrInsertTree(localElf, Global);
80  tree->reserve(numGlobal);
81 
82  tree = getOrInsertTree(localElf, Weak);
83  tree->reserve(numWeak);
84 }
85 
87  size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
88 {
89  auto tree = getOrInsertTree(localElf, Global);
90  tree->reserve(tree->count() + numGlobal);
91 
92  tree = getOrInsertTree(localElf, Weak);
93  tree->reserve(tree->count() + numWeak);
94 
95  tree = getOrInsertTree(localElf);
96  tree->reserve(tree->count() + numLocal);
97 }
98 
100  const String &name, Binding binding, Elf *pParent, uintptr_t value)
101 {
102  Symbol *pSymbol = new Symbol(pParent, binding, value);
103  SharedPointer<Symbol> newSymbol(pSymbol);
104 
105  insertShared(name, newSymbol);
106  return newSymbol;
107 }
108 
111 {
112  auto tree = getOrInsertTree(symbol->getParent(), symbol->getBinding());
113  tree->insert(name, symbol);
114 }
115 
116 void SymbolTable::eraseByElf(Elf *pParent)
117 {
118  RAII_LOCK;
119 
120  // Will wipe out recursively by destroying the SharedPointers within.
121  m_LocalSymbols.remove(pParent);
122  m_GlobalSymbols.remove(pParent);
123  m_WeakSymbols.remove(pParent);
124 }
125 
127  const HashedStringView &name, Elf *pElf, Policy policy, Binding *pBinding)
128 {
129  RAII_LOCK;
130 
131  // safe empty SharedPointer we can use for lookupRef()'s failed result
132  static SharedPointer<symbolTree_t> failedLookup;
133 
134  uintptr_t lookupResult = 0;
135 
136  // Local to the ELF file itself.
137  if (policy != NotOriginatingElf)
138  {
139  const SharedPointer<symbolTree_t> &symbolTree = m_LocalSymbols.lookupRef(pElf, failedLookup);
140  if (symbolTree)
141  {
142  symbolTree_t::LookupResult result = symbolTree->lookup(name);
143  if (result.hasValue())
144  {
145  lookupResult = result.value()->getValue();
146  }
147  }
148  }
149 
150  // Global lookup across all ELFs that expose global symbols.
151  if (!lookupResult)
152  {
153  for (parentedSymbolTree_t::Iterator it = m_GlobalSymbols.begin();
154  it != m_GlobalSymbols.end();
155  ++it)
156  {
157  symbolTree_t::LookupResult result = it.value(failedLookup)->lookup(name);
158  if (result.hasValue())
159  {
160  lookupResult = result.value()->getValue();
161  break;
162  }
163  }
164  }
165 
166  // Finally we try and find a usable weak symbol.
167  if (!lookupResult)
168  {
169  for (parentedSymbolTree_t::Iterator it = m_WeakSymbols.begin();
170  it != m_WeakSymbols.end();
171  ++it)
172  {
173  symbolTree_t::LookupResult result = it.value(failedLookup)->lookup(name);
174  if (result.hasValue())
175  {
176  lookupResult = result.value()->getValue();
177  break;
178  }
179  }
180  }
181 
182  // NOTICE("SymbolTable::lookup(" << name << ", " << pElf->getName() << ")
183  // ==> " << Hex << lookupResult);
184 
185  return lookupResult;
186 }
187 
189 {
190  // safe empty SharedPointer we can use for lookupRef()'s failed result
192 
194  switch (table)
195  {
196  case Local:
197  tree = &m_LocalSymbols;
198  break;
199  case Global:
200  tree = &m_GlobalSymbols;
201  break;
202  default:
203  tree = &m_WeakSymbols;
204  break;
205  }
206 
207  auto symbolTree = tree->lookupRef(p, v);
208  if (symbolTree)
209  {
210  return symbolTree.get();
211  }
212 
213  auto newTree = SharedPointer<symbolTree_t>::allocate();
214  auto result = newTree.get();
215  tree->insert(p, pedigree_std::move(newTree));
216  return result;
217 }
Iterator end()
Definition: Tree.h:348
const E & lookupRef(const K &key, const E &failed=E()) const
Definition: Tree.h:209
uintptr_t EXPORTED_PUBLIC lookup(const HashedStringView &name, Elf *pElf, Policy policy=LocalFirst, Binding *pBinding=0)
Definition: SymbolTable.cc:126
void preallocateAdditional(size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
Definition: SymbolTable.cc:86
Definition: String.h:49
Definition: Result.h:36
symbolTree_t * getOrInsertTree(Elf *, Binding table=Local)
Definition: SymbolTable.cc:188
void insert(const K &key, const E &value)
Definition: Tree.h:173
void insert(const String &name, Binding binding, Elf *pParent, uintptr_t value)
Definition: SymbolTable.cc:51
Iterator begin()
Definition: Tree.h:326
A key/value dictionary.
Definition: Tree.h:33
bool insert(const K &k, const V &v)
Definition: HashTable.h:264
void insertShared(const String &name, SharedPointer< Symbol > &symbol)
Definition: SymbolTable.cc:109
LookupResult lookup(const K &k) const
Definition: HashTable.h:200
Definition: Elf.h:201
void copyTable(Elf *pNewElf, const SymbolTable &newSymtab)
Definition: SymbolTable.cc:40
SymbolTable(Elf *pElf)
Definition: SymbolTable.cc:30
void remove(const K &key)
Definition: Tree.h:242
void insertMultiple(SymbolTable *pOther, const String &name, Binding binding, Elf *pParent, uintptr_t value)
Definition: SymbolTable.cc:59
An iterator applicable for many data structures.
Definition: Iterator.h:180
SharedPointer< Symbol > doInsert(const String &name, Binding binding, Elf *pParent, uintptr_t value)
Definition: SymbolTable.cc:99
void preallocate(size_t numGlobal, size_t numWeak, Elf *localElf, size_t numLocal)
Definition: SymbolTable.cc:73
static SharedPointer< T > allocate(Args...)