Changed a vector to a set to improve lookup speed
[dyninst.git] / symtabAPI / src / Symtab-edit.C
1 /*
2  * Copyright (c) 1996-2011 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 <stdio.h>
33 #include <stdlib.h>
34 #include <assert.h>
35 #include <string.h>
36 #include <algorithm>
37
38 #include "common/h/Timer.h"
39 #include "common/h/debugOstream.h"
40 #include "common/h/serialize.h"
41 #include "common/h/pathName.h"
42
43 #include "Serialization.h"
44 #include "Symtab.h"
45 #include "Symbol.h"
46 #include "Module.h"
47 #include "Collections.h"
48 #include "Function.h"
49 #include "Variable.h"
50
51 #include "symtabAPI/src/Object.h"
52
53 using namespace Dyninst;
54 using namespace Dyninst::SymtabAPI;
55 using namespace std;
56
57 static Symbol deletedSymbol(std::string("DeletedSymbol"), Symbol::ST_DELETED, Symbol::SL_UNKNOWN, Symbol::SV_UNKNOWN, 0);
58 /*
59  * We're changing the type of a symbol. Therefore we need to rip it out of the indices
60  * for whatever it used to be (also, aggregations) and put it in the new ones. 
61  * Oy. 
62  */
63
64 bool Symtab::changeType(Symbol *sym, Symbol::SymbolType oldType)
65 {
66     switch (oldType) {
67     case Symbol::ST_FUNCTION: {
68         Function *func = NULL;
69         if (findFuncByEntryOffset(func, sym->getAddr())) {
70             // Remove this symbol from the function
71             func->removeSymbol(sym);
72             // What if we removed the last symbol from the function?
73             // Argh. Ah, well. Users may do that - leave it there for now.
74         break;
75         }
76     }
77     case Symbol::ST_TLS:
78     case Symbol::ST_OBJECT: {
79         Variable *var = NULL;
80         if (findVariableByOffset(var, sym->getAddr())) {
81             var->removeSymbol(sym);
82             // See above
83         }
84         break;
85     }
86     case Symbol::ST_MODULE: {
87         // TODO Module should be an Aggregation
88         break;
89     }
90     default:
91         break;
92     }
93
94     addSymbolToIndices(sym, false);
95     addSymbolToAggregates(sym);
96
97     return true;
98 }
99
100 bool Symtab::deleteFunction(Function *func) {
101     // First, remove the function
102     everyFunction.erase(std::remove(everyFunction.begin(), everyFunction.end(), func), everyFunction.end());
103 /*    std::vector<Function *>::iterator iter;
104     for (iter = everyFunction.begin(); iter != everyFunction.end(); iter++) {
105         if ((*iter) == func) {
106             everyFunction.erase(iter);
107         }
108     }
109 */
110     funcsByOffset.erase(func->getOffset());
111
112     // Now handle the Aggregate stuff
113     return deleteAggregate(func);
114 }
115
116 bool Symtab::deleteVariable(Variable *var) {
117     // First, remove the function
118     everyVariable.erase(std::remove(everyVariable.begin(), everyVariable.end(), var), everyVariable.end());
119
120     varsByOffset.erase(var->getOffset());
121     return deleteAggregate(var);
122 }
123
124 bool Symtab::deleteAggregate(Aggregate *agg) {
125     std::vector<Symbol *> syms;
126     agg->getSymbols(syms);
127
128     bool ret = true;
129     for (unsigned i = 0; i < syms.size(); i++) {
130         if (!deleteSymbolFromIndices(syms[i]))
131             ret = false;
132     }
133     return ret;
134 }
135
136 bool Symtab::deleteSymbolFromIndices(Symbol *sym) {
137     // Remove from global indices
138     std::vector<Symbol *>::iterator iter;
139
140     // everyDefinedSymbol
141     for (iter = everyDefinedSymbol.begin(); iter != everyDefinedSymbol.end(); iter++) 
142     {
143         //  we use indexes in this vector as a unique id for symbols, so mark
144         //  as deleted w/out changing vector
145         if ((*iter) == sym) (*iter) = &deletedSymbol;
146     }
147
148     // userAddedSymbols
149     userAddedSymbols.erase(sym);
150     undefDynSymsByMangledName[sym->getMangledName()].erase(std::remove(undefDynSymsByMangledName[sym->getMangledName()].begin(),
151                                                                        undefDynSymsByMangledName[sym->getMangledName()].end(), sym),
152                                                            undefDynSymsByMangledName[sym->getMangledName()].end());
153     undefDynSymsByPrettyName[sym->getPrettyName()].erase(std::remove(undefDynSymsByPrettyName[sym->getPrettyName()].begin(),
154                                                                        undefDynSymsByPrettyName[sym->getPrettyName()].end(), sym),
155                                                          undefDynSymsByPrettyName[sym->getPrettyName()].end());
156     undefDynSymsByTypedName[sym->getTypedName()].erase(std::remove(undefDynSymsByTypedName[sym->getTypedName()].begin(),
157                                                                        undefDynSymsByTypedName[sym->getTypedName()].end(), sym),
158                                                            undefDynSymsByTypedName[sym->getTypedName()].end());
159     undefDynSyms.erase(std::remove(undefDynSyms.begin(), undefDynSyms.end(), sym), undefDynSyms.end());
160
161     symsByOffset[sym->getOffset()].erase(std::remove(symsByOffset[sym->getOffset()].begin(), symsByOffset[sym->getOffset()].end(),
162                                                      sym), symsByOffset[sym->getOffset()].end());
163     symsByMangledName[sym->getMangledName()].erase(std::remove(symsByMangledName[sym->getMangledName()].begin(),
164                                                                symsByMangledName[sym->getMangledName()].end(), sym),
165                                                    symsByMangledName[sym->getMangledName()].end());
166     symsByPrettyName[sym->getPrettyName()].erase(std::remove(symsByPrettyName[sym->getPrettyName()].begin(),
167                                                              symsByPrettyName[sym->getPrettyName()].end(), sym),
168                                                  symsByPrettyName[sym->getPrettyName()].end());
169     symsByTypedName[sym->getTypedName()].erase(std::remove(symsByTypedName[sym->getTypedName()].begin(),
170                                                            symsByTypedName[sym->getTypedName()].end(), sym),
171                                                symsByTypedName[sym->getTypedName()].end());
172     return true;
173 }
174
175 bool Symtab::deleteSymbol(Symbol *sym)
176 {
177     if (sym->aggregate_) {
178         sym->aggregate_->removeSymbol(sym);
179     }
180
181     return deleteSymbolFromIndices(sym);
182 }
183
184 bool Symtab::changeSymbolOffset(Symbol *sym, Offset newOffset) {
185     // If we aren't part of an aggregate, change the symbol offset
186     // and update symsByOffset.
187     // If we are part of an aggregate and the only symbol element,
188     // do that and update funcsByOffset or varsByOffset.
189     // If we are and not the only symbol, do 1), remove from 
190     // the aggregate, and make a new aggregate.
191
192     Offset oldOffset = sym->offset_;
193     std::vector<Symbol *>::iterator iter;
194     for (iter = symsByOffset[oldOffset].begin();
195          iter != symsByOffset[oldOffset].end();
196          iter++) {
197         if ((*iter) == sym) {
198             symsByOffset[oldOffset].erase(iter);
199             break;
200         }
201     }
202     sym->offset_ = newOffset;
203     symsByOffset[newOffset].push_back(sym);
204
205     if (sym->aggregate_ == NULL) return true;
206     else 
207         return sym->aggregate_->changeSymbolOffset(sym);
208
209 }
210
211 bool Symtab::changeAggregateOffset(Aggregate *agg, Offset oldOffset, Offset newOffset) {
212     Function *func = dynamic_cast<Function *>(agg);
213     Variable *var = dynamic_cast<Variable *>(agg);
214
215     if (func) {
216         funcsByOffset.erase(oldOffset);
217         if (funcsByOffset.find(newOffset) == funcsByOffset.end())
218             funcsByOffset[newOffset] = func;
219         else {
220             // Already someone there... odd, so don't do anything.
221         }
222     }
223     if (var) {
224         varsByOffset.erase(oldOffset);
225         if (varsByOffset.find(newOffset) == varsByOffset.end())
226             varsByOffset[newOffset] = var;
227         else {
228             // Already someone there... odd, so don't do anything.
229         }
230     }
231     return true;
232 }
233
234 bool Symtab::addSymbol(Symbol *newSym, Symbol *referringSymbol) 
235 {
236    if (std::find(userAddedSymbols.begin(), 
237                  userAddedSymbols.end(), 
238                  newSym) != userAddedSymbols.end()) return true;
239
240     if (!newSym || !referringSymbol ) return false;
241
242     if( !referringSymbol->getSymtab()->isStaticBinary() ) {
243         if (!newSym->isInDynSymtab()) return false;
244
245         newSym->setReferringSymbol(referringSymbol);
246
247         string filename = referringSymbol->getModule()->exec()->name();
248         vector<string> *vers, *newSymVers = new vector<string>;
249         newSym->setVersionFileName(filename);
250         std::string rstr;
251
252         bool ret = newSym->getVersionFileName(rstr);
253         if (!ret) 
254         {
255            fprintf(stderr, "%s[%d]:  failed to getVersionFileName(%s)\n", 
256                  FILE__, __LINE__, rstr.c_str());
257         }
258
259         if (referringSymbol->getVersions(vers) && vers != NULL && vers->size() > 0) 
260         {
261             newSymVers->push_back((*vers)[0]);
262             newSym->setVersions(*newSymVers);
263         }
264     }else{
265         newSym->setReferringSymbol(referringSymbol);
266     }
267
268     return addSymbol(newSym);
269 }
270
271 bool Symtab::addSymbol(Symbol *newSym) 
272 {
273    if (!newSym) {
274         return false;
275    }
276    if (std::find(userAddedSymbols.begin(), 
277                  userAddedSymbols.end(), 
278                  newSym) != userAddedSymbols.end()) return true;
279
280
281    // Expected default behavior: if there is no
282    // module use the default.
283    if (newSym->getModule() == NULL) {
284       newSym->setModule(getDefaultModule());
285    }
286    
287    // If there aren't any pretty names, create them
288    if (newSym->getPrettyName() == "") {
289       demangleSymbol(newSym);
290    }
291    
292    // Add to appropriate indices
293    addSymbolToIndices(newSym, false);
294    
295    // And to aggregates
296    addSymbolToAggregates(newSym);
297    
298    // And to "new symbols added by user"
299    userAddedSymbols.insert(newSym);
300    
301    return true;
302 }
303
304
305 Function *Symtab::createFunction(std::string name, 
306                                  Offset offset, 
307                                  size_t sz,
308                                  Module *mod)
309 {
310     Region *reg = NULL;
311     
312     if (!findRegion(reg, ".text") && !isDefensiveBinary()) {
313         assert(0 && "could not find text region");
314         fprintf(stderr, "%s[%d]:  could not find text region\n", FILE__, __LINE__);
315         return NULL;
316     }
317     
318     if (!reg) {
319         reg = findEnclosingRegion(offset);
320     }
321
322     if (!reg) {
323         fprintf(stderr, "%s[%d]:  could not find region for func at %lx\n", 
324                 FILE__, __LINE__,offset);
325         return NULL;
326     }
327     
328     // Let's get the module hammered out. 
329     if (mod == NULL) {
330         mod = getDefaultModule();
331     }
332
333     // Check to see if we contain this module...
334     bool found = false;
335     for (unsigned i = 0; i < _mods.size(); i++) {
336         if (_mods[i] == mod) {
337             found = true;
338             break;
339         }
340     }
341     if (!found) {
342         fprintf(stderr, "Mod is %p/%s\n",
343                 mod, mod->fileName().c_str());
344         for (unsigned i = 0; i < _mods.size(); i++) {
345             fprintf(stderr, "Matched against %p/%s\n",
346                     _mods[i], _mods[i]->fileName().c_str());
347         }
348         fprintf(stderr, "This %p; mod symtab %p\n",
349                 this, mod->exec());
350
351         assert(0 && "passed invalid module\n");
352         return NULL;
353     }
354     
355     Symbol *statSym = new Symbol(name, 
356                                  Symbol::ST_FUNCTION, 
357                                  Symbol::SL_GLOBAL,
358                                  Symbol::SV_DEFAULT, 
359                                  offset, 
360                                  mod,
361                                  reg, 
362                                  sz,
363                                  false,
364                                  false);
365     Symbol *dynSym = new Symbol(name,
366                                 Symbol::ST_FUNCTION,
367                                 Symbol::SL_GLOBAL,
368                                 Symbol::SV_DEFAULT,
369                                 offset,
370                                 mod,
371                                 reg,
372                                 sz,
373                                 true,
374                                 false);
375
376     if (!addSymbol(statSym) || !addSymbol(dynSym)) {
377         assert(0 && "failed to add symbol\n");
378         fprintf(stderr, "%s[%d]:  symtab failed to addSymbol\n", FILE__, __LINE__);
379         return NULL;
380     }
381     
382     Function *func = statSym->getFunction();
383     if (!func) {                
384         assert(0 && "failed aggregate creation");
385         fprintf(stderr, "%s[%d]:  symtab failed to create function\n", FILE__, __LINE__);
386         return NULL;
387     }
388     
389     return func;
390 }
391
392
393
394 Variable *Symtab::createVariable(std::string name, 
395                                  Offset offset, 
396                                  size_t sz,
397                                  Module *mod)
398 {
399     Region *reg = NULL;
400 #if 0    
401     if (!findRegion(reg, ".data") {
402         fprintf(stderr, "%s[%d]:  could not find %s region\n", FILE__, __LINE__, regionName.c_str());
403         return NULL;
404     }
405     
406     if (!reg) {
407         fprintf(stderr, "%s[%d]:  could not find data region\n", FILE__, __LINE__);
408         return NULL;
409     }
410 #endif    
411     // Let's get the module hammered out. 
412     if (mod == NULL) {
413         mod = getDefaultModule();
414     }
415     // Check to see if we contain this module...
416     bool found = false;
417     for (unsigned i = 0; i < _mods.size(); i++) {
418         if (_mods[i] == mod) {
419             found = true;
420             break;
421         }
422     }
423     if (!found) return NULL;
424     
425     Symbol *statSym = new Symbol(name, 
426                                  Symbol::ST_OBJECT, 
427                                  Symbol::SL_GLOBAL,
428                                  Symbol::SV_DEFAULT, 
429                                  offset, 
430                                  mod,
431                                  reg, 
432                                  sz,
433                                  false,
434                                  false);
435     Symbol *dynSym = new Symbol(name,
436                                 Symbol::ST_OBJECT,
437                                 Symbol::SL_GLOBAL,
438                                 Symbol::SV_DEFAULT,
439                                 offset,
440                                 mod,
441                                 reg,
442                                 sz,
443                                 true,
444                                 false);
445     
446     statSym->setModule(mod);
447     dynSym->setModule(mod);
448
449     if (!addSymbol(statSym) || !addSymbol(dynSym)) {
450         fprintf(stderr, "%s[%d]:  symtab failed to addSymbol\n", FILE__, __LINE__);
451         return NULL;
452     }
453     
454     Variable *var = statSym->getVariable();
455     if (!var) {         
456         fprintf(stderr, "%s[%d]:  symtab failed to create var\n", FILE__, __LINE__);
457         return NULL;
458     }
459     
460     return var;
461 }
462
463 SYMTAB_EXPORT bool Symtab::updateRelocations(Address start,
464                                              Address end,
465                                              Symbol *oldsym,
466                                              Symbol *newsym) {
467    for (unsigned i = 0; i < codeRegions_.size(); ++i) {
468       codeRegions_[i]->updateRelocations(start, end, oldsym, newsym);
469    }
470    return true;
471 }
472