Merge branch 'master' of 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 /*
58  * We're changing the type of a symbol. Therefore we need to rip it out of the indices
59  * for whatever it used to be (also, aggregations) and put it in the new ones. 
60  * Oy. 
61  */
62
63 bool Symtab::changeType(Symbol *sym, Symbol::SymbolType oldType)
64 {
65     switch (oldType) {
66     case Symbol::ST_FUNCTION: {
67         Function *func = NULL;
68         if (findFuncByEntryOffset(func, sym->getAddr())) {
69             // Remove this symbol from the function
70             func->removeSymbol(sym);
71             // What if we removed the last symbol from the function?
72             // Argh. Ah, well. Users may do that - leave it there for now.
73         break;
74         }
75     }
76     case Symbol::ST_OBJECT: {
77         Variable *var = NULL;
78         if (findVariableByOffset(var, sym->getAddr())) {
79             var->removeSymbol(sym);
80             // See above
81         }
82         break;
83     }
84     case Symbol::ST_MODULE: {
85         // TODO Module should be an Aggregation
86         break;
87     }
88     default:
89         break;
90     }
91
92     addSymbolToIndices(sym);
93     addSymbolToAggregates(sym);
94
95     return true;
96 }
97
98 bool Symtab::delSymbol(Symbol *sym)
99 {
100     switch (sym->getType()) {
101     case Symbol::ST_FUNCTION: {
102         Function *func = NULL;
103         if (findFuncByEntryOffset(func, sym->getAddr())) {
104             // Remove this symbol from the function
105             func->removeSymbol(sym);
106             // What if we removed the last symbol from the function?
107             // Argh. Ah, well. Users may do that - leave it there for now.
108         break;
109         }
110     }
111     case Symbol::ST_OBJECT: {
112         Variable *var = NULL;
113         if (findVariableByOffset(var, sym->getAddr())) {
114             var->removeSymbol(sym);
115             // See above
116         }
117         break;
118     }
119     case Symbol::ST_MODULE: {
120         // TODO Module should be an Aggregation
121         break;
122     }
123     default:
124         break;
125     }
126
127     // Remove from global indices
128     for (std::vector<Symbol *>::iterator iter = everyDefinedSymbol.begin();
129          iter != everyDefinedSymbol.end();
130          iter++) {
131         if (*iter == sym) {
132             everyDefinedSymbol.erase(iter);
133             break;
134         }
135     }
136     // Delete from user added symbols
137     for (std::vector<Symbol *>::iterator iter = userAddedSymbols.begin();
138          iter != userAddedSymbols.end();
139          iter++) {
140         if (*iter == sym) {
141             userAddedSymbols.erase(iter);
142             break;
143         }
144     }
145     // From undefined dynamic symbols, if it exists
146     if (undefDynSyms.find(sym->getName()) != undefDynSyms.end())
147         undefDynSyms.erase(sym->getName());
148
149     // And now from the other maps
150     // symsByOffset:
151     std::vector<Symbol *> offsetSyms = symsByOffset[sym->getAddr()];
152     for (std::vector<Symbol *>::iterator iter = offsetSyms.begin();
153          iter != offsetSyms.end();
154          iter++) {
155         if (*iter == sym) {
156             offsetSyms.erase(iter);
157         }
158     }
159     symsByOffset[sym->getAddr()] = offsetSyms;
160
161     // symsByMangledName, same idea. 
162     std::vector<Symbol *> mangledSyms = symsByMangledName[sym->getName()];
163     for (std::vector<Symbol *>::iterator iter = mangledSyms.begin();
164          iter != mangledSyms.end();
165          iter++) {
166         if (*iter == sym) {
167             mangledSyms.erase(iter);
168         }
169     }
170     symsByMangledName[sym->getName()] = mangledSyms;
171
172     // symsByPrettyName, same idea. 
173     std::vector<Symbol *> prettySyms = symsByPrettyName[sym->getPrettyName()];
174     for (std::vector<Symbol *>::iterator iter = prettySyms.begin();
175          iter != prettySyms.end();
176          iter++) {
177         if (*iter == sym) {
178             prettySyms.erase(iter);
179         }
180     }
181     symsByPrettyName[sym->getPrettyName()] = prettySyms;
182
183     // symsByTypedName, same idea. 
184     std::vector<Symbol *> typedSyms = symsByTypedName[sym->getTypedName()];
185     for (std::vector<Symbol *>::iterator iter = typedSyms.begin();
186          iter != typedSyms.end();
187          iter++) {
188         if (*iter == sym) {
189             typedSyms.erase(iter);
190         }
191     }
192     symsByTypedName[sym->getTypedName()] = typedSyms;
193
194     // Don't delete; it still exists in the linkedFile
195     return true;
196 }
197
198 bool Symtab::addSymbol(Symbol *newSym, Symbol *referringSymbol) 
199 {
200     if (!newSym)
201         return false;
202
203     string filename = referringSymbol->getModule()->exec()->name();
204     vector<string> *vers, *newSymVers = new vector<string>;
205     newSym->setVersionFileName(filename);
206     std::string rstr;
207
208     bool ret = newSym->getVersionFileName(rstr);
209     if (!ret) 
210     {
211        fprintf(stderr, "%s[%d]:  failed to getVersionFileName(%s)\n", 
212              FILE__, __LINE__, rstr.c_str());
213     }
214
215     if (referringSymbol->getVersions(vers) && vers != NULL && vers->size() > 0) 
216     {
217         newSymVers->push_back((*vers)[0]);
218         newSym->setVersions(*newSymVers);
219     }
220
221     //Check again. Is this an ok thing to do??
222     undefDynSyms[newSym->getPrettyName()].push_back(newSym);
223
224     return addSymbol(newSym, true);
225 }
226
227 bool Symtab::addSymbol(Symbol *newSym, bool isDynamic) 
228 {
229     if (!newSym)
230         return false;
231
232     if (isDynamic) 
233     {
234         newSym->clearIsInSymtab();
235         newSym->setDynSymtab();
236     }   
237
238 #if !defined(os_windows)
239     // Windows: variables are created with an empty module
240     if (newSym->getModuleName().length() == 0) 
241     {
242         //fprintf(stderr, "SKIPPING EMPTY MODULE\n");
243         return false;
244     }
245 #endif
246     
247     // This mimics the behavior during parsing
248
249     fixSymModule(newSym);
250
251     // If there aren't any pretty names, create them
252     if (newSym->getPrettyName() == "") {
253         demangleSymbol(newSym);
254     }
255
256     // Add to appropriate indices
257     addSymbolToIndices(newSym);
258
259     // And to aggregates
260     addSymbolToAggregates(newSym);
261
262     // And to "new symbols added by user"
263     userAddedSymbols.push_back(newSym);
264
265     return true;
266 }
267