windows build fixes and some more work on symtab serialization
[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 "symutil.h"
35 #include "Annotatable.h"
36 #include "common/h/serialize.h"
37
38 #include "Symtab.h"
39 #include "Module.h"
40 #include "Region.h"
41 #include "Collections.h"
42 #include "annotations.h"
43 #include "Symbol.h"
44
45 #include "Aggregate.h"
46 #include "Function.h"
47 #include "Variable.h"
48
49 #include "symtabAPI/src/Object.h"
50
51 #include <iostream>
52
53 using namespace std;
54 using namespace Dyninst;
55 using namespace Dyninst::SymtabAPI;
56
57 string Symbol::emptyString("");
58
59
60 //#ifdef BINEDIT_DEBUG
61 bool ____sym_hdr_printed = false;
62 void print_symbols( std::vector< Symbol *>& allsymbols ) {
63     FILE* fd = stdout;
64     Symbol *sym;
65     std::string modname;
66     if (!____sym_hdr_printed) {
67         fprintf(fd, "%-20s  %-15s  %-10s  %5s  SEC  TYP  LN  VIS  INFO\n", 
68                 "SYMBOL", "MODULE", "ADDR", "SIZE");
69         ____sym_hdr_printed = true;
70     }
71     for (unsigned i=0; i<allsymbols.size(); i++) {
72         sym = allsymbols[i];
73         modname = sym->getModuleName();
74         //if (sym->getName() == "__gmon_start__") {
75         //if (modname == "libspecial.so" || modname == "libprofile.so") {
76         //if (sym->getLinkage() == Symbol::SL_WEAK) {
77         //if (sym->isInDynSymtab()) {
78         if (1) {
79             fprintf(fd, "%-20s  %-15s  0x%08x  %5u  %3u", 
80                 sym->getName().substr(0,20).c_str(), 
81                 //modname.size() > 15 ? modname.substr(modname.size()-15,15).c_str() : modname.c_str(),
82                 "",
83                 (unsigned)sym->getAddr(),
84                 (unsigned)sym->getSize(),
85                 sym->getSec() ? sym->getSec()->getRegionNumber() : 0
86                 );
87             switch (sym->getType()) {
88                 case Symbol::ST_UNKNOWN:  fprintf(fd, "  ???"); break;
89                 case Symbol::ST_FUNCTION: fprintf(fd, "  FUN"); break;
90                 case Symbol::ST_OBJECT:   fprintf(fd, "  OBJ"); break;
91                 case Symbol::ST_MODULE:   fprintf(fd, "  MOD"); break;
92                 case Symbol::ST_SECTION:  fprintf(fd, "  SEC"); break;
93                 case Symbol::ST_DELETED:  fprintf(fd, "  DEL"); break;
94                 case Symbol::ST_NOTYPE:   fprintf(fd, "   - "); break;
95             }
96             switch (sym->getLinkage()) {
97                 case Symbol::SL_UNKNOWN: fprintf(fd, "  ??"); break;
98                 case Symbol::SL_GLOBAL:  fprintf(fd, "  GL"); break;
99                 case Symbol::SL_LOCAL:   fprintf(fd, "  LO"); break;
100                 case Symbol::SL_WEAK:    fprintf(fd, "  WK"); break;
101             }
102             switch (sym->getVisibility()) {
103                 case Symbol::SV_UNKNOWN:   fprintf(fd, "  ???"); break;
104                 case Symbol::SV_DEFAULT:   fprintf(fd, "   - "); break;
105                 case Symbol::SV_INTERNAL:  fprintf(fd, "  INT"); break;
106                 case Symbol::SV_HIDDEN:    fprintf(fd, "  HID"); break;
107                 case Symbol::SV_PROTECTED: fprintf(fd, "  PRO"); break;
108             }
109             fprintf(fd, " ");
110             if (sym->isInSymtab())
111                 fprintf(fd, " STA");
112             if (sym->isInDynSymtab())
113                 fprintf(fd, " DYN");
114             if (sym->isAbsolute())
115                 fprintf(fd, " ABS");
116             std::string fileName;
117             std::vector<std::string> *vers;
118             if (sym->getVersionFileName(fileName))
119                 fprintf(fd, "  [%s]", fileName.c_str());
120             if (sym->getVersions(vers)) {
121                 fprintf(fd, " {");
122                 for (unsigned j=0; j < vers->size(); j++) {
123                     if (j > 0)
124                         fprintf(fd, ", ");
125                     fprintf(fd, "%s", (*vers)[j].c_str());
126                 }
127                 fprintf(fd, "}");
128             }
129             fprintf(fd,"\n");
130         }
131     }
132 }
133 void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols) {
134     dyn_hash_map< std::string, std::vector< Symbol *> >::iterator siter = symbols->begin();
135     int total_syms = 0;
136     while (siter != symbols->end()) {
137         print_symbols(siter->second);
138         total_syms += siter->second.size();
139         siter++;
140     }
141     printf("%d total symbol(s)\n", total_syms);
142 }
143 //#endif
144
145
146 const char *Dyninst::SymtabAPI::supportedLanguages2Str(supportedLanguages s)
147 {
148    switch(s) {
149       CASE_RETURN_STR(lang_Unknown);
150       CASE_RETURN_STR(lang_Assembly);
151       CASE_RETURN_STR(lang_C);
152       CASE_RETURN_STR(lang_CPlusPlus);
153       CASE_RETURN_STR(lang_GnuCPlusPlus);
154       CASE_RETURN_STR(lang_Fortran);
155       CASE_RETURN_STR(lang_Fortran_with_pretty_debug);
156       CASE_RETURN_STR(lang_CMFortran);
157    };
158    return "bad_language";
159 }
160
161
162 bool Dyninst::SymtabAPI::symbol_compare(const Symbol *s1, const Symbol *s2) 
163 {
164     // select the symbol with the lowest address
165     Offset s1_addr = s1->getAddr();
166     Offset s2_addr = s2->getAddr();
167     if (s1_addr > s2_addr)
168         return false;
169     if (s1_addr < s2_addr)
170         return true;
171
172     // symbols are co-located at the same address
173     // select the symbol which is not a function
174     if ((s1->getType() != Symbol::ST_FUNCTION) && (s2->getType() == Symbol::ST_FUNCTION))
175         return true;
176     if ((s2->getType() != Symbol::ST_FUNCTION) && (s1->getType() == Symbol::ST_FUNCTION))
177         return false;
178     
179     // symbols are both functions
180     // select the symbol which has GLOBAL linkage
181     if ((s1->getLinkage() == Symbol::SL_GLOBAL) && (s2->getLinkage() != Symbol::SL_GLOBAL))
182         return true;
183     if ((s2->getLinkage() == Symbol::SL_GLOBAL) && (s1->getLinkage() != Symbol::SL_GLOBAL))
184         return false;
185         
186     // neither function is GLOBAL
187     // select the symbol which has LOCAL linkage
188     if ((s1->getLinkage() == Symbol::SL_LOCAL) && (s2->getLinkage() != Symbol::SL_LOCAL))
189         return true;
190     if ((s2->getLinkage() == Symbol::SL_LOCAL) && (s1->getLinkage() != Symbol::SL_LOCAL))
191         return false;
192     
193     // both functions are WEAK
194     
195     // Apparently sort requires a strict weak ordering
196     // and fails for equality. our compare
197     // function behaviour should be as follows
198     // f(x,y) => !f(y,x)
199     // f(x,y),f(y,z) => f(x,z)
200     // f(x,x) = false. 
201     // So return which ever is first in the array. May be that would help.
202     return (s1 < s2);
203 }
204
205
206 bool AObject::needs_function_binding() const 
207 {
208     return false;
209 }
210
211 bool AObject::get_func_binding_table(std::vector<relocationEntry> &) const 
212 {
213     return false;
214 }
215
216 bool AObject::get_func_binding_table_ptr(const std::vector<relocationEntry> *&) const 
217 {
218     return false;
219 }
220
221 bool AObject::addRelocationEntry(relocationEntry &)
222 {
223     return true;
224 }
225
226 char *AObject::mem_image() const
227 {
228         return NULL;
229 }
230
231 SYMTAB_EXPORT ExceptionBlock::~ExceptionBlock() 
232 {
233 }
234
235 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock() : tryStart_(0), trySize_(0), 
236                                                                 catchStart_(0), hasTry_(false) 
237 {
238 }
239
240 SYMTAB_EXPORT Offset ExceptionBlock::catchStart() const 
241 {
242         return catchStart_;
243 }
244
245 SYMTAB_EXPORT relocationEntry::relocationEntry(const relocationEntry& ra) : 
246    Serializable(),
247    target_addr_(ra.target_addr_), 
248    rel_addr_(ra.rel_addr_), 
249    addend_ (ra.addend_),
250    rtype_ (ra.rtype_),
251    name_(ra.name_), 
252    dynref_(ra.dynref_), relType_(ra.relType_) 
253 {
254 }
255
256 SYMTAB_EXPORT Offset relocationEntry::target_addr() const 
257 {
258         return target_addr_;
259 }
260
261 SYMTAB_EXPORT Offset relocationEntry::rel_addr() const 
262 {
263         return rel_addr_;
264 }
265
266 SYMTAB_EXPORT const string &relocationEntry::name() const 
267 {
268         return name_;
269 }
270
271 SYMTAB_EXPORT Symbol *relocationEntry::getDynSym() const 
272 {
273     return dynref_;
274 }
275
276 SYMTAB_EXPORT bool relocationEntry::addDynSym(Symbol *dynref) 
277 {
278     dynref_ = dynref;
279     return true;
280 }
281
282 SYMTAB_EXPORT unsigned long relocationEntry::getRelType() const 
283 {
284     return relType_;
285 }
286
287 SYMTAB_EXPORT Symbol::~Symbol ()
288 {
289    std::string *sfa_p = NULL;
290
291    if (getAnnotation(sfa_p, SymbolFileNameAnno))
292    {
293       if (!sfa_p) 
294       {
295          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
296       }
297       else
298       {
299          delete (sfa_p);
300       }
301    }
302 }
303
304 #if 0
305 SYMTAB_EXPORT Symbol::Symbol(const Symbol& s) :
306    Serializable(),
307    AnnotatableSparse(),
308    module_(s.module_), 
309    type_(s.type_), linkage_(s.linkage_), visibility_(s.visibility_),
310    addr_(s.addr_), ptr_addr_(s.ptr_addr_), sec_(s.sec_), size_(s.size_), 
311    isInDynsymtab_(s.isInDynsymtab_), isInSymtab_(s.isInSymtab_), 
312    isAbsolute_(s.isAbsolute_),
313    aggregate_(s.aggregate_),
314    mangledName_(s.mangledName_), 
315    prettyName_(s.prettyName_), 
316    typedName_(s.typedName_), 
317    tag_(s.tag_), 
318    framePtrRegNum_(s.framePtrRegNum_),
319    retType_(s.retType_), 
320    moduleName_(s.moduleName_) 
321 {
322 #if 0
323    Annotatable <std::string, symbol_file_name_a> &sfa = *this;
324    const Annotatable <std::string, symbol_file_name_a> &sfa_src = s;
325    if (sfa_src.size())
326       sfa.addAnnotation(sfa_src[0]);
327
328    Annotatable <std::vector<std::string>, symbol_version_names_a> &sva = *this;
329    const Annotatable <std::vector<std::string>, symbol_version_names_a> &sva_src = s;
330    if (sva_src.size())
331       sva.addAnnotation(sva_src[0]);
332
333    Annotatable<localVarCollection, symbol_variables_a, true> &lvA = *this;
334    const Annotatable<localVarCollection, symbol_variables_a, true> &lvA_src = s;
335    if (lvA_src.size())
336       lvA.addAnnotation(lvA_src[0]);
337
338    Annotatable<localVarCollection, symbol_parameters_a, true> &pA = *this;
339    const Annotatable<localVarCollection, symbol_parameters_a, true> &pA_src = s;
340    if (pA_src.size())
341       pA.addAnnotation(pA_src[0]);
342    fprintf(stderr, "%s[%d]:  FIXME??  copy annotations here or not??\n", FILE__, __LINE__);
343 #endif
344
345    std::string *sfa_p = NULL;
346    if (s.getAnnotation(sfa_p, SymbolFileNameAnno))
347    {
348       if (!sfa_p) 
349       {
350          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
351       }
352       else
353       {
354          std::string *sfa_p2 = new std::string(*sfa_p);
355
356          if (!addAnnotation(sfa_p2, SymbolFileNameAnno)) 
357          {
358             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
359          }
360       }
361    }
362
363    std::vector<std::string> *svn_p = NULL;
364    if (s.getAnnotation(svn_p, SymbolVersionNamesAnno))
365    {
366       if (!svn_p) 
367       {
368          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
369       }
370       else
371       {
372          //  note:  in an older version we just copied one element from this
373          // vector when the symbol got copied.  I think this is incorrect.
374          //fprintf(stderr, "%s[%d]:  alloc'ing new vector for symbol versions\n", FILE__, __LINE__);
375
376          //  if we alloc here, probably want to check in dtor to make
377          //  sure that we are deleting this if it exists.
378          //std::vector<std::string> *svn_p2 = new std::vector<std::string>();
379
380          //for (unsigned int i = 0; i < svn_p->size(); ++i)
381          //{
382          //   svn_p2->push_back(std::string((*svn_p)[i]));
383          //}
384
385          if (!addAnnotation(svn_p, SymbolVersionNamesAnno))
386          {
387             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
388          }
389       }
390    }
391
392    localVarCollection *vars_p = NULL;
393    if (s.getAnnotation(vars_p, FunctionLocalVariablesAnno))
394    {
395       if (!vars_p) 
396       {
397          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
398       }
399       else
400       {
401          if (!addAnnotation(vars_p, FunctionLocalVariablesAnno))
402          {
403             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
404          }
405       }
406    }
407
408    localVarCollection *params_p = NULL;
409    if (s.getAnnotation(params_p, FunctionParametersAnno))
410    {
411       if (!params_p) 
412       {
413          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
414       }
415       else
416       {
417          if (!addAnnotation(params_p, FunctionParametersAnno))
418          {
419             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
420          }
421       }
422    }
423 }
424
425 SYMTAB_EXPORT Symbol& Symbol::operator=(const Symbol& s) 
426 {
427    module_  = s.module_;
428    type_    = s.type_;
429    linkage_ = s.linkage_;
430    addr_    = s.addr_;
431    sec_     = s.sec_;
432    size_    = s.size_;
433    isInDynsymtab_ = s.isInDynsymtab_;
434    isInSymtab_ = s.isInSymtab_;
435    isAbsolute_ = s.isAbsolute_;
436    aggregate_ = s.aggregate_;
437    tag_     = s.tag_;
438    mangledName_ = s.mangledName_;
439    prettyName_ = s.prettyName_;
440    typedName_ = s.typedName_;
441    framePtrRegNum_ = s.framePtrRegNum_;
442
443    std::string *sfa_p = NULL;
444
445    if (s.getAnnotation(sfa_p, SymbolFileNameAnno))
446    {
447       if (!sfa_p) 
448       {
449          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
450       }
451       else
452       {
453          std::string *sfa_p2 = new std::string(*sfa_p);
454
455          if (!addAnnotation(sfa_p2, SymbolFileNameAnno))
456          {
457             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
458          }
459       }
460    }
461
462    std::vector<std::string> *svn_p = NULL;
463    if (s.getAnnotation(svn_p, SymbolVersionNamesAnno))
464    {
465       if (!svn_p) 
466       {
467          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
468       }
469       else
470       {
471          //  note:  in an older version we just copied one element from this
472          // vector when the symbol got copied.  I think this is incorrect.
473          //fprintf(stderr, "%s[%d]:  alloc'ing new vector for symbol versions\n", FILE__, __LINE__);
474
475          //  if we alloc here, probably want to check in dtor to make
476          //  sure that we are deleting this if it exists.
477          //std::vector<std::string> *svn_p2 = new std::vector<std::string>();
478
479          //for (unsigned int i = 0; i < svn_p->size(); ++i)
480          //{
481          //   svn_p2->push_back(std::string((*svn_p)[i]));
482          //}
483
484          if (!addAnnotation(svn_p, SymbolVersionNamesAnno))
485          {
486             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
487          }
488       }
489    }
490
491    localVarCollection *vars_p = NULL;
492    if (s.getAnnotation(vars_p, FunctionLocalVariablesAnno))
493    {
494       if (!vars_p) 
495       {
496          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
497       }
498       else
499       {
500          if (!addAnnotation(vars_p, FunctionLocalVariablesAnno))
501          {
502             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
503          }
504       }
505    }
506
507    localVarCollection *params_p = NULL;
508    if (s.getAnnotation(params_p, FunctionParametersAnno))
509    {
510       if (!params_p) 
511       {
512          fprintf(stderr, "%s[%d]:  inconsistency here??\n", FILE__, __LINE__);
513       }
514       else
515       {
516          if (!addAnnotation(params_p, FunctionParametersAnno))
517          {
518             fprintf(stderr, "%s[%d]:  failed ot addAnnotation here\n", FILE__, __LINE__);
519          }
520       }
521    }
522 #if 0
523 #if 1 
524    fprintf(stderr, "%s[%d]:  WARNING:  assignment ctor not assigning local variables and parameters\n", FILE__, __LINE__);
525 #else
526    Annotatable <std::string, symbol_file_name_a> &sfa = *this;
527    const Annotatable <std::string, symbol_file_name_a> &sfa_src = s;
528    if (sfa_src.size())
529       sfa.addAnnotation(sfa_src[0]);
530
531    Annotatable <std::vector<std::string>, symbol_version_names_a> &sva = *this;
532    const Annotatable <std::vector<std::string>, symbol_version_names_a> &sva_src = s;
533    if (sva_src.size())
534       sva.addAnnotation(sva_src[0]);
535
536    Annotatable<localVarCollection, symbol_variables_a, true> &lvA = *this;
537    const Annotatable<localVarCollection, symbol_variables_a,true> &lvA_src = s;
538    if (lvA_src.size())
539       lvA.addAnnotation(lvA_src[0]);
540
541    Annotatable<localVarCollection, symbol_parameters_a, true> &pA = *this;
542    const Annotatable<localVarCollection, symbol_parameters_a,true> &pA_src = s;
543    if (pA_src.size())
544       pA.addAnnotation(pA_src[0]);
545 #endif
546 #endif
547    return *this;
548 }
549 #endif
550 #if 0
551 }
552
553 SYMTAB_EXPORT bool Symbol::getVersions(std::vector<std::string> *&vers)
554 {
555    std::vector<std::string> *vn_p = NULL;
556
557    if (getAnnotation(vn_p, SymbolVersionNamesAnno)) 
558    {
559       if (!vn_p) 
560       {
561          fprintf(stderr, "%s[%d]:  inconsistency here\n", FILE__, __LINE__);
562       }
563       else
564       {
565          vers = vn_p;
566          return true;
567       } 
568    }
569
570    return false;
571 }
572
573
574
575 void Symbol::serialize(SerializerBase *s, const char *tag) 
576 {
577         struct getTypeByID {
578                 bool operator()(SerializerBase *sb, unsigned int &tid)
579                 {
580                         fprintf(stderr, "%s[%d]:  getting type by id here (not yet)\n", FILE__, __LINE__);
581                         return true;
582                 }
583         };
584
585         //  Need to serialize types before symbols
586         //  Use typeID as unique identifier
587         Type *t = retType_;
588         unsigned int t_id = t ? t->getID() : (unsigned int) 0xdeadbeef; 
589
590         //  Need to serialize regions before symbols
591         //  Use disk offset as unique identifier
592         Region *r = sec_;
593         Offset r_off = r ? r->getDiskOffset() : (Offset) 0;
594
595    try {
596       ifxml_start_element(s, tag);
597       gtranslate(s, type_, symbolType2Str, "type");
598       gtranslate(s, linkage_, symbolLinkage2Str, "linkage");
599       gtranslate(s, tag_, symbolTag2Str, "tag");
600       gtranslate(s, visibility_, symbolVisibility2Str, "visibility");
601       gtranslate(s, addr_, "addr");
602       gtranslate(s, size_, "size");
603       gtranslate(s, isInDynsymtab_, "isInDynsymtab");
604       gtranslate(s, isInSymtab_, "isInSymtab");
605       gtranslate(s, isAbsolute_, "isAbsolute");
606       gtranslate(s, prettyName_, "prettyName");
607       gtranslate(s, mangledName_, "mangledName");
608       gtranslate(s, typedName_, "typedName");
609       gtranslate(s, framePtrRegNum_, "framePtrRegNum");
610       gtranslate(s, t_id, "typeID");
611       gtranslate(s, r_off, "regionDiskOffset");
612       gtranslate(s, moduleName_, "moduleName");
613       gtranslate(s, fileName_, "fileName");
614       ifxml_end_element(s, "Symbol");
615
616    //  Now, if we are doing binary deserialization, lookup type and region by unique ids
617           if (s->isBin())
618           {
619                   if (s->isInput())
620                   {
621                           ScopedSerializerBase<Symtab> *ssb = dynamic_cast<ScopedSerializerBase<Symtab> *>(s);
622                           if (!ssb)
623                           {
624                                   fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
625                                   SER_ERR("FIXME");
626                           }
627                           Symtab *st = ssb->getScope();
628                           assert(st);
629                           Module *m = NULL;
630                           if (!st->findModuleByName(m, moduleName_) || !m)
631                           {
632                                           fprintf(stderr, "%s[%d]:  WARNING:  cannot find module '%s' for symbol during deserailize\n", FILE__, __LINE__, moduleName_.c_str());
633                           }
634                           else
635                           {
636                                   module_ = m;
637                           }
638
639                           if (t_id == 0xdeadbeef)
640                                   retType_ = NULL;
641                           else 
642                           {
643                                   Type *t = st->findType(t_id);
644                                   if (!t)
645                                   {
646                                           fprintf(stderr, "%s[%d]:  WARNING:  cannot find type for symbol during deserailize\n", FILE__, __LINE__);
647                                   }
648                                   else
649                                   {
650                                           retType_ = t;
651                                   }
652                           }
653                           Region *r = NULL;
654                           if (!st->findRegionByEntry(r, r_off) || !r)
655                           {
656                                   fprintf(stderr, "%s[%d]:  WARNING:  cannot find region for symbol during deserailize\n", FILE__, __LINE__);
657                           }
658                           else 
659                           {
660                                   sec_ = r;
661                           }
662                           
663                   }
664           }
665 #if 0
666           getTypeByID tbid;
667           if_bin(if_input(tbid, 
668                                   t_id, 
669                                   s),
670                           t_id, 
671                           s);
672 #endif
673    } SER_CATCH("Symbol");
674
675 }
676
677 ostream& Dyninst::SymtabAPI::operator<< (ostream &os, const Symbol &s) 
678 {
679     return os << "{"
680               << " mangled=" << s.getMangledName()
681               << " pretty="  << s.getPrettyName()
682               << " module="  << s.module_
683         //<< " type="    << (unsigned) s.type_
684               << " type="    << s.symbolType2Str(s.type_)
685         //<< " linkage=" << (unsigned) s.linkage_
686               << " linkage=" << s.symbolLinkage2Str(s.linkage_)
687               << " addr=0x"    << hex << s.addr_ << dec
688         //<< " tag="     << (unsigned) s.tag_
689               << " tag="     << s.symbolTag2Str(s.tag_)
690               << " isAbs="   << s.isAbsolute_
691               << (s.isFunction() ? " [FUNC]" : "")
692               << (s.isVariable() ? " [VAR]" : "")
693               << (s.isInSymtab_ ? " [STA]" : "")
694               << (s.isInDynsymtab_ ? " [DYN]" : "")
695               << " }" << endl;
696 }
697
698
699 ostream & Dyninst::SymtabAPI::operator<< (ostream &s, const relocationEntry &r) 
700 {
701         s << "target_addr=" << r.target_addr_ 
702                 << "rel_addr=" << r.rel_addr_ 
703                 << "addend=" << r.addend_ 
704                 << "rtype=" << r.rtype_ 
705                 << "name=" << r.name_ ;
706         return s; 
707 }
708      Offset tryStart_;
709                unsigned trySize_;
710                          Offset catchStart_;
711                                        bool hasTry_;
712
713 ostream & Dyninst::SymtabAPI::operator<< (ostream &s, const ExceptionBlock &eb) 
714 {
715         s << "tryStart=" << eb.tryStart_ 
716                 << "trySize=" << eb.trySize_ 
717                 << "catchStart=" << eb.catchStart_ 
718                 << "hasTry=" << eb.trySize_ ;
719         return s; 
720 }
721
722 #endif
723
724 #ifdef DEBUG 
725 ostream &operator<<(ostream &os, relocationEntry &q) {
726    return q.operator<<(os);
727 }
728 #endif
729
730 /**************************************************
731  *
732  *  Stream based debuggering output - for regreesion testing.
733  *  Dump info on state of object *this....
734  *
735  **************************************************/
736
737 SYMTAB_EXPORT unsigned AObject::nsymbols () const 
738
739     unsigned n = 0;
740     for (dyn_hash_map<std::string, std::vector<Symbol *> >::const_iterator i = symbols_.begin();
741          i != symbols_.end(); 
742          i++) {
743         n += i->second.size();
744     }
745     return n;
746 }
747
748 SYMTAB_EXPORT bool AObject::get_symbols(string & name, 
749       std::vector<Symbol *> &symbols ) 
750 {
751    if ( symbols_.find(name) == symbols_.end()) {
752       return false;
753    }
754
755    symbols = symbols_[name];
756    return true;
757 }
758
759 SYMTAB_EXPORT char* AObject::code_ptr () const 
760
761    return code_ptr_; 
762 }
763
764 SYMTAB_EXPORT Offset AObject::code_off () const 
765
766    return code_off_; 
767 }
768
769 SYMTAB_EXPORT Offset AObject::code_len () const 
770
771    return code_len_; 
772 }
773
774 SYMTAB_EXPORT char* AObject::data_ptr () const 
775
776    return data_ptr_; 
777 }
778
779 SYMTAB_EXPORT Offset AObject::data_off () const 
780
781    return data_off_; 
782 }
783
784 SYMTAB_EXPORT Offset AObject::data_len () const 
785
786    return data_len_; 
787 }
788
789 SYMTAB_EXPORT bool AObject::is_aout() const 
790 {
791    return is_aout_;  
792 }
793
794 SYMTAB_EXPORT bool AObject::isDynamic() const 
795 {
796    return is_dynamic_;  
797 }
798
799 SYMTAB_EXPORT unsigned AObject::no_of_sections() const 
800
801    return no_of_sections_; 
802 }
803
804 SYMTAB_EXPORT unsigned AObject::no_of_symbols() const 
805
806    return no_of_symbols_;  
807 }
808
809 SYMTAB_EXPORT bool AObject::getAllExceptions(std::vector<ExceptionBlock *>&excpBlocks) const
810 {
811    for (unsigned i=0;i<catch_addrs_.size();i++)
812       excpBlocks.push_back(new ExceptionBlock(catch_addrs_[i]));
813
814    return true;
815 }
816
817 SYMTAB_EXPORT std::vector<Region *> AObject::getAllRegions() const
818 {
819    return regions_;     
820 }
821
822 SYMTAB_EXPORT Offset AObject::loader_off() const 
823
824    return loader_off_; 
825 }
826
827 SYMTAB_EXPORT unsigned AObject::loader_len() const 
828
829    return loader_len_; 
830 }
831
832
833 SYMTAB_EXPORT int AObject::getAddressWidth() const 
834
835    return addressWidth_nbytes; 
836 }
837
838 SYMTAB_EXPORT bool AObject::have_deferred_parsing(void) const
839
840    return deferredParse;
841 }
842
843 SYMTAB_EXPORT void * AObject::getErrFunc() const 
844 {
845    return (void *) err_func_; 
846 }
847
848 SYMTAB_EXPORT dyn_hash_map< string, std::vector< Symbol *> > *AObject::getAllSymbols() 
849
850    return &(symbols_);
851 }
852
853 SYMTAB_EXPORT AObject::~AObject() 
854 {
855 }
856
857 // explicitly protected
858 SYMTAB_EXPORT AObject::AObject(MappedFile *mf_, MappedFile *mfd, void (*err_func)(const char *)) 
859 : mf(mf_), mfForDebugInfo(mfd), code_ptr_(0), code_off_(0),
860    code_len_(0), data_ptr_(0), data_off_(0), data_len_(0),loader_off_(0),
861    loader_len_(0), is_dynamic_(false), deferredParse(false), err_func_(err_func),
862    addressWidth_nbytes(4) 
863 {
864 }
865
866 SYMTAB_EXPORT AObject::AObject(const AObject &obj)
867 : mf(obj.mf), mfForDebugInfo(obj.mfForDebugInfo), symbols_(obj.symbols_), 
868    code_ptr_(obj.code_ptr_), code_off_(obj.code_off_), 
869    code_len_(obj.code_len_), data_ptr_(obj.data_ptr_), 
870    data_off_(obj.data_off_), data_len_(obj.data_len_), 
871    loader_off_(obj.loader_off_), loader_len_(obj.loader_len_), is_dynamic_(obj.is_dynamic_),
872    deferredParse(false), err_func_(obj.err_func_), addressWidth_nbytes(4)
873 {
874
875
876 //  a helper routine that selects a language based on information from the symtab
877 supportedLanguages AObject::pickLanguage(string &working_module, char *working_options,
878       supportedLanguages working_lang)
879 {
880    supportedLanguages lang = lang_Unknown;
881    static int sticky_fortran_modifier_flag = 0;
882    // (2) -- check suffixes -- try to keep most common suffixes near the top of the checklist
883    string::size_type len = working_module.length();
884    if((len>2) && (working_module.substr(len-2,2) == string(".c"))) lang = lang_C;
885    else if ((len>2) && (working_module.substr(len-2,2) == string(".C"))) lang = lang_CPlusPlus;
886    else if ((len>4) && (working_module.substr(len-4,4) == string(".cpp"))) lang = lang_CPlusPlus;
887    else if ((len>2) && (working_module.substr(len-2,2) == string(".F"))) lang = lang_Fortran;
888    else if ((len>2) && (working_module.substr(len-2,2) == string(".f"))) lang = lang_Fortran;
889    else if ((len>3) && (working_module.substr(len-3,3) == string(".cc"))) lang = lang_C;
890    else if ((len>2) && (working_module.substr(len-2,2) == string(".a"))) lang = lang_Assembly; // is this right?
891    else if ((len>2) && (working_module.substr(len-2,2) == string(".S"))) lang = lang_Assembly;
892    else if ((len>2) && (working_module.substr(len-2,2) == string(".s"))) lang = lang_Assembly;
893    else
894    {
895       //(3) -- try to use options string -- if we have 'em
896       if (working_options)
897       {
898          //  NOTE:  a binary is labeled "gcc2_compiled" even if compiled w/g77 -- thus this is
899          //  quite inaccurate to make such assumptions
900          if (strstr(working_options, "gcc"))
901             lang = lang_C;
902          else if (strstr(working_options, "g++"))
903             lang = lang_CPlusPlus;
904       }
905    }
906    //  This next section tries to determine the version of the debug info generator for a
907    //  Sun fortran compiler.  Some leave the underscores on names in the debug info, and some
908    //  have the "pretty" names, we need to detect this in order to properly read the debug.
909    if (working_lang == lang_Fortran)
910    {
911       if (sticky_fortran_modifier_flag)
912       {
913          //cerr << FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug." << endl;
914          working_lang = lang_Fortran_with_pretty_debug;
915       }
916       else if (working_options)
917       {
918          char *dbg_gen = NULL;
919          //cerr << FILE__ << __LINE__ << ":  OPT: " << working_options << endl;                 
920          if (NULL != (dbg_gen = strstr(working_options, "DBG_GEN=")))
921          {
922             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen << endl;
923             // Sun fortran compiler (probably), need to examine version
924             char *dbg_gen_ver_maj = dbg_gen + strlen("DBG_GEN=");
925             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen_ver_maj << endl;
926             char *next_dot = strchr(dbg_gen_ver_maj, '.');
927             if (NULL != next_dot)
928             {
929                next_dot = '\0';  //terminate major version number string
930                int ver_maj = atoi(dbg_gen_ver_maj);
931                //cerr <<"Major Debug Ver. "<<ver_maj<< endl;
932                if (ver_maj < 3)
933                {
934                   working_lang = lang_Fortran_with_pretty_debug;
935                   sticky_fortran_modifier_flag = 1;
936                   //cerr << __FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug.  " << "Major Debug Ver. "<<ver_maj<<endl;
937                }
938             }
939          }
940       }
941    }
942    return lang;
943 }
944
945 SymbolIter::SymbolIter( Object & obj ) 
946 : symbols(obj.getAllSymbols()), currentPositionInVector(0) 
947 {
948    symbolIterator = obj.getAllSymbols()->begin();
949 }
950
951 SymbolIter::SymbolIter( const SymbolIter & src ) 
952 : symbols(src.symbols),currentPositionInVector(0),
953    symbolIterator( src.symbolIterator ) 
954 {
955 }
956
957 SymbolIter::~SymbolIter () 
958 {
959 }
960
961
962 void SymbolIter::reset () 
963 {
964    currentPositionInVector = 0;
965    symbolIterator = symbols->begin();
966 }
967
968 SymbolIter::operator bool() const
969 {
970    return (symbolIterator!=symbols->end());
971 }
972
973 void SymbolIter::operator++ ( int ) 
974 {
975    if ( currentPositionInVector + 1 < (symbolIterator->second).size())
976    {
977       currentPositionInVector++;
978       return;
979    }
980
981    /* Otherwise, we need a new std::vector. */
982    currentPositionInVector = 0;                 
983    symbolIterator++;
984 }
985
986 const string & SymbolIter::currkey() const 
987 {
988    return symbolIterator->first;
989 }
990
991 /* If it's important that this be const, we could try to initialize
992    currentVector to '& symbolIterator.currval()' in the constructor. */
993
994 Symbol *SymbolIter::currval() 
995 {
996    return ((symbolIterator->second)[ currentPositionInVector ]);
997 }
998
999 const std::string AObject::findModuleForSym(Symbol *sym) {
1000     return symsToModules_[sym];
1001 }
1002
1003 void AObject::clearSymsToMods() {
1004     symsToModules_.clear();
1005 }
1006