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