Merge branch 'master' of git.dyninst.org:/pub/dyninst
[dyninst.git] / symtabAPI / src / Object.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 // $Id: Object.C,v 1.31 2008/11/03 15:19:25 jaw Exp $
33
34 #include "Annotatable.h"
35 #include "common/h/serialize.h"
36
37 #include "Symtab.h"
38 #include "symutil.h"
39 #include "Module.h"
40 #include "Collections.h"
41 #include "annotations.h"
42 #include "Symbol.h"
43
44 #include "Aggregate.h"
45 #include "Function.h"
46 #include "Variable.h"
47
48 #include "symtabAPI/src/Object.h"
49
50 #include <iostream>
51
52 using namespace std;
53 using namespace Dyninst;
54 using namespace Dyninst::SymtabAPI;
55
56 string Symbol::emptyString("");
57
58
59 //#ifdef BINEDIT_DEBUG
60 bool ____sym_hdr_printed = false;
61 void print_symbols( std::vector< Symbol *>& allsymbols ) {
62     FILE* fd = stdout;
63     Symbol *sym;
64     std::string modname;
65     if (!____sym_hdr_printed) {
66         fprintf(fd, "%-20s  %-15s  %-10s  %5s  SEC  TYP  LN  VIS  INFO\n", 
67                 "SYMBOL", "MODULE", "ADDR", "SIZE");
68         ____sym_hdr_printed = true;
69     }
70     for (unsigned i=0; i<allsymbols.size(); i++) {
71         sym = allsymbols[i];
72         modname = sym->getModuleName();
73         //if (sym->getName() == "__gmon_start__") {
74         //if (modname == "libspecial.so" || modname == "libprofile.so") {
75         //if (sym->getLinkage() == Symbol::SL_WEAK) {
76         //if (sym->isInDynSymtab()) {
77         if (1) {
78             fprintf(fd, "%-20s  %-15s  0x%08x  %5u  %3u", 
79                 sym->getName().substr(0,20).c_str(), 
80                 //modname.size() > 15 ? modname.substr(modname.size()-15,15).c_str() : modname.c_str(),
81                 "",
82                 (unsigned)sym->getAddr(),
83                 (unsigned)sym->getSize(),
84                 sym->getSec() ? sym->getSec()->getRegionNumber() : 0
85                 );
86             switch (sym->getType()) {
87                 case Symbol::ST_UNKNOWN:  fprintf(fd, "  ???"); break;
88                 case Symbol::ST_FUNCTION: fprintf(fd, "  FUN"); break;
89                 case Symbol::ST_OBJECT:   fprintf(fd, "  OBJ"); break;
90                 case Symbol::ST_MODULE:   fprintf(fd, "  MOD"); break;
91                 case Symbol::ST_SECTION:  fprintf(fd, "  SEC"); break;
92                 case Symbol::ST_NOTYPE:   fprintf(fd, "   - "); break;
93             }
94             switch (sym->getLinkage()) {
95                 case Symbol::SL_UNKNOWN: fprintf(fd, "  ??"); break;
96                 case Symbol::SL_GLOBAL:  fprintf(fd, "  GL"); break;
97                 case Symbol::SL_LOCAL:   fprintf(fd, "  LO"); break;
98                 case Symbol::SL_WEAK:    fprintf(fd, "  WK"); break;
99             }
100             switch (sym->getVisibility()) {
101                 case Symbol::SV_UNKNOWN:   fprintf(fd, "  ???"); break;
102                 case Symbol::SV_DEFAULT:   fprintf(fd, "   - "); break;
103                 case Symbol::SV_INTERNAL:  fprintf(fd, "  INT"); break;
104                 case Symbol::SV_HIDDEN:    fprintf(fd, "  HID"); break;
105                 case Symbol::SV_PROTECTED: fprintf(fd, "  PRO"); break;
106             }
107             fprintf(fd, " ");
108             if (sym->isInSymtab())
109                 fprintf(fd, " STA");
110             if (sym->isInDynSymtab())
111                 fprintf(fd, " DYN");
112             if (sym->isAbsolute())
113                 fprintf(fd, " ABS");
114             std::string fileName;
115             std::vector<std::string> *vers;
116             if (sym->getVersionFileName(fileName))
117                 fprintf(fd, "  [%s]", fileName.c_str());
118             if (sym->getVersions(vers)) {
119                 fprintf(fd, " {");
120                 for (unsigned j=0; j < vers->size(); j++) {
121                     if (j > 0)
122                         fprintf(fd, ", ");
123                     fprintf(fd, "%s", (*vers)[j].c_str());
124                 }
125                 fprintf(fd, "}");
126             }
127             fprintf(fd,"\n");
128         }
129     }
130 }
131 void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols) {
132     dyn_hash_map< std::string, std::vector< Symbol *> >::iterator siter = symbols->begin();
133     int total_syms = 0;
134     while (siter != symbols->end()) {
135         print_symbols(siter->second);
136         total_syms += siter->second.size();
137         siter++;
138     }
139     printf("%d total symbol(s)\n", total_syms);
140 }
141 //#endif
142
143
144 const char *Dyninst::SymtabAPI::supportedLanguages2Str(supportedLanguages s)
145 {
146    switch(s) {
147       CASE_RETURN_STR(lang_Unknown);
148       CASE_RETURN_STR(lang_Assembly);
149       CASE_RETURN_STR(lang_C);
150       CASE_RETURN_STR(lang_CPlusPlus);
151       CASE_RETURN_STR(lang_GnuCPlusPlus);
152       CASE_RETURN_STR(lang_Fortran);
153       CASE_RETURN_STR(lang_Fortran_with_pretty_debug);
154       CASE_RETURN_STR(lang_CMFortran);
155    };
156    return "bad_language";
157 }
158
159
160 bool Dyninst::SymtabAPI::symbol_compare(const Symbol *s1, const Symbol *s2) 
161 {
162     // select the symbol with the lowest address
163     Offset s1_addr = s1->getAddr();
164     Offset s2_addr = s2->getAddr();
165     if (s1_addr > s2_addr)
166         return false;
167     if (s1_addr < s2_addr)
168         return true;
169
170     // symbols are co-located at the same address
171     // select the symbol which is not a function
172     if ((s1->getType() != Symbol::ST_FUNCTION) && (s2->getType() == Symbol::ST_FUNCTION))
173         return true;
174     if ((s2->getType() != Symbol::ST_FUNCTION) && (s1->getType() == Symbol::ST_FUNCTION))
175         return false;
176     
177     // symbols are both functions
178     // select the symbol which has GLOBAL linkage
179     if ((s1->getLinkage() == Symbol::SL_GLOBAL) && (s2->getLinkage() != Symbol::SL_GLOBAL))
180         return true;
181     if ((s2->getLinkage() == Symbol::SL_GLOBAL) && (s1->getLinkage() != Symbol::SL_GLOBAL))
182         return false;
183         
184     // neither function is GLOBAL
185     // select the symbol which has LOCAL linkage
186     if ((s1->getLinkage() == Symbol::SL_LOCAL) && (s2->getLinkage() != Symbol::SL_LOCAL))
187         return true;
188     if ((s2->getLinkage() == Symbol::SL_LOCAL) && (s1->getLinkage() != Symbol::SL_LOCAL))
189         return false;
190     
191     // both functions are WEAK
192     
193     // Apparently sort requires a strict weak ordering
194     // and fails for equality. our compare
195     // function behaviour should be as follows
196     // f(x,y) => !f(y,x)
197     // f(x,y),f(y,z) => f(x,z)
198     // f(x,x) = false. 
199     // So return which ever is first in the array. May be that would help.
200     return (s1 < s2);
201 }
202
203
204 bool AObject::needs_function_binding() const 
205 {
206     return false;
207 }
208
209 bool AObject::get_func_binding_table(std::vector<relocationEntry> &) const 
210 {
211     return false;
212 }
213
214 bool AObject::get_func_binding_table_ptr(const std::vector<relocationEntry> *&) const 
215 {
216     return false;
217 }
218
219 bool AObject::addRelocationEntry(relocationEntry &)
220 {
221     return true;
222 }
223
224 char *AObject::mem_image() const
225 {
226         return NULL;
227 }
228
229 DLLEXPORT ExceptionBlock::~ExceptionBlock() 
230 {
231 }
232
233 DLLEXPORT ExceptionBlock::ExceptionBlock() : tryStart_(0), trySize_(0), 
234                                                                 catchStart_(0), hasTry_(false) 
235 {
236 }
237
238 DLLEXPORT Offset ExceptionBlock::catchStart() const 
239 {
240         return catchStart_;
241 }
242
243 DLLEXPORT relocationEntry::relocationEntry(const relocationEntry& ra) : 
244    Serializable(),
245    target_addr_(ra.target_addr_), 
246    rel_addr_(ra.rel_addr_), 
247    addend_ (ra.addend_),
248    rtype_ (ra.rtype_),
249    name_(ra.name_), 
250    dynref_(ra.dynref_), relType_(ra.relType_) 
251 {
252 }
253
254 DLLEXPORT Offset relocationEntry::target_addr() const 
255 {
256         return target_addr_;
257 }
258
259 DLLEXPORT Offset relocationEntry::rel_addr() const 
260 {
261         return rel_addr_;
262 }
263
264 DLLEXPORT const string &relocationEntry::name() const 
265 {
266         return name_;
267 }
268
269 DLLEXPORT Symbol *relocationEntry::getDynSym() const 
270 {
271     return dynref_;
272 }
273
274 DLLEXPORT bool relocationEntry::addDynSym(Symbol *dynref) 
275 {
276     dynref_ = dynref;
277     return true;
278 }
279
280 DLLEXPORT unsigned long relocationEntry::getRelType() const 
281 {
282     return relType_;
283 }
284
285 DLLEXPORT Symbol::~Symbol ()
286 {
287    std::string *sfa_p = NULL;
288
289    if (getAnnotation(sfa_p, SymbolFileNameAnno))
290    {
291       if (!sfa_p) 
292       {
293          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
294       }
295       else
296       {
297          delete (sfa_p);
298       }
299    }
300 }
301
302 DLLEXPORT Symbol::Symbol(const Symbol& s) :
303    Serializable(),
304    AnnotatableSparse(),
305    module_(s.module_), 
306    type_(s.type_), linkage_(s.linkage_), visibility_(s.visibility_),
307    addr_(s.addr_), sec_(s.sec_), size_(s.size_), 
308    isInDynsymtab_(s.isInDynsymtab_), isInSymtab_(s.isInSymtab_), 
309    isAbsolute_(s.isAbsolute_),
310    aggregate_(s.aggregate_),
311    mangledName_(s.mangledName_), 
312    prettyName_(s.prettyName_), 
313    typedName_(s.typedName_), 
314    tag_(s.tag_), 
315    framePtrRegNum_(s.framePtrRegNum_),
316    retType_(s.retType_), 
317    moduleName_(s.moduleName_) 
318 {
319 #if 0
320    Annotatable <std::string, symbol_file_name_a> &sfa = *this;
321    const Annotatable <std::string, symbol_file_name_a> &sfa_src = s;
322    if (sfa_src.size())
323       sfa.addAnnotation(sfa_src[0]);
324
325    Annotatable <std::vector<std::string>, symbol_version_names_a> &sva = *this;
326    const Annotatable <std::vector<std::string>, symbol_version_names_a> &sva_src = s;
327    if (sva_src.size())
328       sva.addAnnotation(sva_src[0]);
329
330    Annotatable<localVarCollection, symbol_variables_a, true> &lvA = *this;
331    const Annotatable<localVarCollection, symbol_variables_a, true> &lvA_src = s;
332    if (lvA_src.size())
333       lvA.addAnnotation(lvA_src[0]);
334
335    Annotatable<localVarCollection, symbol_parameters_a, true> &pA = *this;
336    const Annotatable<localVarCollection, symbol_parameters_a, true> &pA_src = s;
337    if (pA_src.size())
338       pA.addAnnotation(pA_src[0]);
339    fprintf(stderr, "%s[%d]:  FIXME??  copy annotations here or not??\n", FILE__, __LINE__);
340 #endif
341
342    std::string *sfa_p = NULL;
343    if (s.getAnnotation(sfa_p, SymbolFileNameAnno))
344    {
345       if (!sfa_p) 
346       {
347          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
348       }
349       else
350       {
351          std::string *sfa_p2 = new std::string(*sfa_p);
352
353          if (!addAnnotation(sfa_p2, SymbolFileNameAnno)) 
354          {
355             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
356          }
357       }
358    }
359
360    std::vector<std::string> *svn_p = NULL;
361    if (s.getAnnotation(svn_p, SymbolVersionNamesAnno))
362    {
363       if (!svn_p) 
364       {
365          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
366       }
367       else
368       {
369          //  note:  in an older version we just copied one element from this
370          // vector when the symbol got copied.  I think this is incorrect.
371          //fprintf(stderr, "%s[%d]:  alloc'ing new vector for symbol versions\n", FILE__, __LINE__);
372
373          //  if we alloc here, probably want to check in dtor to make
374          //  sure that we are deleting this if it exists.
375          //std::vector<std::string> *svn_p2 = new std::vector<std::string>();
376
377          //for (unsigned int i = 0; i < svn_p->size(); ++i)
378          //{
379          //   svn_p2->push_back(std::string((*svn_p)[i]));
380          //}
381
382          if (!addAnnotation(svn_p, SymbolVersionNamesAnno))
383          {
384             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
385          }
386       }
387    }
388
389    localVarCollection *vars_p = NULL;
390    if (s.getAnnotation(vars_p, FunctionLocalVariablesAnno))
391    {
392       if (!vars_p) 
393       {
394          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
395       }
396       else
397       {
398          if (!addAnnotation(vars_p, FunctionLocalVariablesAnno))
399          {
400             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
401          }
402       }
403    }
404
405    localVarCollection *params_p = NULL;
406    if (s.getAnnotation(params_p, FunctionParametersAnno))
407    {
408       if (!params_p) 
409       {
410          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
411       }
412       else
413       {
414          if (!addAnnotation(params_p, FunctionParametersAnno))
415          {
416             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
417          }
418       }
419    }
420 }
421
422 DLLEXPORT Symbol& Symbol::operator=(const Symbol& s) 
423 {
424    module_  = s.module_;
425    type_    = s.type_;
426    linkage_ = s.linkage_;
427    addr_    = s.addr_;
428    sec_     = s.sec_;
429    size_    = s.size_;
430    isInDynsymtab_ = s.isInDynsymtab_;
431    isInSymtab_ = s.isInSymtab_;
432    isAbsolute_ = s.isAbsolute_;
433    aggregate_ = s.aggregate_;
434    tag_     = s.tag_;
435    mangledName_ = s.mangledName_;
436    prettyName_ = s.prettyName_;
437    typedName_ = s.typedName_;
438    framePtrRegNum_ = s.framePtrRegNum_;
439
440    std::string *sfa_p = NULL;
441
442    if (s.getAnnotation(sfa_p, SymbolFileNameAnno))
443    {
444       if (!sfa_p) 
445       {
446          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
447       }
448       else
449       {
450          std::string *sfa_p2 = new std::string(*sfa_p);
451
452          if (!addAnnotation(sfa_p2, SymbolFileNameAnno))
453          {
454             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
455          }
456       }
457    }
458
459    std::vector<std::string> *svn_p = NULL;
460    if (s.getAnnotation(svn_p, SymbolVersionNamesAnno))
461    {
462       if (!svn_p) 
463       {
464          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
465       }
466       else
467       {
468          //  note:  in an older version we just copied one element from this
469          // vector when the symbol got copied.  I think this is incorrect.
470          //fprintf(stderr, "%s[%d]:  alloc'ing new vector for symbol versions\n", FILE__, __LINE__);
471
472          //  if we alloc here, probably want to check in dtor to make
473          //  sure that we are deleting this if it exists.
474          //std::vector<std::string> *svn_p2 = new std::vector<std::string>();
475
476          //for (unsigned int i = 0; i < svn_p->size(); ++i)
477          //{
478          //   svn_p2->push_back(std::string((*svn_p)[i]));
479          //}
480
481          if (!addAnnotation(svn_p, SymbolVersionNamesAnno))
482          {
483             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
484          }
485       }
486    }
487
488    localVarCollection *vars_p = NULL;
489    if (s.getAnnotation(vars_p, FunctionLocalVariablesAnno))
490    {
491       if (!vars_p) 
492       {
493          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
494       }
495       else
496       {
497          if (!addAnnotation(vars_p, FunctionLocalVariablesAnno))
498          {
499             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
500          }
501       }
502    }
503
504    localVarCollection *params_p = NULL;
505    if (s.getAnnotation(params_p, FunctionParametersAnno))
506    {
507       if (!params_p) 
508       {
509          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
510       }
511       else
512       {
513          if (!addAnnotation(params_p, FunctionParametersAnno))
514          {
515             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
516          }
517       }
518    }
519 #if 0
520 #if 1 
521    fprintf(stderr, "%s[%d]:  WARNING:  assignment ctor not assigning local variables and parameters\n", FILE__, __LINE__);
522 #else
523    Annotatable <std::string, symbol_file_name_a> &sfa = *this;
524    const Annotatable <std::string, symbol_file_name_a> &sfa_src = s;
525    if (sfa_src.size())
526       sfa.addAnnotation(sfa_src[0]);
527
528    Annotatable <std::vector<std::string>, symbol_version_names_a> &sva = *this;
529    const Annotatable <std::vector<std::string>, symbol_version_names_a> &sva_src = s;
530    if (sva_src.size())
531       sva.addAnnotation(sva_src[0]);
532
533    Annotatable<localVarCollection, symbol_variables_a, true> &lvA = *this;
534    const Annotatable<localVarCollection, symbol_variables_a,true> &lvA_src = s;
535    if (lvA_src.size())
536       lvA.addAnnotation(lvA_src[0]);
537
538    Annotatable<localVarCollection, symbol_parameters_a, true> &pA = *this;
539    const Annotatable<localVarCollection, symbol_parameters_a,true> &pA_src = s;
540    if (pA_src.size())
541       pA.addAnnotation(pA_src[0]);
542 #endif
543 #endif
544    return *this;
545 }
546
547 DLLEXPORT const string& Symbol::getMangledName() const 
548 {
549     return mangledName_;
550 }
551
552 DLLEXPORT const string& Symbol::getPrettyName() const 
553 {
554     return prettyName_;
555 }
556
557 DLLEXPORT const string& Symbol::getTypedName() const 
558 {
559     return typedName_;
560 }
561
562 DLLEXPORT const string& Symbol::getModuleName() const 
563 {
564     if (module_)
565         return module_->fullName();
566     else
567         return moduleName_;
568 }
569
570 DLLEXPORT Module* Symbol::getModule() const 
571 {
572     return module_;
573 }
574
575 DLLEXPORT bool Symbol::setModule(Module *mod) 
576 {
577         module_ = mod; 
578         return true;
579 }
580
581 DLLEXPORT Symbol::SymbolType Symbol::getType() const 
582 {
583     return type_;
584 }
585
586 DLLEXPORT Symbol::SymbolLinkage Symbol::getLinkage() const 
587 {
588     return linkage_;
589 }
590
591 DLLEXPORT Symbol::SymbolVisibility Symbol::getVisibility() const 
592 {
593     return visibility_;
594 }
595
596 DLLEXPORT Offset Symbol::getAddr() const 
597 {
598     return addr_;
599 }
600
601 DLLEXPORT Region *Symbol::getSec() const 
602 {
603     return sec_;
604 }
605
606 DLLEXPORT bool Symbol::isInDynSymtab() const 
607 {
608     return isInDynsymtab_;
609 }
610
611 DLLEXPORT bool Symbol::isInSymtab() const 
612 {
613     return isInSymtab_;
614 }
615
616 DLLEXPORT bool Symbol::isAbsolute() const
617 {
618     return isAbsolute_;
619 }
620
621 DLLEXPORT bool Symbol::isFunction() const
622 {
623     return (getFunction() != NULL);
624 }
625
626 DLLEXPORT bool Symbol::setFunction(Function *func)
627 {
628     aggregate_ = func;
629     return true;
630 }
631
632 DLLEXPORT Function * Symbol::getFunction() const
633 {
634     return dynamic_cast<Function *>(aggregate_);
635 }
636
637 DLLEXPORT bool Symbol::isVariable() const 
638 {
639     return (getVariable() != NULL);
640 }
641
642 DLLEXPORT bool Symbol::setVariable(Variable *var) 
643 {
644     aggregate_ = var;
645     return true;
646 }
647
648 DLLEXPORT Variable * Symbol::getVariable() const
649 {
650     return dynamic_cast<Variable *>(aggregate_);
651 }
652
653 DLLEXPORT unsigned Symbol::getSize() const 
654 {
655     return size_;
656 }
657
658 DLLEXPORT bool  Symbol::setSize(unsigned ns)
659 {
660         size_ = ns;
661         return true;
662 }
663
664 DLLEXPORT Symbol::SymbolTag Symbol::tag() const 
665 {
666     return tag_;
667 }
668
669 DLLEXPORT bool Symbol::setModuleName(string module)
670 {
671         moduleName_ = module;
672         return true;
673 }
674
675 DLLEXPORT bool Symbol::setAddr (Offset newAddr) 
676 {
677       addr_ = newAddr;
678       return true;
679 }
680
681 DLLEXPORT bool Symbol::setDynSymtab() 
682 {
683     isInDynsymtab_= true;
684     return true;
685 }
686
687 DLLEXPORT bool Symbol::clearDynSymtab() 
688 {
689     isInDynsymtab_ = false;
690     return true;
691 }
692
693 DLLEXPORT bool Symbol::setIsInSymtab() 
694 {
695     isInSymtab_= true;
696     return true;
697 }
698
699 DLLEXPORT bool Symbol::clearIsInSymtab() 
700 {
701     isInSymtab_= false;
702     return true;
703 }
704
705 DLLEXPORT bool Symbol::setIsAbsolute()
706 {
707     isAbsolute_= true;
708     return true;
709 }
710
711 DLLEXPORT bool Symbol::clearIsAbsolute()
712 {
713     isAbsolute_= false;
714     return true;
715 }
716
717 DLLEXPORT Symbol::Symbol()
718    : //name_("*bad-symbol*"), module_("*bad-module*"),
719     module_(NULL), type_(ST_UNKNOWN), linkage_(SL_UNKNOWN), addr_(0), sec_(NULL), size_(0),
720     isInDynsymtab_(false), isInSymtab_(true), isAbsolute_(false), 
721     aggregate_(NULL),
722     tag_(TAG_UNKNOWN),
723     framePtrRegNum_(-1), retType_(NULL), moduleName_("")
724 {
725    // note: this ctor is called surprisingly often (when we have
726    // vectors of Symbols and/or dictionaries of Symbols).  So, make it fast.
727 }
728
729 DLLEXPORT Symbol::Symbol(const string iname, const string imodule,
730     SymbolType itype, SymbolLinkage ilinkage, SymbolVisibility ivisibility, Offset iaddr,
731     Region *isec, unsigned size,  bool isInDynSymtab, bool isInSymtab,
732     bool isAbsolute)
733     : type_(itype), linkage_(ilinkage), visibility_(ivisibility),
734     addr_(iaddr), sec_(isec), size_(size), isInDynsymtab_(isInDynSymtab),
735     isInSymtab_(isInSymtab), isAbsolute_(isAbsolute), tag_(TAG_UNKNOWN), framePtrRegNum_(-1),
736     retType_(NULL)
737 {
738         module_ = NULL;
739         moduleName_ = imodule;
740         mangledName_ = iname;
741         aggregate_ = NULL;
742 }
743
744 DLLEXPORT Symbol::Symbol(const string iname, Module *mod,
745     SymbolType itype, SymbolLinkage ilinkage, SymbolVisibility ivisibility, Offset iaddr,
746     Region *isec, unsigned size,  bool isInDynSymtab, bool isInSymtab,
747     bool isAbsolute)
748     : module_(mod), type_(itype), linkage_(ilinkage), visibility_(ivisibility),
749     addr_(iaddr), sec_(isec), size_(size),  isInDynsymtab_(isInDynSymtab), 
750     isInSymtab_(isInSymtab), isAbsolute_(isAbsolute), tag_(TAG_UNKNOWN), framePtrRegNum_(-1),
751     retType_(NULL)
752 {
753     mangledName_ = iname;
754     aggregate_ = NULL;
755 }
756
757
758 DLLEXPORT bool Symbol::setSymbolType(SymbolType sType)
759 {
760     if ((sType != ST_UNKNOWN)&&
761         (sType != ST_FUNCTION)&&
762         (sType != ST_OBJECT)&&
763         (sType != ST_MODULE)&&
764         (sType != ST_NOTYPE))
765         return false;
766     
767     SymbolType oldType = type_; 
768     type_ = sType;
769     if (module_->exec())
770         module_->exec()->changeType(this, oldType);
771
772     // TODO: update aggregate with information
773     
774     return true;
775 }
776
777 DLLEXPORT bool Symbol::setVersionFileName(std::string &fileName)
778 {
779    std::string *fn_p = NULL;
780    if (getAnnotation(fn_p, SymbolFileNameAnno)) 
781    {
782       if (!fn_p) 
783       {
784          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
785       }
786       else
787       {
788          fprintf(stderr, "%s[%d]:  WARNING, already have filename set for symbol %s\n", 
789                  FILE__, __LINE__, getMangledName().c_str());
790       }
791       return false;
792    }
793    else
794    {
795       //  not sure if we need to copy here or not, so let's do it...
796       std::string *fn = new std::string(fileName);
797       if (!addAnnotation(fn, SymbolFileNameAnno)) 
798       {
799          fprintf(stderr, "%s[%d]:  failed to add anno here\n", FILE__, __LINE__);
800          return false;
801       }
802       return true;
803    }
804
805    return false;
806 }
807
808 DLLEXPORT bool Symbol::setVersions(std::vector<std::string> &vers)
809 {
810    std::vector<std::string> *vn_p = NULL;
811    if (getAnnotation(vn_p, SymbolVersionNamesAnno)) 
812    {
813       if (!vn_p) 
814       {
815          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
816       }
817       else
818          fprintf(stderr, "%s[%d]:  WARNING, already have versions set for symbol %s\n", FILE__, __LINE__, getMangledName().c_str());
819       return false;
820    }
821    else
822    {
823       if (!addAnnotation(&vers, SymbolVersionNamesAnno)) 
824       {
825          fprintf(stderr, "%s[%d]:  failed to add anno here\n", FILE__, __LINE__);
826       }
827    }
828
829    return true;
830 }
831
832 DLLEXPORT bool Symbol::getVersionFileName(std::string &fileName)
833 {
834    std::string *fn_p = NULL;
835
836    if (getAnnotation(fn_p, SymbolFileNameAnno)) 
837    {
838       if (!fn_p) 
839       {
840          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
841       }
842       else
843          fileName = *fn_p;
844
845       return true;
846    }
847
848    return false;
849
850 #if 0
851    Annotatable<std::string, symbol_file_name_a> &fn = *this;
852    if (!fn.size()) {
853       return false;
854    }
855    fileName = fn[0];
856    return true;
857 #endif
858 }
859
860 DLLEXPORT bool Symbol::getVersions(std::vector<std::string> *&vers)
861 {
862    std::vector<std::string> *vn_p = NULL;
863
864    if (getAnnotation(vn_p, SymbolVersionNamesAnno)) 
865    {
866       if (!vn_p) 
867       {
868          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
869       }
870       else
871       {
872          vers = vn_p;
873          return true;
874       } 
875    }
876
877    return false;
878
879 #if 0
880    Annotatable<std::vector<std::string>, symbol_version_names_a> &sv = *this;
881    if (!sv.size()) {
882       return false;
883    }
884    vers = &(sv[0]);
885    return true;
886 #endif
887 }
888
889 void Symbol::serialize(SerializerBase *s, const char *tag) 
890 {
891    try {
892       ifxml_start_element(s, tag);
893       gtranslate(s, type_, symbolType2Str, "type");
894       gtranslate(s, linkage_, symbolLinkage2Str, "linkage");
895       gtranslate(s, tag_, symbolTag2Str, "tag");
896       gtranslate(s, visibility_, symbolVisibility2Str, "visibility");
897       gtranslate(s, addr_, "addr");
898       gtranslate(s, size_, "size");
899       gtranslate(s, isInDynsymtab_, "isInDynsymtab");
900       gtranslate(s, isInSymtab_, "isInSymtab");
901       gtranslate(s, isAbsolute_, "isAbsolute");
902       gtranslate(s, prettyName_, "prettyName", "prettyName");
903       gtranslate(s, mangledName_, "mangledName", "mangledName");
904       gtranslate(s, typedName_, "typedName", "typedName");
905       gtranslate(s, framePtrRegNum_, "framePtrRegNum");
906       //  Note:  have to deal with retType_ here?? Probably use type id.
907       gtranslate(s, moduleName_, "moduleName");
908       ifxml_end_element(s, "Symbol");
909 #if 0
910       symbol_start(param);
911       translate(param.type_, "type");
912       translate(param.linkage_, "linkage");
913       translate(param.tag_, "tag");
914       getSD().translate(param.addr_, "addr");
915       getSD().translate(param.size_, "size");
916       getSD().translate(param.isInDynsymtab_, "isInDynsymtab");
917       getSD().translate(param.isInSymtab_, "isInSymtab");
918       getSD().translate(param.prettyName_, "prettyName", "prettyName");
919       getSD().translate(param.mangledName_, "mangledName", "mangledName");
920       getSD().translate(param.typedName_, "typedName", "typedName");
921       getSD().translate(param.framePtrRegNum_, "framePtrRegNum");
922       //  Note:  have to deal with retType_ here?? Probably use type id.
923       getSD().translate(param.moduleName_, "moduleName");
924       symbol_end(param);
925 #endif
926    } SER_CATCH("Symbol");
927 }
928
929 ostream& Dyninst::SymtabAPI::operator<< (ostream &os, const Symbol &s) 
930 {
931     return os << "{"
932               << " mangled=" << s.getMangledName()
933               << " pretty="  << s.getPrettyName()
934               << " module="  << s.module_
935         //<< " type="    << (unsigned) s.type_
936               << " type="    << s.symbolType2Str(s.type_)
937         //<< " linkage=" << (unsigned) s.linkage_
938               << " linkage=" << s.symbolLinkage2Str(s.linkage_)
939               << " addr=0x"    << hex << s.addr_ << dec
940         //<< " tag="     << (unsigned) s.tag_
941               << " tag="     << s.symbolTag2Str(s.tag_)
942               << " isAbs="   << s.isAbsolute_
943               << (s.isFunction() ? " [FUNC]" : "")
944               << (s.isVariable() ? " [VAR]" : "")
945               << (s.isInSymtab_ ? " [STA]" : "")
946               << (s.isInDynsymtab_ ? " [DYN]" : "")
947               << " }" << endl;
948 }
949
950 #ifdef DEBUG 
951
952 ostream & relocationEntry::operator<< (ostream &s) const {
953    s << "target_addr_ = " << target_addr_ << endl;
954    s << "rel_addr_ = " << rel_addr_ << endl;
955    s << "addend_ = " << addend_ << endl;
956    s << "rtype_ = " << rtype_ << endl;
957    s << "name_ = " << name_ << endl;
958    return s; 
959 }
960
961 ostream &operator<<(ostream &os, relocationEntry &q) {
962    return q.operator<<(os);
963 }
964
965 /**************************************************
966  *
967  *  Stream based debuggering output - for regreesion testing.
968  *  Dump info on state of object *this....
969  *
970  **************************************************/
971
972
973 const ostream &AObject::dump_state_info(ostream &s) {
974
975    // key and value for distc hash iter.... 
976    string str;
977    Symbol sym;
978    hash_map<string, std::vector <Symbol> >::iterator symbols_iter = symbols_.begin();
979
980    s << "Debugging Info for AObject (address) : " << this << endl;
981
982    s << " file_ = " << file_ << endl;
983    s << " symbols_ = " << endl;
984
985    // and loop over all the symbols, printing symbol name and data....
986    //  or try at least....
987    for(;symbols_iter!=symbols_.end();symbols_iter++)
988    {
989       str = symbols_iter->first
990          for(int i = 0; i<symbols_iter->second->size(); i++)
991          {
992             sym = (*(symbols_iter->second))[i];
993             s << "  key = " << str << " val " << sym << endl;
994          }
995    }
996    s << " code_ptr_ = " << code_ptr_ << endl;
997    s << " code_off_ = " << code_off_ << endl;
998    s << " code_len_ = " << code_len_ << endl;
999    s << " data_ptr_ = " << data_ptr_ << endl;
1000    s << " data_off_ = " << data_off_ << endl;
1001    s << " data_len_ = " << data_len_ << endl;
1002    return s;
1003 }
1004
1005 #endif
1006
1007 DLLEXPORT AObject::AObject()
1008 {
1009 }       
1010
1011 DLLEXPORT unsigned AObject::nsymbols () const 
1012
1013    return symbols_.size(); 
1014 }
1015
1016 DLLEXPORT bool AObject::get_symbols(string & name, 
1017       std::vector<Symbol *> &symbols ) 
1018 {
1019    if ( symbols_.find(name) == symbols_.end()) {
1020       return false;
1021    }
1022
1023    symbols = symbols_[name];
1024    return true;
1025 }
1026
1027 DLLEXPORT char* AObject::code_ptr () const 
1028
1029    return code_ptr_; 
1030 }
1031
1032 DLLEXPORT Offset AObject::code_off () const 
1033
1034    return code_off_; 
1035 }
1036
1037 DLLEXPORT Offset AObject::code_len () const 
1038
1039    return code_len_; 
1040 }
1041
1042 DLLEXPORT char* AObject::data_ptr () const 
1043
1044    return data_ptr_; 
1045 }
1046
1047 DLLEXPORT Offset AObject::data_off () const 
1048
1049    return data_off_; 
1050 }
1051
1052 DLLEXPORT Offset AObject::data_len () const 
1053
1054    return data_len_; 
1055 }
1056
1057 DLLEXPORT bool AObject::is_aout() const 
1058 {
1059    return is_aout_;  
1060 }
1061
1062 DLLEXPORT bool AObject::isDynamic() const 
1063 {
1064    return is_dynamic_;  
1065 }
1066
1067 DLLEXPORT unsigned AObject::no_of_sections() const 
1068
1069    return no_of_sections_; 
1070 }
1071
1072 DLLEXPORT unsigned AObject::no_of_symbols() const 
1073
1074    return no_of_symbols_;  
1075 }
1076
1077 DLLEXPORT bool AObject::getAllExceptions(std::vector<ExceptionBlock *>&excpBlocks) const
1078 {
1079    for (unsigned i=0;i<catch_addrs_.size();i++)
1080       excpBlocks.push_back(new ExceptionBlock(catch_addrs_[i]));
1081
1082    return true;
1083 }
1084
1085 DLLEXPORT std::vector<Region *> AObject::getAllRegions() const
1086 {
1087    return regions_;     
1088 }
1089
1090 DLLEXPORT Offset AObject::loader_off() const 
1091
1092    return loader_off_; 
1093 }
1094
1095 DLLEXPORT unsigned AObject::loader_len() const 
1096
1097    return loader_len_; 
1098 }
1099
1100 DLLEXPORT int AObject::getAddressWidth() const 
1101
1102    return addressWidth_nbytes; 
1103 }
1104
1105 DLLEXPORT bool AObject::have_deferred_parsing(void) const
1106
1107    return deferredParse;
1108 }
1109
1110 DLLEXPORT void * AObject::getErrFunc() const 
1111 {
1112    return (void *) err_func_; 
1113 }
1114
1115 DLLEXPORT dyn_hash_map< string, std::vector< Symbol *> > *AObject::getAllSymbols() 
1116
1117    return &(symbols_);
1118 }
1119
1120 DLLEXPORT AObject::~AObject() 
1121 {
1122 }
1123
1124 // explicitly protected
1125 DLLEXPORT AObject::AObject(MappedFile *mf_, MappedFile *mfd, void (*err_func)(const char *)) 
1126 : mf(mf_), mfForDebugInfo(mfd), code_ptr_(0), code_off_(0),
1127    code_len_(0), data_ptr_(0), data_off_(0), data_len_(0),loader_off_(0),
1128    loader_len_(0), is_dynamic_(false), deferredParse(false), err_func_(err_func),
1129    addressWidth_nbytes(4) 
1130 {
1131 }
1132
1133 DLLEXPORT AObject::AObject(const AObject &obj)
1134 : mf(obj.mf), mfForDebugInfo(obj.mfForDebugInfo), symbols_(obj.symbols_), 
1135    code_ptr_(obj.code_ptr_), code_off_(obj.code_off_), 
1136    code_len_(obj.code_len_), data_ptr_(obj.data_ptr_), 
1137    data_off_(obj.data_off_), data_len_(obj.data_len_), 
1138    loader_off_(obj.loader_off_), loader_len_(obj.loader_len_), is_dynamic_(obj.is_dynamic_),
1139    deferredParse(false), err_func_(obj.err_func_), addressWidth_nbytes(4)
1140 {
1141
1142
1143 DLLEXPORT AObject& AObject::operator=(const AObject &obj) 
1144 {   
1145    if (this == &obj) {
1146       return *this;
1147    }
1148
1149    mf = obj.mf;
1150    mfForDebugInfo = obj.mfForDebugInfo;
1151    symbols_   = obj.symbols_;
1152    code_ptr_  = obj.code_ptr_;
1153    code_off_  = obj.code_off_;
1154    code_len_  = obj.code_len_;
1155    data_ptr_  = obj.data_ptr_;
1156    data_off_  = obj.data_off_;
1157    data_len_  = obj.data_len_;
1158    err_func_  = obj.err_func_;
1159    loader_off_ = obj.loader_off_; 
1160    loader_len_ = obj.loader_len_;
1161    is_dynamic_ = obj.is_dynamic_;
1162    addressWidth_nbytes = obj.addressWidth_nbytes;
1163    return *this;
1164 }
1165
1166 //  a helper routine that selects a language based on information from the symtab
1167 supportedLanguages AObject::pickLanguage(string &working_module, char *working_options,
1168       supportedLanguages working_lang)
1169 {
1170    supportedLanguages lang = lang_Unknown;
1171    static int sticky_fortran_modifier_flag = 0;
1172    // (2) -- check suffixes -- try to keep most common suffixes near the top of the checklist
1173    string::size_type len = working_module.length();
1174    if((len>2) && (working_module.substr(len-2,2) == string(".c"))) lang = lang_C;
1175    else if ((len>2) && (working_module.substr(len-2,2) == string(".C"))) lang = lang_CPlusPlus;
1176    else if ((len>4) && (working_module.substr(len-4,4) == string(".cpp"))) lang = lang_CPlusPlus;
1177    else if ((len>2) && (working_module.substr(len-2,2) == string(".F"))) lang = lang_Fortran;
1178    else if ((len>2) && (working_module.substr(len-2,2) == string(".f"))) lang = lang_Fortran;
1179    else if ((len>3) && (working_module.substr(len-3,3) == string(".cc"))) lang = lang_C;
1180    else if ((len>2) && (working_module.substr(len-2,2) == string(".a"))) lang = lang_Assembly; // is this right?
1181    else if ((len>2) && (working_module.substr(len-2,2) == string(".S"))) lang = lang_Assembly;
1182    else if ((len>2) && (working_module.substr(len-2,2) == string(".s"))) lang = lang_Assembly;
1183    else
1184    {
1185       //(3) -- try to use options string -- if we have 'em
1186       if (working_options)
1187       {
1188          //  NOTE:  a binary is labeled "gcc2_compiled" even if compiled w/g77 -- thus this is
1189          //  quite inaccurate to make such assumptions
1190          if (strstr(working_options, "gcc"))
1191             lang = lang_C;
1192          else if (strstr(working_options, "g++"))
1193             lang = lang_CPlusPlus;
1194       }
1195    }
1196    //  This next section tries to determine the version of the debug info generator for a
1197    //  Sun fortran compiler.  Some leave the underscores on names in the debug info, and some
1198    //  have the "pretty" names, we need to detect this in order to properly read the debug.
1199    if (working_lang == lang_Fortran)
1200    {
1201       if (sticky_fortran_modifier_flag)
1202       {
1203          //cerr << FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug." << endl;
1204          working_lang = lang_Fortran_with_pretty_debug;
1205       }
1206       else if (working_options)
1207       {
1208          char *dbg_gen = NULL;
1209          //cerr << FILE__ << __LINE__ << ":  OPT: " << working_options << endl;                 
1210          if (NULL != (dbg_gen = strstr(working_options, "DBG_GEN=")))
1211          {
1212             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen << endl;
1213             // Sun fortran compiler (probably), need to examine version
1214             char *dbg_gen_ver_maj = dbg_gen + strlen("DBG_GEN=");
1215             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen_ver_maj << endl;
1216             char *next_dot = strchr(dbg_gen_ver_maj, '.');
1217             if (NULL != next_dot)
1218             {
1219                next_dot = '\0';  //terminate major version number string
1220                int ver_maj = atoi(dbg_gen_ver_maj);
1221                //cerr <<"Major Debug Ver. "<<ver_maj<< endl;
1222                if (ver_maj < 3)
1223                {
1224                   working_lang = lang_Fortran_with_pretty_debug;
1225                   sticky_fortran_modifier_flag = 1;
1226                   //cerr << __FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug.  " << "Major Debug Ver. "<<ver_maj<<endl;
1227                }
1228             }
1229          }
1230       }
1231    }
1232    return lang;
1233 }
1234
1235 SymbolIter::SymbolIter( Object & obj ) 
1236 : symbols(obj.getAllSymbols()), currentPositionInVector(0) 
1237 {
1238    symbolIterator = obj.getAllSymbols()->begin();
1239 }
1240
1241 SymbolIter::SymbolIter( const SymbolIter & src ) 
1242 : symbols(src.symbols),currentPositionInVector(0),
1243    symbolIterator( src.symbolIterator ) 
1244 {
1245 }
1246
1247 SymbolIter::~SymbolIter () 
1248 {
1249 }
1250
1251
1252 void SymbolIter::reset () 
1253 {
1254    currentPositionInVector = 0;
1255    symbolIterator = symbols->begin();
1256 }
1257
1258 SymbolIter::operator bool() const
1259 {
1260    return (symbolIterator!=symbols->end());
1261 }
1262
1263 void SymbolIter::operator++ ( int ) 
1264 {
1265    if ( currentPositionInVector + 1 < (symbolIterator->second).size())
1266    {
1267       currentPositionInVector++;
1268       return;
1269    }
1270
1271    /* Otherwise, we need a new std::vector. */
1272    currentPositionInVector = 0;                 
1273    symbolIterator++;
1274 }
1275
1276 const string & SymbolIter::currkey() const 
1277 {
1278    return symbolIterator->first;
1279 }
1280
1281 /* If it's important that this be const, we could try to initialize
1282    currentVector to '& symbolIterator.currval()' in the constructor. */
1283
1284 Symbol *SymbolIter::currval() 
1285 {
1286    return ((symbolIterator->second)[ currentPositionInVector ]);
1287 }
1288