arch-power: Add multi-mode support
[gem5.git] / src / base / loader / symtab.hh
1 /*
2 * Copyright (c) 2002-2005 The Regents of The University of Michigan
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #ifndef __BASE_LOADER_SYMTAB_HH__
30 #define __BASE_LOADER_SYMTAB_HH__
31
32 #include <functional>
33 #include <iosfwd>
34 #include <map>
35 #include <memory>
36 #include <string>
37 #include <vector>
38
39 #include "base/types.hh"
40 #include "sim/serialize.hh"
41
42 namespace Loader
43 {
44
45 struct Symbol
46 {
47 enum class Binding {
48 Global,
49 Local,
50 Weak
51 };
52
53 Binding binding;
54 std::string name;
55 Addr address;
56 };
57
58 class SymbolTable
59 {
60 public:
61 typedef std::shared_ptr<SymbolTable> SymbolTablePtr;
62
63 private:
64 typedef std::vector<Symbol> SymbolVector;
65 // Map addresses to an index into the symbol vector.
66 typedef std::multimap<Addr, int> AddrMap;
67 // Map a symbol name to an index into the symbol vector.
68 typedef std::map<std::string, int> NameMap;
69
70 SymbolVector symbols;
71 AddrMap addrMap;
72 NameMap nameMap;
73
74 bool
75 upperBound(Addr addr, AddrMap::const_iterator &iter) const
76 {
77 // find first key *larger* than desired address
78 iter = addrMap.upper_bound(addr);
79
80 // if very first key is larger, we're out of luck
81 if (iter == addrMap.begin())
82 return false;
83
84 return true;
85 }
86
87 typedef std::function<void(SymbolTable &symtab,
88 const Symbol &symbol)> SymTabOp;
89 SymbolTablePtr
90 operate(SymTabOp op) const
91 {
92 SymbolTablePtr symtab(new SymbolTable);
93 for (const auto &symbol: symbols)
94 op(*symtab, symbol);
95 return symtab;
96 }
97
98 typedef std::function<bool(const Symbol &symbol)> SymTabFilter;
99 SymbolTablePtr
100 filter(SymTabFilter filter) const
101 {
102 SymTabOp apply_filter =
103 [filter](SymbolTable &symtab, const Symbol &symbol) {
104 if (filter(symbol)) {
105 symtab.insert(symbol);
106 }
107 };
108 return operate(apply_filter);
109 }
110
111 SymbolTablePtr
112 filterByBinding(Symbol::Binding binding) const
113 {
114 auto filt = [binding](const Symbol &symbol) {
115 return symbol.binding == binding;
116 };
117 return filter(filt);
118 }
119
120 public:
121 typedef SymbolVector::iterator iterator;
122 typedef SymbolVector::const_iterator const_iterator;
123
124 const_iterator begin() const { return symbols.begin(); }
125 const_iterator end() const { return symbols.end(); }
126
127 void clear();
128 // Insert either a single symbol or the contents of an entire symbol table
129 // into this one.
130 bool insert(const Symbol &symbol);
131 bool insert(const SymbolTable &other);
132 bool empty() const { return symbols.empty(); }
133
134 SymbolTablePtr
135 offset(Addr by) const
136 {
137 SymTabOp op = [by](SymbolTable &symtab, const Symbol &symbol) {
138 Symbol sym = symbol;
139 sym.address += by;
140 symtab.insert(sym);
141 };
142 return operate(op);
143 }
144
145 SymbolTablePtr
146 mask(Addr m) const
147 {
148 SymTabOp op = [m](SymbolTable &symtab, const Symbol &symbol) {
149 Symbol sym = symbol;
150 sym.address &= m;
151 symtab.insert(sym);
152 };
153 return operate(op);
154 }
155
156 SymbolTablePtr
157 globals() const
158 {
159 return filterByBinding(Symbol::Binding::Global);
160 }
161
162 SymbolTablePtr
163 locals() const
164 {
165 return filterByBinding(Symbol::Binding::Local);
166 }
167
168 SymbolTablePtr
169 weaks() const
170 {
171 return filterByBinding(Symbol::Binding::Weak);
172 }
173
174 void serialize(const std::string &base, CheckpointOut &cp) const;
175 void unserialize(const std::string &base, CheckpointIn &cp,
176 Symbol::Binding default_binding=Symbol::Binding::Global);
177
178 const_iterator
179 find(Addr address) const
180 {
181 AddrMap::const_iterator i = addrMap.find(address);
182 if (i == addrMap.end())
183 return end();
184
185 // There are potentially multiple symbols that map to the same
186 // address. For simplicity, just return the first one.
187 return symbols.begin() + i->second;
188 }
189
190 const_iterator
191 find(const std::string &name) const
192 {
193 NameMap::const_iterator i = nameMap.find(name);
194 if (i == nameMap.end())
195 return end();
196
197 return symbols.begin() + i->second;
198 }
199
200 /// Find the nearest symbol equal to or less than the supplied
201 /// address (e.g., the label for the enclosing function).
202 /// @param addr The address to look up.
203 /// @param nextaddr Address of following symbol (for
204 /// determining valid range of symbol).
205 /// @retval A const_iterator which points to the symbol if found, or end.
206 const_iterator
207 findNearest(Addr addr, Addr &nextaddr) const
208 {
209 AddrMap::const_iterator i = addrMap.end();
210 if (!upperBound(addr, i))
211 return end();
212
213 nextaddr = i->first;
214 --i;
215 return symbols.begin() + i->second;
216 }
217
218 /// Overload for findNearestSymbol() for callers who don't care
219 /// about nextaddr.
220 const_iterator
221 findNearest(Addr addr) const
222 {
223 AddrMap::const_iterator i = addrMap.end();
224 if (!upperBound(addr, i))
225 return end();
226
227 --i;
228 return symbols.begin() + i->second;
229 }
230 };
231
232 /// Global unified debugging symbol table (for target). Conceptually
233 /// there should be one of these per System object for full system,
234 /// and per Process object for non-full-system, but so far one big
235 /// global one has worked well enough.
236 extern SymbolTable debugSymbolTable;
237
238 } // namespace Loader
239
240 #endif // __BASE_LOADER_SYMTAB_HH__