Initial infrastructure for variable rewriting
[dyninst.git] / symtabAPI / src / Module.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 * 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 <string.h>
32
33 #include "Annotatable.h"
34 #include "Module.h"
35 #include "Symtab.h"
36 #include "Collections.h"
37 #include "Function.h"
38
39 #include "common/h/pathName.h"
40
41 using namespace Dyninst;
42 using namespace Dyninst::SymtabAPI;
43 using namespace std;
44
45 static AnnotationClass<LineInformation> ModuleLineInfoAnno(std::string("ModuleLineInfoAnno"));
46 static AnnotationClass<typeCollection> ModuleTypeInfoAnno(std::string("ModuleTypeInfoAnno"));
47 static SymtabError serr;
48
49 bool Module::findSymbolByType(std::vector<Symbol *> &found, 
50       const std::string name,
51       Symbol::SymbolType sType, 
52       bool isMangled,
53       bool isRegex, 
54       bool checkCase)
55 {
56    unsigned orig_size = found.size();
57    std::vector<Symbol *> obj_syms;
58
59    if (!exec()->findSymbolByType(obj_syms, name, sType, isMangled, isRegex, checkCase))
60    {
61       //fprintf(stderr, "%s[%d]:  no symbols matching %s found\n", FILE__, __LINE__, name.c_str());
62       return false;
63    }
64
65    for (unsigned i = 0; i < obj_syms.size(); i++)  
66    {
67       if (obj_syms[i]->getModule() == this)
68          found.push_back(obj_syms[i]);
69 #if 0
70       else 
71       {
72          if (obj_syms[i]->getName() == name) {
73             fprintf(stderr, "%s[%d]:  found symbol %s in different module %s not %s\n", 
74                   FILE__, __LINE__, name.c_str(), 
75                   obj_syms[i]->getModule()->fileName().c_str(), 
76                   this->fileName().c_str());
77          }
78       }
79 #endif
80    }
81
82    if (found.size() > orig_size) 
83       return true;
84
85    return false;        
86 }
87
88 const std::string &Module::fileName() const
89 {
90    return fileName_;
91 }
92
93 const std::string &Module::fullName() const
94 {
95    return fullName_;
96 }
97
98  Symtab *Module::exec() const
99 {
100    return exec_;
101 }
102
103 supportedLanguages Module::language() const
104 {
105    return language_;
106 }
107
108 bool Module::hasLineInformation()
109 {
110    LineInformation *li =  NULL;
111    if (getAnnotation(li, ModuleLineInfoAnno)) 
112    {
113       if (!li) 
114       {
115          fprintf(stderr, "%s[%d]:  weird inconsistency with getAnnotation here\n", 
116                FILE__, __LINE__);
117          return false;
118       }
119
120       if (li->getSize())
121       {
122          return true;
123       }
124    }
125
126    return false;
127 #if 0
128    Annotatable<LineInformation *, module_line_info_a,  true> &liA = *this;
129    return ( 0 != liA.size());
130 #endif
131 }
132
133 LineInformation *Module::getLineInformation()
134 {
135    if (!exec_->isLineInfoValid_)
136       exec_->parseLineInformation();
137
138    if (!exec_->isLineInfoValid_) 
139    {
140       return NULL;
141    }
142
143    LineInformation *li =  NULL;
144    if (getAnnotation(li, ModuleLineInfoAnno)) 
145    {
146       if (!li) 
147       {
148          fprintf(stderr, "%s[%d]:  weird inconsistency with getAnnotation here\n", 
149                FILE__, __LINE__);
150          return NULL;
151       }
152
153       if (!li->getSize())
154       {
155          return NULL;
156       }
157    }
158
159    return li;
160 }
161
162 bool Module::getAddressRanges(std::vector<pair<Offset, Offset> >&ranges,
163       std::string lineSource, unsigned int lineNo)
164 {
165    unsigned int originalSize = ranges.size();
166
167    LineInformation *lineInformation = getLineInformation();
168    if (lineInformation)
169       lineInformation->getAddressRanges( lineSource.c_str(), lineNo, ranges );
170
171    if ( ranges.size() != originalSize )
172       return true;
173
174    fprintf(stderr, "%s[%d]:  failing to getAddressRanges fr %s[%d]\n", FILE__, __LINE__, lineSource.c_str(), lineNo);
175
176    return false;
177 }
178
179 bool Module::getSourceLines(std::vector<LineNoTuple> &lines, Offset addressInRange)
180 {
181    unsigned int originalSize = lines.size();
182
183    LineInformation *lineInformation = getLineInformation();
184    if (lineInformation)
185       lineInformation->getSourceLines( addressInRange, lines );
186
187    if ( lines.size() != originalSize )
188       return true;
189
190    return false;
191 }
192
193 vector<Type *> *Module::getAllTypes()
194 {
195    typeCollection *tc = NULL;
196    if (!getAnnotation(tc, ModuleTypeInfoAnno))
197    {
198 #if 0
199       tc = new typeCollection();
200       if (!addAnnotation(tc, ModuleTypeInfoAnno))
201       {
202          fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
203          return NULL;
204       }
205 #endif
206       return NULL;
207    }
208    if (!tc)
209    {
210       fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
211       return NULL;
212    }
213
214    return tc->getAllTypes();
215 }
216
217 vector<pair<string, Type *> > *Module::getAllGlobalVars()
218 {
219
220    typeCollection *tc = NULL;
221    if (!getAnnotation(tc, ModuleTypeInfoAnno))
222    {
223 #if 0
224       tc = new typeCollection();
225       if (!addAnnotation(tc, ModuleTypeInfoAnno))
226       {
227          fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
228          return NULL;
229       }
230 #endif
231       return NULL;
232    }
233    if (!tc)
234    {
235       fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
236       return NULL;
237    }
238
239    return tc->getAllGlobalVariables();
240 }
241
242 typeCollection *Module::getModuleTypes()
243 {
244    typeCollection *tc = NULL;
245    if (!getAnnotation(tc, ModuleTypeInfoAnno))
246    {
247       //  add an empty type collection (to be filled in later)
248       tc = new typeCollection();
249       if (!addAnnotation(tc, ModuleTypeInfoAnno))
250       {
251          fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
252          return NULL;
253       }
254
255       return tc;
256    }
257
258    if (!tc)
259    {
260       fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
261       return NULL;
262    }
263
264    return tc;
265 }
266
267 bool Module::findType(Type *&type, std::string name)
268 {
269    exec_->parseTypesNow();
270    type = getModuleTypes()->findType(name);
271
272    if (type == NULL)
273       return false;
274
275    return true;
276 }
277
278 bool Module::findVariableType(Type *&type, std::string name)
279 {
280    exec_->parseTypesNow();
281    type = getModuleTypes()->findVariableType(name);
282
283    if (type == NULL)
284       return false;
285
286    return true;
287 }
288
289 void Symtab::parseTypesNow()
290 {
291    if (isTypeInfoValid_)
292       return;
293
294    parseTypes();
295 }
296
297 bool Module::setLineInfo(LineInformation *lineInfo)
298 {
299    LineInformation *li =  NULL;
300
301    if (!getAnnotation(li, ModuleLineInfoAnno)) 
302    {
303       if (li) 
304       {
305          return false;
306       }
307
308       if (!addAnnotation(lineInfo, ModuleLineInfoAnno))
309       {
310          return false;
311       }
312
313       return true;
314    }
315    if (li != lineInfo)
316      delete li;
317    
318    if (!addAnnotation(lineInfo, ModuleLineInfoAnno))
319    {
320      fprintf(stderr, "%s[%d]:  failed to add lineInfo annotation\n", FILE__, __LINE__);
321      return false;
322    }
323
324    return false;
325 }
326
327 bool Module::findLocalVariable(std::vector<localVar *>&vars, std::string name)
328 {
329    exec_->parseTypesNow();
330    std::vector<Function *>mod_funcs;
331
332    if (!exec_->getAllFunctions(mod_funcs))
333    {
334       return false;
335    }
336
337    unsigned origSize = vars.size();
338
339    for (unsigned int i = 0; i < mod_funcs.size(); i++)
340    {
341       mod_funcs[i]->findLocalVariable(vars, name);
342    }
343
344    if (vars.size() > origSize)
345       return true;
346
347    return false;
348 }
349
350 Module::Module(supportedLanguages lang, Offset adr,
351       std::string fullNm, Symtab *img) :
352    fullName_(fullNm),
353    language_(lang),
354    addr_(adr),
355    exec_(img)
356 {
357    fileName_ = extract_pathname_tail(fullNm);
358 }
359
360 Module::Module() :
361    fileName_(""),
362    fullName_(""),
363    language_(lang_Unknown),
364    addr_(0),
365    exec_(NULL)
366 {
367 }
368
369 Module::Module(const Module &mod) :
370    LookupInterface(),
371    Serializable(),
372    AnnotatableSparse(),
373    fileName_(mod.fileName_),
374    fullName_(mod.fullName_),
375    language_(mod.language_),
376    addr_(mod.addr_),
377    exec_(mod.exec_)
378 {
379    //  Copy annotations here or no?
380 }
381
382 Module::~Module()
383 {
384
385    //  individual deletion of annotations??
386
387 #if 0
388    if (!clearAnnotations()) 
389    {
390       fprintf(stderr, "%s[%d]:  failed to clear annotations\n", FILE__, __LINE__);
391    }
392 #endif
393    //fprintf(stderr, "%s[%d]:  FIXME:  need to clear annotations??\n", FILE__, __LINE__);
394
395 }
396
397 bool Module::isShared() const
398 {
399    return !exec_->isExec();
400 }
401
402 bool Module::getAllSymbolsByType(std::vector<Symbol *> &found, Symbol::SymbolType sType)
403 {
404    unsigned orig_size = found.size();
405    std::vector<Symbol *> obj_syms;
406
407    if (!exec()->getAllSymbolsByType(obj_syms, sType))
408       return false;
409
410    for (unsigned i = 0; i < obj_syms.size(); i++) 
411    {
412       if (obj_syms[i]->getModule() == this)
413          found.push_back(obj_syms[i]);
414    }
415
416    if (found.size() > orig_size)
417    {
418       return true;
419    }
420
421    serr = No_Such_Symbol;
422    return false;
423 }
424
425 bool Module::getAllFunctions(std::vector<Function *> &ret)
426 {
427     return exec()->getAllFunctions(ret);
428 }
429
430 bool Module::operator==(Module &mod) 
431 {
432    LineInformation *li =  NULL;
433    LineInformation *li_src =  NULL;
434    bool get_anno_res = false, get_anno_res_src = false;
435    get_anno_res = getAnnotation(li, ModuleLineInfoAnno);
436    get_anno_res_src = mod.getAnnotation(li_src, ModuleLineInfoAnno);
437
438    if (get_anno_res != get_anno_res_src)
439    {
440       fprintf(stderr, "%s[%d]:  weird inconsistency with getAnnotation here\n", 
441             FILE__, __LINE__);
442       return false;
443    }
444
445    if (li) 
446    {
447       if (!li_src) 
448       {
449          fprintf(stderr, "%s[%d]:  weird inconsistency with getAnnotation here\n", 
450                FILE__, __LINE__);
451          return false;
452       }
453
454       if (li->getSize() != li_src->getSize()) 
455          return false;
456
457       if ((li != li_src)) 
458          return false;
459    }
460    else
461    {
462       if (li_src) 
463       {
464          fprintf(stderr, "%s[%d]:  weird inconsistency with getAnnotation here\n", 
465                FILE__, __LINE__);
466          return false;
467       }
468    }
469
470    return (
471          (language_==mod.language_)
472          && (addr_==mod.addr_)
473          && (fullName_==mod.fullName_)
474          && (exec_==mod.exec_)
475          );
476 }
477
478 bool Module::setName(std::string newName)
479 {
480    fullName_ = newName;
481    fileName_ = extract_pathname_tail(fullName_);
482    return true;
483 }
484
485 void Module::setLanguage(supportedLanguages lang)
486 {
487    language_ = lang;
488 }
489
490 Offset Module::addr() const
491 {
492    return addr_;
493 }
494
495 bool Module::setDefaultNamespacePrefix(string str)
496 {
497     return exec_->setDefaultNamespacePrefix(str);
498 }
499
500 void Module::serialize(SerializerBase *sb, const char *tag)
501 {
502    ifxml_start_element(sb, tag);
503    gtranslate(sb, fileName_, "fileName");
504    gtranslate(sb, fullName_, "fullName");
505    gtranslate(sb, addr_, "Address");
506    gtranslate(sb, language_, supportedLanguages2Str, "Language");
507    ifxml_end_element(sb, tag);
508
509    //  Patch up exec_ (pointer to Symtab) at a higher level??
510    //if (getSD().iomode() == sd_deserialize)
511    //   param.exec_ = parent_symtab;
512 }
513
514 Variable *Module::createVariable(std::string name, Offset offset, int size) 
515 {
516   Symbol* s = new Symbol(name, this, Symbol::ST_OBJECT, Symbol::SL_GLOBAL,
517                          Symbol::SV_DEFAULT, offset, NULL, size, 
518                          false, // is NOT in dynamic symbol table
519                          true, // is also in the static symbol table
520                          false); // not an absolute address
521   exec()->addSymbol(s, false);
522   Symbol* d = new Symbol(name, this, Symbol::ST_OBJECT, Symbol::SL_GLOBAL,
523                          Symbol::SV_DEFAULT, offset, NULL, size, 
524                          true, // dynamic version...
525                          false, // is NOT also in the static symbol table
526                          false); // not an absolute address
527   exec()->addSymbol(d, true);
528   return s->getVariable();
529 }
530
531