Determine the architecture of an ELF by looking at the file header instead of the...
[dyninst.git] / symtabAPI / src / SymtabReader.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "symtabAPI/h/SymtabReader.h"
32 #include "symtabAPI/h/Symtab.h"
33 #include "symtabAPI/h/Symbol.h"
34 #include "symtabAPI/h/Function.h"
35
36 #include "symtabAPI/src/Object.h"
37 #include <queue>
38 #include <iostream>
39 using namespace std;
40
41 #include <sstream>
42 using std::stringstream;
43
44 using namespace Dyninst;
45 using namespace SymtabAPI;
46
47 SymtabReader::SymtabReader(std::string file_) :
48    symtab(NULL),
49    ref_count(1),
50    ownsSymtab(true)
51 {
52   // We'd throw, but...
53   (void)Symtab::openFile(symtab, file_);
54 }
55
56 SymtabReader::SymtabReader(const char *buffer, unsigned long size) :
57    symtab(NULL),
58    ref_count(1),
59    ownsSymtab(true)
60 {
61    stringstream memName;
62    memName << "memory_" << (unsigned long)(buffer) << "_" << size;
63    Symtab::openFile(symtab, const_cast<char *>(buffer), 
64                     size, memName.str());
65 }
66
67 SymtabReader::SymtabReader(Symtab *s) :
68     symtab(s),
69     ref_count(1),
70     ownsSymtab(false)
71 {}
72
73 SymtabReader::~SymtabReader()
74 {
75    if (symtab && ownsSymtab)
76       Symtab::closeSymtab(symtab);
77    symtab = NULL;
78 }
79
80
81 #define DEFN_SYMBOL_T(name) Symbol_t name; name.v1 = name.v2 = NULL; name.i1 = name.i2 = 0
82
83 Symbol_t SymtabReader::getSymbolByName(std::string symname)
84 {
85    assert(symtab);
86    DEFN_SYMBOL_T(ret);
87
88    std::vector<Symbol *> syms;
89    bool result = symtab->findSymbol(syms, symname);
90    if (!result || syms.empty()) {
91       return ret;
92    }
93
94    ret.v1 = symtab;
95    ret.v2 = syms[0];
96    return ret;
97 }
98
99 Symbol_t SymtabReader::getContainingSymbol(Dyninst::Offset offset)
100 {
101    assert(symtab);
102    DEFN_SYMBOL_T(ret);
103
104    Function *f = NULL;
105    bool result = symtab->getContainingFunction(offset, f);
106    if (!result || !f) {
107       return ret;
108    }
109
110    ret.v1 = symtab;
111    ret.v2 = f->getFirstSymbol();
112    return ret;
113 }
114
115 std::string SymtabReader::getInterpreterName()
116 {
117    assert(symtab);
118    const char *interp = NULL;
119    interp = symtab->getInterpreterName();
120
121    if (!interp)
122       return std::string();
123    return std::string(interp);
124 }
125
126 unsigned SymtabReader::getAddressWidth()
127 {
128    assert(symtab);
129    return symtab->getAddressWidth();
130 }
131    
132 bool SymtabReader::getABIVersion(int &major, int &minor) const
133 {
134    assert(symtab);
135    return symtab->getABIVersion(major, minor);
136 }
137
138 bool SymtabReader::isBigEndianDataEncoding() const
139 {
140    assert(symtab);
141    return symtab->isBigEndianDataEncoding();
142 }
143
144 Architecture SymtabReader::getArchitecture() const
145 {
146     return symtab->getArchitecture();
147 }
148
149 unsigned SymtabReader::numSegments()
150 {
151    buildSegments();
152    return segments.size();
153 }
154
155 bool SymtabReader::getSegment(unsigned num, SymSegment &seg)
156 {
157    buildSegments();
158    if (num >= segments.size()) return false;
159    seg = segments[num];
160
161    return true;
162 }
163
164 void SymtabReader::buildSegments() {
165    if (!segments.empty()) return;
166
167    // We want ELF segments; contiguous areas of the 
168    // binary loaded into memory. 
169    symtab->getSegmentsSymReader(segments);
170 }
171
172
173 Dyninst::Offset SymtabReader::getSymbolOffset(const Symbol_t &sym)
174 {
175    assert(sym.v2);
176    Symbol *symbol = (Symbol *) sym.v2;
177    return symbol->getOffset();
178 }
179
180 Dyninst::Offset SymtabReader::getSymbolTOC(const Symbol_t &sym)
181 {
182    assert(sym.v2);
183    Symbol *symbol = (Symbol *) sym.v2;
184    return symbol->getSymtab()->getTOCoffset(symbol->getOffset());
185 }
186
187 std::string SymtabReader::getSymbolName(const Symbol_t &sym)
188 {
189    assert(sym.v2);
190    Symbol *symbol = (Symbol *) sym.v2;
191    return symbol->getMangledName();
192 }
193
194 std::string SymtabReader::getDemangledName(const Symbol_t &sym) {
195    assert(sym.v2);
196    Symbol *symbol = (Symbol *) sym.v2;
197    return symbol->getTypedName();
198 }
199
200 unsigned long SymtabReader::getSymbolSize(const Symbol_t &sym)
201 {
202    assert(sym.v2);
203    Symbol *symbol = (Symbol *) sym.v2;
204    return symbol->getSize();
205 }
206
207 bool SymtabReader::isValidSymbol(const Symbol_t &sym)
208 {
209    return (sym.v1 != NULL) && (sym.v2 != NULL);
210 }
211
212 Dyninst::Offset SymtabReader::imageOffset()
213 {
214    return symtab->imageOffset();
215 }
216
217 Dyninst::Offset SymtabReader::dataOffset()
218 {
219    return symtab->dataOffset();
220 }
221
222 Section_t SymtabReader::getSectionByName(std::string name)
223 {
224    Region *region;
225    Section_t ret;
226    ret.v1 = NULL;
227    bool result = symtab->findRegion(region, name);
228    if (!result) {
229       return ret;
230    }
231    ret.v1 = (void *) region;
232    return ret;
233 }
234
235 Section_t SymtabReader::getSectionByAddress(Dyninst::Address addr)
236 {
237    Region *region = symtab->findEnclosingRegion(addr);
238    Section_t ret;
239    ret.v1 = (void *) region;
240    return ret;
241 }
242
243 Dyninst::Address SymtabReader::getSectionAddress(Section_t sec)
244 {
245    Region *region = (Region *) sec.v1;
246    assert(region);
247    return region->getMemOffset();
248 }
249
250 std::string SymtabReader::getSectionName(Section_t sec)
251 {
252    Region *region = (Region *) sec.v1;
253    assert(region);
254    return region->getRegionName();
255 }
256
257 bool SymtabReader::isValidSection(Section_t sec)
258 {
259    return (sec.v1 != NULL);
260 }
261
262 void *SymtabReader::getElfHandle()
263 {
264 #if defined(os_linux) || defined(os_bg) || defined(os_freebsd) || defined(os_vxworks)
265    Object *obj = symtab->getObject();
266    return obj->getElfHandle();
267 #else
268    return NULL;
269 #endif
270 }
271
272 SymtabReaderFactory::SymtabReaderFactory()
273 {
274 }
275
276 SymtabReaderFactory::~SymtabReaderFactory()
277 {
278 }
279
280 SymReader *SymtabReaderFactory::openSymbolReader(std::string pathname)
281 {
282    std::map<std::string, SymReader *>::iterator i = open_syms.find(pathname);
283    if (i != open_syms.end()) {
284       SymtabReader *symtabreader = dynamic_cast<SymtabReader *>(i->second);
285       symtabreader->ref_count++;
286       return symtabreader;
287    }
288    SymtabReader *symtabreader = new SymtabReader(pathname);
289    if (!symtabreader) { 
290       return NULL;
291    }
292    if(!symtabreader->symtab) {
293      delete symtabreader;
294      return NULL;
295    }
296    open_syms[pathname] = symtabreader;
297
298    return symtabreader;
299 }
300
301 SymReader *SymtabReaderFactory::openSymbolReader(const char *buffer, unsigned long size)
302 {
303    SymtabReader *symtabreader = new SymtabReader(buffer, size);
304    if (!symtabreader) 
305       return NULL;
306    return symtabreader;
307 }
308
309 bool SymtabReaderFactory::closeSymbolReader(SymReader *sr)
310 {
311    SymtabReader *symreader = static_cast<SymtabReader *>(sr);
312    assert(symreader->ref_count >= 1);
313    symreader->ref_count--;
314    if (symreader->ref_count == 0) {
315      // We need to remove this from the big map, but we don't 
316      // store the path. So crawl and look. 
317      std::queue<std::string> toDelete;
318      std::map<std::string, SymReader *>::iterator i;
319      for (i = open_syms.begin(); i != open_syms.end(); ++i) {
320        if (i->second == symreader) {
321          toDelete.push(i->first);
322        }
323      }
324      while (!toDelete.empty()) {
325        open_syms.erase(toDelete.front());
326        toDelete.pop();
327      }
328
329       delete symreader;
330    }
331    return true;
332 }
333
334 SymbolReaderFactory *Dyninst::SymtabAPI::getSymtabReaderFactory()
335 {
336    static SymtabReaderFactory *fact = NULL;
337    if (!fact)
338       fact = new SymtabReaderFactory();
339    return static_cast<SymbolReaderFactory *>(fact);
340 }