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