1) Cmake support for PPC64LE builds
[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 int SymtabReader::getABIVersion() const
133 {
134    assert(symtab);
135    return symtab->getABIVersion();
136 }
137
138 bool SymtabReader::isBigEndianDataEncoding() const
139 {
140    assert(symtab);
141    return symtab->isBigEndianDataEncoding();
142 }
143
144 unsigned SymtabReader::numSegments()
145 {
146    buildSegments();
147    return segments.size();
148 }
149
150 bool SymtabReader::getSegment(unsigned num, SymSegment &seg)
151 {
152    buildSegments();
153    if (num >= segments.size()) return false;
154    seg = segments[num];
155
156    return true;
157 }
158
159 void SymtabReader::buildSegments() {
160    if (!segments.empty()) return;
161
162    // We want ELF segments; contiguous areas of the 
163    // binary loaded into memory. 
164    symtab->getSegmentsSymReader(segments);
165 }
166
167
168 Dyninst::Offset SymtabReader::getSymbolOffset(const Symbol_t &sym)
169 {
170    assert(sym.v2);
171    Symbol *symbol = (Symbol *) sym.v2;
172    return symbol->getOffset();
173 }
174
175 Dyninst::Offset SymtabReader::getSymbolTOC(const Symbol_t &sym)
176 {
177    assert(sym.v2);
178    Symbol *symbol = (Symbol *) sym.v2;
179    return symbol->getSymtab()->getTOCoffset(symbol->getOffset());
180 }
181
182 std::string SymtabReader::getSymbolName(const Symbol_t &sym)
183 {
184    assert(sym.v2);
185    Symbol *symbol = (Symbol *) sym.v2;
186    return symbol->getMangledName();
187 }
188
189 std::string SymtabReader::getDemangledName(const Symbol_t &sym) {
190    assert(sym.v2);
191    Symbol *symbol = (Symbol *) sym.v2;
192    return symbol->getTypedName();
193 }
194
195 unsigned long SymtabReader::getSymbolSize(const Symbol_t &sym)
196 {
197    assert(sym.v2);
198    Symbol *symbol = (Symbol *) sym.v2;
199    return symbol->getSize();
200 }
201
202 bool SymtabReader::isValidSymbol(const Symbol_t &sym)
203 {
204    return (sym.v1 != NULL) && (sym.v2 != NULL);
205 }
206
207 Dyninst::Offset SymtabReader::imageOffset()
208 {
209    return symtab->imageOffset();
210 }
211
212 Dyninst::Offset SymtabReader::dataOffset()
213 {
214    return symtab->dataOffset();
215 }
216
217 Section_t SymtabReader::getSectionByName(std::string name)
218 {
219    Region *region;
220    Section_t ret;
221    ret.v1 = NULL;
222    bool result = symtab->findRegion(region, name);
223    if (!result) {
224       return ret;
225    }
226    ret.v1 = (void *) region;
227    return ret;
228 }
229
230 Section_t SymtabReader::getSectionByAddress(Dyninst::Address addr)
231 {
232    Region *region = symtab->findEnclosingRegion(addr);
233    Section_t ret;
234    ret.v1 = (void *) region;
235    return ret;
236 }
237
238 Dyninst::Address SymtabReader::getSectionAddress(Section_t sec)
239 {
240    Region *region = (Region *) sec.v1;
241    assert(region);
242    return region->getMemOffset();
243 }
244
245 std::string SymtabReader::getSectionName(Section_t sec)
246 {
247    Region *region = (Region *) sec.v1;
248    assert(region);
249    return region->getRegionName();
250 }
251
252 bool SymtabReader::isValidSection(Section_t sec)
253 {
254    return (sec.v1 != NULL);
255 }
256
257 void *SymtabReader::getElfHandle()
258 {
259 #if defined(os_linux) || defined(os_bg) || defined(os_freebsd) || defined(os_vxworks)
260    Object *obj = symtab->getObject();
261    return obj->getElfHandle();
262 #else
263    return NULL;
264 #endif
265 }
266
267 SymtabReaderFactory::SymtabReaderFactory()
268 {
269 }
270
271 SymtabReaderFactory::~SymtabReaderFactory()
272 {
273 }
274
275 SymReader *SymtabReaderFactory::openSymbolReader(std::string pathname)
276 {
277    std::map<std::string, SymReader *>::iterator i = open_syms.find(pathname);
278    if (i != open_syms.end()) {
279       SymtabReader *symtabreader = dynamic_cast<SymtabReader *>(i->second);
280       symtabreader->ref_count++;
281       return symtabreader;
282    }
283    SymtabReader *symtabreader = new SymtabReader(pathname);
284    if (!symtabreader) { 
285       return NULL;
286    }
287    if(!symtabreader->symtab) {
288      delete symtabreader;
289      return NULL;
290    }
291    open_syms[pathname] = symtabreader;
292
293    return symtabreader;
294 }
295
296 SymReader *SymtabReaderFactory::openSymbolReader(const char *buffer, unsigned long size)
297 {
298    SymtabReader *symtabreader = new SymtabReader(buffer, size);
299    if (!symtabreader) 
300       return NULL;
301    return symtabreader;
302 }
303
304 bool SymtabReaderFactory::closeSymbolReader(SymReader *sr)
305 {
306    SymtabReader *symreader = static_cast<SymtabReader *>(sr);
307    assert(symreader->ref_count >= 1);
308    symreader->ref_count--;
309    if (symreader->ref_count == 0) {
310      // We need to remove this from the big map, but we don't 
311      // store the path. So crawl and look. 
312      std::queue<std::string> toDelete;
313      std::map<std::string, SymReader *>::iterator i;
314      for (i = open_syms.begin(); i != open_syms.end(); ++i) {
315        if (i->second == symreader) {
316          toDelete.push(i->first);
317        }
318      }
319      while (!toDelete.empty()) {
320        open_syms.erase(toDelete.front());
321        toDelete.pop();
322      }
323
324       delete symreader;
325    }
326    return true;
327 }
328
329 SymbolReaderFactory *Dyninst::SymtabAPI::getSymtabReaderFactory()
330 {
331    static SymtabReaderFactory *fact = NULL;
332    if (!fact)
333       fact = new SymtabReaderFactory();
334    return static_cast<SymbolReaderFactory *>(fact);
335 }