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