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