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