Merge branch 'master' of legendre@git.dyninst.org:/pub/dyninst
[dyninst.git] / symtabAPI / src / Symtab-edit.C
1 /*
2  * Copyright (c) 1996-2007 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);
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(std::remove(userAddedSymbols.begin(), userAddedSymbols.end(), sym), userAddedSymbols.end());
150     undefDynSyms[sym->getMangledName()].erase(std::remove(undefDynSyms[sym->getMangledName()].begin(),
151         undefDynSyms[sym->getMangledName()].end(), sym), undefDynSyms[sym->getMangledName()].end());
152     symsByOffset[sym->getOffset()].erase(std::remove(symsByOffset[sym->getOffset()].begin(), symsByOffset[sym->getOffset()].end(),
153         sym), symsByOffset[sym->getOffset()].end());
154     symsByMangledName[sym->getMangledName()].erase(std::remove(symsByMangledName[sym->getMangledName()].begin(),
155         symsByMangledName[sym->getMangledName()].end(), sym), symsByMangledName[sym->getMangledName()].end());
156     symsByPrettyName[sym->getPrettyName()].erase(std::remove(symsByPrettyName[sym->getPrettyName()].begin(),
157         symsByPrettyName[sym->getPrettyName()].end(), sym), symsByPrettyName[sym->getPrettyName()].end());
158     symsByTypedName[sym->getTypedName()].erase(std::remove(symsByTypedName[sym->getTypedName()].begin(),
159         symsByTypedName[sym->getTypedName()].end(), sym), symsByTypedName[sym->getTypedName()].end());
160
161
162     return true;
163 }
164
165 bool Symtab::deleteSymbol(Symbol *sym)
166 {
167     if (sym->aggregate_) {
168         sym->aggregate_->removeSymbol(sym);
169     }
170
171     return deleteSymbolFromIndices(sym);
172 }
173
174 bool Symtab::changeSymbolOffset(Symbol *sym, Offset newOffset) {
175     // If we aren't part of an aggregate, change the symbol offset
176     // and update symsByOffset.
177     // If we are part of an aggregate and the only symbol element,
178     // do that and update funcsByOffset or varsByOffset.
179     // If we are and not the only symbol, do 1), remove from 
180     // the aggregate, and make a new aggregate.
181
182     Offset oldOffset = sym->offset_;
183     std::vector<Symbol *>::iterator iter;
184     for (iter = symsByOffset[oldOffset].begin();
185          iter != symsByOffset[oldOffset].end();
186          iter++) {
187         if ((*iter) == sym) {
188             symsByOffset[oldOffset].erase(iter);
189             break;
190         }
191     }
192     sym->offset_ = newOffset;
193     symsByOffset[newOffset].push_back(sym);
194
195     if (sym->aggregate_ == NULL) return true;
196     else 
197         return sym->aggregate_->changeSymbolOffset(sym);
198
199 }
200
201 bool Symtab::changeAggregateOffset(Aggregate *agg, Offset oldOffset, Offset newOffset) {
202     Function *func = dynamic_cast<Function *>(agg);
203     Variable *var = dynamic_cast<Variable *>(agg);
204
205     if (func) {
206         funcsByOffset.erase(oldOffset);
207         if (funcsByOffset.find(newOffset) == funcsByOffset.end())
208             funcsByOffset[newOffset] = func;
209         else {
210             // Already someone there... odd, so don't do anything.
211         }
212     }
213     if (var) {
214         varsByOffset.erase(oldOffset);
215         if (varsByOffset.find(newOffset) == varsByOffset.end())
216             varsByOffset[newOffset] = var;
217         else {
218             // Already someone there... odd, so don't do anything.
219         }
220     }
221     return true;
222 }
223
224 bool Symtab::addSymbol(Symbol *newSym, Symbol *referringSymbol) 
225 {
226     if (!newSym)
227         return false;
228     if (!newSym->isInDynSymtab())
229         return false;
230
231     newSym->setReferringSymbol(referringSymbol);
232
233     string filename = referringSymbol->getModule()->exec()->name();
234     vector<string> *vers, *newSymVers = new vector<string>;
235     newSym->setVersionFileName(filename);
236     std::string rstr;
237
238     bool ret = newSym->getVersionFileName(rstr);
239     if (!ret) 
240     {
241        fprintf(stderr, "%s[%d]:  failed to getVersionFileName(%s)\n", 
242              FILE__, __LINE__, rstr.c_str());
243     }
244
245     if (referringSymbol->getVersions(vers) && vers != NULL && vers->size() > 0) 
246     {
247         newSymVers->push_back((*vers)[0]);
248         newSym->setVersions(*newSymVers);
249     }
250
251     return addSymbol(newSym);
252 }
253
254 bool Symtab::addSymbol(Symbol *newSym) 
255 {
256     if (!newSym)
257         return false;
258
259     // Expected default behavior: if there is no
260     // module use the default.
261     if (newSym->getModule() == NULL) {
262         newSym->setModule(getDefaultModule());
263     }
264
265     // If there aren't any pretty names, create them
266     if (newSym->getPrettyName() == "") {
267         demangleSymbol(newSym);
268     }
269
270     // Add to appropriate indices
271     addSymbolToIndices(newSym);
272
273     // And to aggregates
274     addSymbolToAggregates(newSym);
275
276     // And to "new symbols added by user"
277     userAddedSymbols.push_back(newSym);
278
279     return true;
280 }
281
282
283 Function *Symtab::createFunction(std::string name, 
284                                  Offset offset, 
285                                  size_t sz,
286                                  Module *mod)
287 {
288     Region *reg = NULL;
289     
290     if (!findRegion(reg, ".text")) {
291         assert(0 && "could not find text region");
292         fprintf(stderr, "%s[%d]:  could not find data region\n", FILE__, __LINE__);
293         return NULL;
294     }
295     
296     if (!reg) {
297         fprintf(stderr, "%s[%d]:  could not find text region\n", FILE__, __LINE__);
298         return NULL;
299     }
300     
301     // Let's get the module hammered out. 
302     if (mod == NULL) {
303         mod = getDefaultModule();
304     }
305
306     // Check to see if we contain this module...
307     bool found = false;
308     for (unsigned i = 0; i < _mods.size(); i++) {
309         if (_mods[i] == mod) {
310             found = true;
311             break;
312         }
313     }
314     if (!found) {
315         fprintf(stderr, "Mod is %p/%s\n",
316                 mod, mod->fileName().c_str());
317         for (unsigned i = 0; i < _mods.size(); i++) {
318             fprintf(stderr, "Matched against %p/%s\n",
319                     _mods[i], _mods[i]->fileName().c_str());
320         }
321         fprintf(stderr, "This %p; mod symtab %p\n",
322                 this, mod->exec());
323
324         assert(0 && "passed invalid module\n");
325         return NULL;
326     }
327     
328     Symbol *statSym = new Symbol(name, 
329                                  Symbol::ST_FUNCTION, 
330                                  Symbol::SL_GLOBAL,
331                                  Symbol::SV_DEFAULT, 
332                                  offset, 
333                                  mod,
334                                  reg, 
335                                  sz,
336                                  false,
337                                  false);
338     Symbol *dynSym = new Symbol(name,
339                                 Symbol::ST_FUNCTION,
340                                 Symbol::SL_GLOBAL,
341                                 Symbol::SV_DEFAULT,
342                                 offset,
343                                 mod,
344                                 reg,
345                                 sz,
346                                 true,
347                                 false);
348
349     if (!addSymbol(statSym) || !addSymbol(dynSym)) {
350         assert(0 && "failed to add symbol\n");
351         fprintf(stderr, "%s[%d]:  symtab failed to addSymbol\n", FILE__, __LINE__);
352         return NULL;
353     }
354     
355     Function *func = statSym->getFunction();
356     if (!func) {                
357         assert(0 && "failed aggregate creation");
358         fprintf(stderr, "%s[%d]:  symtab failed to create function\n", FILE__, __LINE__);
359         return NULL;
360     }
361     
362     return func;
363 }
364
365
366
367 Variable *Symtab::createVariable(std::string name, 
368                                  Offset offset, 
369                                  size_t sz,
370                                  Module *mod)
371 {
372     Region *reg = NULL;
373 #if 0    
374     if (!findRegion(reg, ".data") {
375         fprintf(stderr, "%s[%d]:  could not find %s region\n", FILE__, __LINE__, regionName.c_str());
376         return NULL;
377     }
378     
379     if (!reg) {
380         fprintf(stderr, "%s[%d]:  could not find data region\n", FILE__, __LINE__);
381         return NULL;
382     }
383 #endif    
384     // Let's get the module hammered out. 
385     if (mod == NULL) {
386         mod = getDefaultModule();
387     }
388     // Check to see if we contain this module...
389     bool found = false;
390     for (unsigned i = 0; i < _mods.size(); i++) {
391         if (_mods[i] == mod) {
392             found = true;
393             break;
394         }
395     }
396     if (!found) return NULL;
397     
398     Symbol *statSym = new Symbol(name, 
399                                  Symbol::ST_OBJECT, 
400                                  Symbol::SL_GLOBAL,
401                                  Symbol::SV_DEFAULT, 
402                                  offset, 
403                                  mod,
404                                  reg, 
405                                  sz,
406                                  false,
407                                  false);
408     Symbol *dynSym = new Symbol(name,
409                                 Symbol::ST_OBJECT,
410                                 Symbol::SL_GLOBAL,
411                                 Symbol::SV_DEFAULT,
412                                 offset,
413                                 mod,
414                                 reg,
415                                 sz,
416                                 true,
417                                 false);
418     
419     statSym->setModule(mod);
420     dynSym->setModule(mod);
421
422     if (!addSymbol(statSym) || !addSymbol(dynSym)) {
423         fprintf(stderr, "%s[%d]:  symtab failed to addSymbol\n", FILE__, __LINE__);
424         return NULL;
425     }
426     
427     Variable *var = statSym->getVariable();
428     if (!var) {         
429         fprintf(stderr, "%s[%d]:  symtab failed to create var\n", FILE__, __LINE__);
430         return NULL;
431     }
432     
433     return var;
434 }
435
436