Update copyright to LGPL on all files
[dyninst.git] / symtabAPI / src / AddrLookup.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 #include "symtabAPI/h/Symtab.h"
33 #include "symtabAPI/h/Symbol.h"
34 #include "symtabAPI/h/AddrLookup.h"
35
36 #include "symtabAPI/src/addrtranslate.h"
37
38 #include <vector>
39 #include <algorithm>
40 #include <string>
41
42 using namespace Dyninst;
43 using namespace Dyninst::SymtabAPI;
44 using namespace std;
45
46 dyn_hash_map<string, std::vector<Symbol *> > AddressLookup::syms;
47
48 AddressLookup *AddressLookup::createAddressLookup(PID pid, ProcessReader *reader)
49 {
50    AddressTranslate *trans = AddressTranslate::createAddressTranslator(pid, reader);
51
52    if (!trans)
53       return NULL;
54    AddressLookup *ar = new AddressLookup(trans);
55
56    if (!ar)
57       return NULL;
58    return ar;
59 }
60
61 AddressLookup *AddressLookup::createAddressLookup(ProcessReader *reader)
62 {
63    AddressTranslate *trans = AddressTranslate::createAddressTranslator(reader);
64    if (!trans) {
65       return NULL;
66    }
67    AddressLookup *ar = new AddressLookup(trans);
68    if (!ar) {
69       return NULL;
70    }
71    return ar;
72 }
73
74 AddressLookup *AddressLookup::createAddressLookup(const std::vector<LoadedLibrary> &name_addrs)
75 {
76    AddressTranslate *trans = AddressTranslate::createAddressTranslator(name_addrs);
77    if (!trans)
78       return NULL;
79    AddressLookup *ar = new AddressLookup(trans);
80    if (!ar)
81       return NULL;
82    return ar;
83 }
84
85 bool AddressLookup::getAddress(Symtab *tab, Offset off, Address &addr)
86 {
87    LoadedLib *ll = translator->getLoadedLib(tab);
88    if (!ll)
89       return false;
90    addr = ll->offToAddress(off);
91    return true;
92 }
93
94 bool AddressLookup::getAddress(Symtab *tab, Symbol *sym, Address &addr)
95 {
96    LoadedLib *ll = translator->getLoadedLib(tab);
97    if (!ll)
98       return false;
99    addr = ll->symToAddress(sym);
100    return true;
101 }
102
103 bool sort_by_addr(const Symbol* a, const Symbol* b)
104 {
105    return a->getAddr() < b->getAddr();
106 }
107
108 vector<Symbol *> *AddressLookup::getSymsVector(LoadedLib *lib)
109 {
110    string str = lib->getName();
111    if (syms.find(str) != syms.end()) {
112       return &(syms[str]);
113    }
114    
115    Symtab *tab = lib->getSymtab();
116    if (!tab) {
117       return NULL;
118    }
119
120    vector<Symbol *> &symbols = syms[str];
121    tab->getAllSymbolsByType(symbols, Symbol::ST_UNKNOWN);
122    std::sort(symbols.begin(), symbols.end(), sort_by_addr);
123
124    return &(syms[str]);
125 }
126
127 bool AddressLookup::getOffset(Address addr, Symtab* &tab, Offset &off)
128 {
129    LoadedLib *lib;
130    bool result;
131
132    result = translator->getLibAtAddress(addr, lib);
133    if (!result || !lib) {
134       return false;
135    }
136
137    off = lib->addrToOffset(addr);
138    tab = lib->getSymtab();
139    return true;
140 }
141
142 bool AddressLookup::getSymbol(Address addr, Symbol* &sym, Symtab* &tab, bool close)
143 {
144    LoadedLib *lib;
145    bool result;
146
147    result = translator->getLibAtAddress(addr, lib);
148    if (!result || !lib) {
149       return false;
150    }
151
152    tab = lib->getSymtab();
153    vector<Symbol *> *symbols = getSymsVector(lib);
154    if (!symbols) {
155       return false;
156    }
157    
158    unsigned min = 0;
159    unsigned max = symbols->size();
160    unsigned mid, last_mid;
161    last_mid = max+1;
162
163    Symbol *closest = NULL;
164    unsigned long closest_dist = 0;
165
166    addr -= lib->addrToOffset(addr);
167
168    for (;;) {
169       mid = (min + max) / 2;
170       if (mid == last_mid)
171          break;
172       last_mid = mid;
173       
174       Offset cur_off = (*symbols)[mid]->getAddr();
175       
176       if (addr == cur_off) {
177          sym = (*symbols)[mid];
178          return true;
179       }
180       if (addr < cur_off) {
181          max = mid;
182          continue;
183       }
184       if (close && (!closest || closest_dist > (cur_off - addr)))
185       {
186          closest_dist = cur_off - addr;
187          closest = (*symbols)[mid];
188       }
189       if (addr > cur_off) {
190          min = mid;
191          continue;
192       }
193    }
194
195    if (close && closest)
196    {
197       sym = (*symbols)[mid];
198       return true;
199    }
200
201    return false;
202 }
203
204 bool AddressLookup::getAllSymtabs(std::vector<Symtab *> &tabs)
205 {
206    vector<LoadedLib *> libs;
207    bool result = translator->getLibs(libs);
208    if (!result)
209       return false;
210
211    for (unsigned i=0; i<libs.size(); i++)
212    {
213       Symtab *symt = libs[i]->getSymtab();
214       if (symt)
215          tabs.push_back(symt);
216    }
217
218    return true;
219 }
220
221 bool AddressLookup::getLoadAddress(Symtab* sym, Address &load_addr)
222 {
223    LoadedLib *ll = translator->getLoadedLib(sym);
224    if (!ll)
225       return false;
226    load_addr = ll->getCodeLoadAddr();
227    return true;
228 }
229
230 bool AddressLookup::getDataLoadAddress(Symtab* sym, Address &load_addr)
231 {
232    LoadedLib *ll = translator->getLoadedLib(sym);
233    if (!ll)
234       return false;
235    load_addr = ll->getDataLoadAddr();
236    return true;
237 }
238
239 bool AddressLookup::getLoadAddresses(std::vector<LoadedLibrary> &name_addrs)
240 {
241    vector<LoadedLib *> libs;
242    bool result = translator->getLibs(libs);
243    if (!result)
244       return false;
245
246    for (unsigned i=0; i<libs.size(); i++)
247    {
248       LoadedLibrary l;
249       libs[i]->getOutputs(l.name, l.codeAddr, l.dataAddr);
250       name_addrs.push_back(l);
251    }
252
253    return true;
254 }
255
256 Address AddressLookup::getLibraryTrapAddrSysV()
257 {
258    return translator->getLibraryTrapAddrSysV();
259 }
260
261 AddressLookup::AddressLookup(AddressTranslate *at) :
262    translator(at)
263 {
264 }
265
266 AddressLookup::~AddressLookup()
267 {
268 }
269
270 bool AddressLookup::refresh()
271 {
272    return translator->refresh();
273 }
274
275 bool AddressLookup::getExecutable(LoadedLibrary &lib)
276 {
277 #if !defined(os_linux)
278    return false;
279 #endif
280    LoadedLib *llib = translator->getExecutable();
281    if (!llib)
282       return false;
283    llib->getOutputs(lib.name, lib.codeAddr, lib.dataAddr);
284    return true;
285 }