Update Examples in dataflowAPI (#700)
[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/src/Timer.h"
38 #include "common/src/debugOstream.h"
39 #include "common/src/serialize.h"
40 #include "common/src/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   everyDefinedSymbol.erase(sym);
139   undefDynSyms.erase(sym);
140   return true;
141 }
142
143 bool Symtab::deleteSymbol(Symbol *sym)
144 {
145     boost::unique_lock<dyn_rwlock> l(symbols_rwlock);
146     if (sym->aggregate_) {
147         sym->aggregate_->removeSymbol(sym);
148     }
149     bool result = deleteSymbolFromIndices(sym);
150     return result;
151 }
152
153 bool Symtab::changeSymbolOffset(Symbol *sym, Offset newOffset) {
154     // If we aren't part of an aggregate, change the symbol offset
155     // and update symsByOffset.
156     // If we are part of an aggregate and the only symbol element,
157     // do that and update funcsByOffset or varsByOffset.
158     // If we are and not the only symbol, do 1), remove from 
159     // the aggregate, and make a new aggregate.
160   {
161     indexed_symbols::master_t::accessor a;
162     assert(everyDefinedSymbol.master.find(a, sym));
163
164     indexed_symbols::by_offset_t::accessor oa;
165     assert(everyDefinedSymbol.by_offset.find(oa, sym->offset_));
166     std::remove(oa->second.begin(), oa->second.end(), sym);
167     everyDefinedSymbol.by_offset.insert(oa, newOffset);
168     oa->second.push_back(sym);
169
170     a->second = newOffset;
171     sym->offset_ = newOffset;
172   }
173
174   if (sym->aggregate_ == NULL) return true;
175   else return sym->aggregate_->changeSymbolOffset(sym);
176 }
177
178 bool Symtab::changeAggregateOffset(Aggregate *agg, Offset oldOffset, Offset newOffset) {
179     Function *func = dynamic_cast<Function *>(agg);
180     Variable *var = dynamic_cast<Variable *>(agg);
181
182     if (func) {
183         funcsByOffset.erase(oldOffset);
184         if (!funcsByOffset.insert({newOffset, func})) {
185             // Already someone there... odd, so don't do anything.
186         }
187     }
188     if (var) {
189         varsByOffset.erase(oldOffset);
190         if (!varsByOffset.insert({newOffset, var})) {
191             // Already someone there... odd, so don't do anything.
192         }
193     }
194     return true;
195 }
196
197 bool Symtab::addSymbol(Symbol *newSym, Symbol *referringSymbol) 
198 {
199     if (!newSym || !referringSymbol ) return false;
200
201     if( !referringSymbol->getSymtab()->isStaticBinary() ) {
202         if (!newSym->isInDynSymtab()) return false;
203
204         newSym->setReferringSymbol(referringSymbol);
205
206         string filename = referringSymbol->getModule()->exec()->name();
207         vector<string> *vers, *newSymVers = new vector<string>;
208         newSym->setVersionFileName(filename);
209         std::string rstr;
210
211         newSym->getVersionFileName(rstr);
212         if (referringSymbol->getVersions(vers) && vers != NULL && vers->size() > 0) 
213         {
214             newSymVers->push_back((*vers)[0]);
215             newSym->setVersions(*newSymVers);
216         }
217     }else{
218         newSym->setReferringSymbol(referringSymbol);
219     }
220
221     return addSymbol(newSym);
222 }
223
224 bool Symtab::addSymbol(Symbol *newSym) 
225 {
226    if (!newSym) {
227         return false;
228    }
229
230    // Expected default behavior: if there is no
231    // module use the default.
232    if (newSym->getModule() == NULL) {
233       newSym->setModule(getDefaultModule());
234    }
235    
236    // If there aren't any pretty names, create them
237    if (newSym->getPrettyName() == "") {
238       demangleSymbol(newSym);
239    }
240    
241    // Add to appropriate indices
242    addSymbolToIndices(newSym, false);
243    
244    // And to aggregates
245    addSymbolToAggregates(newSym);
246
247    return true;
248 }
249
250
251 Function *Symtab::createFunction(std::string name, 
252                                  Offset offset, 
253                                  size_t sz,
254                                  Module *mod)
255 {
256     Region *reg = NULL;
257     
258     if (!findRegion(reg, ".text") && !isDefensiveBinary()) {
259         return NULL;
260     }
261     
262     if (!reg) {
263         reg = findEnclosingRegion(offset);
264     }
265
266     if (!reg) {
267         return NULL;
268     }
269     
270     // Let's get the module hammered out. 
271     if (mod == NULL) {
272         mod = getDefaultModule();
273     }
274
275     // Check to see if we contain this module...
276     if(indexed_modules.get<1>().find(mod) == indexed_modules.get<1>().end()) return NULL;
277 //
278 //    bool found = false;
279 //    for (unsigned i = 0; i < indexed_modules.size(); i++) {
280 //        if (indexed_modules[i] == mod) {
281 //            found = true;
282 //            break;
283 //        }
284 //    }
285 //    if (!found) {
286 //        return NULL;
287 //    }
288     
289     Symbol *statSym = new Symbol(name, 
290                                  Symbol::ST_FUNCTION, 
291                                  Symbol::SL_GLOBAL,
292                                  Symbol::SV_DEFAULT, 
293                                  offset, 
294                                  mod,
295                                  reg, 
296                                  sz,
297                                  false,
298                                  false);
299     if (!addSymbol(statSym)) {
300         return NULL;
301     }
302     
303     Function *func = statSym->getFunction();
304     if (!func) {                
305         return NULL;
306     }
307     
308     return func;
309 }
310
311
312
313 Variable *Symtab::createVariable(std::string name, 
314                                  Offset offset, 
315                                  size_t sz,
316                                  Module *mod)
317 {
318     Region *reg = NULL;
319     // Let's get the module hammered out. 
320     if (mod == NULL) {
321         mod = getDefaultModule();
322     }
323     // Check to see if we contain this module...
324     if(indexed_modules.get<1>().find(mod) == indexed_modules.get<1>().end()) return NULL;
325 //
326 //    bool found = false;
327 //    for (unsigned i = 0; i < indexed_modules.size(); i++) {
328 //        if (indexed_modules[i] == mod) {
329 //            found = true;
330 //            break;
331 //        }
332 //    }
333 //    if (!found) {
334 //        return NULL;
335 //    }
336     
337     Symbol *statSym = new Symbol(name, 
338                                  Symbol::ST_OBJECT, 
339                                  Symbol::SL_GLOBAL,
340                                  Symbol::SV_DEFAULT, 
341                                  offset, 
342                                  mod,
343                                  reg, 
344                                  sz,
345                                  false,
346                                  false);
347     Symbol *dynSym = new Symbol(name,
348                                 Symbol::ST_OBJECT,
349                                 Symbol::SL_GLOBAL,
350                                 Symbol::SV_DEFAULT,
351                                 offset,
352                                 mod,
353                                 reg,
354                                 sz,
355                                 true,
356                                 false);
357     
358     statSym->setModule(mod);
359     dynSym->setModule(mod);
360
361     if (!addSymbol(statSym) || !addSymbol(dynSym)) {
362         return NULL;
363     }
364     
365     Variable *var = statSym->getVariable();
366     if (!var) {         
367         return NULL;
368     }
369     
370     return var;
371 }
372
373 SYMTAB_EXPORT bool Symtab::updateRelocations(Address start,
374                                              Address end,
375                                              Symbol *oldsym,
376                                              Symbol *newsym) {
377    for (unsigned i = 0; i < codeRegions_.size(); ++i) {
378       codeRegions_[i]->updateRelocations(start, end, oldsym, newsym);
379    }
380    return true;
381 }
382