make variable and parameter lists annotations to class Symbol instead of class members
[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.21 2008/04/27 06:54:23 jaw Exp $
33
34 #include "symtabAPI/src/Object.h"
35 #include "symtabAPI/h/Symtab.h"
36 #include "symtabAPI/src/Collections.h"
37
38 using namespace std;
39 using namespace Dyninst;
40 using namespace Dyninst::SymtabAPI;
41
42 string Symbol::emptyString("");
43
44 bool Dyninst::SymtabAPI::symbol_compare(const Symbol *s1, const Symbol *s2) 
45 {
46     // select the symbol with the lowest address
47     Offset s1_addr = s1->getAddr();
48     Offset s2_addr = s2->getAddr();
49     if (s1_addr > s2_addr)
50         return false;
51     if (s1_addr < s2_addr)
52         return true;
53
54     // symbols are co-located at the same address
55     // select the symbol which is not a function
56     if ((s1->getType() != Symbol::ST_FUNCTION) && (s2->getType() == Symbol::ST_FUNCTION))
57         return true;
58     if ((s2->getType() != Symbol::ST_FUNCTION) && (s1->getType() == Symbol::ST_FUNCTION))
59         return false;
60     
61     // symbols are both functions
62     // select the symbol which has GLOBAL linkage
63     if ((s1->getLinkage() == Symbol::SL_GLOBAL) && (s2->getLinkage() != Symbol::SL_GLOBAL))
64         return true;
65     if ((s2->getLinkage() == Symbol::SL_GLOBAL) && (s1->getLinkage() != Symbol::SL_GLOBAL))
66         return false;
67         
68     // neither function is GLOBAL
69     // select the symbol which has LOCAL linkage
70     if ((s1->getLinkage() == Symbol::SL_LOCAL) && (s2->getLinkage() != Symbol::SL_LOCAL))
71         return true;
72     if ((s2->getLinkage() == Symbol::SL_LOCAL) && (s1->getLinkage() != Symbol::SL_LOCAL))
73         return false;
74     
75     // both functions are WEAK
76     
77     // Apparently sort requires a strict weak ordering
78     // and fails for equality. our compare
79     // function behaviour should be as follows
80     // f(x,y) => !f(y,x)
81     // f(x,y),f(y,z) => f(x,z)
82     // f(x,x) = false. 
83     // So return which ever is first in the array. May be that would help.
84     return (s1 < s2);
85 }
86
87
88 bool AObject::needs_function_binding() const 
89 {
90     return false;
91 }
92
93 bool AObject::get_func_binding_table(std::vector<relocationEntry> &) const 
94 {
95     return false;
96 }
97
98 bool AObject::get_func_binding_table_ptr(const std::vector<relocationEntry> *&) const 
99 {
100     return false;
101 }
102
103 bool AObject::addRelocationEntry(relocationEntry &)
104 {
105     return true;
106 }
107
108 char *AObject::mem_image() const
109 {
110         return NULL;
111 }
112
113 DLLEXPORT ExceptionBlock::~ExceptionBlock() 
114 {
115 }
116
117 DLLEXPORT ExceptionBlock::ExceptionBlock() : tryStart_(0), trySize_(0), 
118                                                                 catchStart_(0), hasTry_(false) 
119 {
120 }
121
122 DLLEXPORT Offset ExceptionBlock::catchStart() const 
123 {
124         return catchStart_;
125 }
126
127 DLLEXPORT relocationEntry::relocationEntry(const relocationEntry& ra) : 
128    target_addr_(ra.target_addr_), 
129    rel_addr_(ra.rel_addr_), name_(ra.name_), 
130    dynref_(ra.dynref_), relType_(ra.relType_) 
131 {
132 }
133
134 DLLEXPORT Offset relocationEntry::target_addr() const 
135 {
136         return target_addr_;
137 }
138
139 DLLEXPORT Offset relocationEntry::rel_addr() const 
140 {
141         return rel_addr_;
142 }
143
144 DLLEXPORT const string &relocationEntry::name() const 
145 {
146         return name_;
147 }
148
149 DLLEXPORT Symbol *relocationEntry::getDynSym() const 
150 {
151     return dynref_;
152 }
153
154 DLLEXPORT bool relocationEntry::addDynSym(Symbol *dynref) 
155 {
156     dynref_ = dynref;
157     return true;
158 }
159
160 DLLEXPORT unsigned long relocationEntry::getRelType() const 
161 {
162     return relType_;
163 }
164
165 DLLEXPORT Symbol::~Symbol ()
166 {
167         mangledNames.clear();
168         prettyNames.clear();
169         typedNames.clear();
170 }
171
172 DLLEXPORT Symbol::Symbol(const Symbol& s) :
173    Annotatable <std::string, symbol_file_name_a>(), 
174    Annotatable <std::vector<std::string>, symbol_version_names_a>(), 
175    Annotatable <localVarCollection, symbol_variables_a, true>(), 
176    Annotatable <localVarCollection, symbol_parameters_a, true>(), 
177    module_(s.module_), 
178    type_(s.type_), linkage_(s.linkage_),
179    addr_(s.addr_), sec_(s.sec_), size_(s.size_), 
180    isInDynsymtab_(s.isInDynsymtab_), isInSymtab_(s.isInSymtab_), 
181    mangledNames(s.mangledNames), prettyNames(s.prettyNames), typedNames(s.typedNames), tag_(s.tag_), framePtrRegNum_(s.framePtrRegNum_),
182    retType_(s.retType_), moduleName_(s.moduleName_) 
183 {
184    Annotatable <std::string, symbol_file_name_a> &sfa = *this;
185    const Annotatable <std::string, symbol_file_name_a> &sfa_src = s;
186    if (sfa_src.size())
187       sfa.addAnnotation(sfa_src[0]);
188
189    Annotatable <std::vector<std::string>, symbol_version_names_a> &sva = *this;
190    const Annotatable <std::vector<std::string>, symbol_version_names_a> &sva_src = s;
191    if (sva_src.size())
192       sva.addAnnotation(sva_src[0]);
193
194    Annotatable<localVarCollection, symbol_variables_a, true> &lvA = *this;
195    const Annotatable<localVarCollection, symbol_variables_a, true> &lvA_src = s;
196    if (lvA_src.size())
197       lvA.addAnnotation(lvA_src[0]);
198
199    Annotatable<localVarCollection, symbol_parameters_a, true> &pA = *this;
200    const Annotatable<localVarCollection, symbol_parameters_a, true> &pA_src = s;
201    if (pA_src.size())
202       pA.addAnnotation(pA_src[0]);
203 }
204
205 DLLEXPORT Symbol& Symbol::operator=(const Symbol& s) 
206 {
207    module_  = s.module_;
208    type_    = s.type_;
209    linkage_ = s.linkage_;
210    addr_    = s.addr_;
211    sec_     = s.sec_;
212    size_    = s.size_;
213    isInDynsymtab_ = s.isInDynsymtab_;
214    isInSymtab_ = s.isInSymtab_;
215    tag_     = s.tag_;
216    mangledNames = s.mangledNames;
217    prettyNames = s.prettyNames;
218    typedNames = s.typedNames;
219    framePtrRegNum_ = s.framePtrRegNum_;
220 #if 0
221    fprintf(stderr, "%s[%d]:  WARNING:  assignment ctor not assigning local variables and parameters\n", FILE__, __LINE__);
222 #else
223    Annotatable <std::string, symbol_file_name_a> &sfa = *this;
224    const Annotatable <std::string, symbol_file_name_a> &sfa_src = s;
225    if (sfa_src.size())
226       sfa.addAnnotation(sfa_src[0]);
227
228    Annotatable <std::vector<std::string>, symbol_version_names_a> &sva = *this;
229    const Annotatable <std::vector<std::string>, symbol_version_names_a> &sva_src = s;
230    if (sva_src.size())
231       sva.addAnnotation(sva_src[0]);
232
233    Annotatable<localVarCollection, symbol_variables_a, true> &lvA = *this;
234    const Annotatable<localVarCollection, symbol_variables_a, true> &lvA_src = s;
235    if (lvA_src.size())
236       lvA.addAnnotation(lvA_src[0]);
237
238    Annotatable<localVarCollection, symbol_parameters_a, true> &pA = *this;
239    const Annotatable<localVarCollection, symbol_parameters_a, true> &pA_src = s;
240    if (pA_src.size())
241       pA.addAnnotation(pA_src[0]);
242 #endif
243    return *this;
244 }
245
246 DLLEXPORT const string& Symbol::getName() const 
247 {
248    if (mangledNames.size() > 0)
249       return mangledNames[0];
250    return emptyString;
251 }
252
253 DLLEXPORT const string& Symbol::getPrettyName() const 
254 {
255    if (prettyNames.size() > 0)
256       return prettyNames[0];
257    return emptyString;
258 }
259
260 DLLEXPORT const string& Symbol::getTypedName() const 
261 {
262    if (typedNames.size() > 0)
263         return typedNames[0];
264     return emptyString;
265 }
266
267 DLLEXPORT const string& Symbol::getModuleName() const 
268 {
269     if (module_)
270         return module_->fullName();
271     else
272         return moduleName_;
273 }
274
275 DLLEXPORT Module* Symbol::getModule() const 
276 {
277     return module_;
278 }
279
280 DLLEXPORT bool Symbol::setModule(Module *mod) 
281 {
282         module_ = mod; 
283         return true;
284 }
285
286 DLLEXPORT Symbol::SymbolType Symbol::getType() const 
287 {
288     return type_;
289 }
290
291 DLLEXPORT Symbol::SymbolLinkage Symbol::getLinkage() const 
292 {
293     return linkage_;
294 }
295
296 DLLEXPORT Offset Symbol::getAddr() const 
297 {
298     return addr_;
299 }
300
301 DLLEXPORT Region *Symbol::getSec() const 
302 {
303     return sec_;
304 }
305
306 bool Symbol::addLocalVar(localVar *locVar)
307 {
308    Annotatable<localVarCollection, symbol_variables_a, true> &varA = *this;
309
310    if (!varA.size()) {
311       localVarCollection newColl;
312       varA.addAnnotation(newColl);
313    }
314
315    if (!varA.size()) {
316       fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
317       return false;
318    }
319
320    localVarCollection &svars = varA[0];
321    svars.addLocalVar(locVar);
322
323    return true;
324 }
325
326 bool Symbol::addParam(localVar *param)
327 {
328    Annotatable<localVarCollection, symbol_parameters_a, true> &paramA = *this;
329
330    if (!paramA.size()) {
331       localVarCollection newColl;
332       paramA.addAnnotation(newColl);
333    }
334
335    if (!paramA.size()) {
336       fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
337       return false;
338    }
339
340    localVarCollection &sparams = paramA[0];
341    sparams.addLocalVar(param);
342
343    return true;
344 }
345         
346 DLLEXPORT bool Symbol::isInDynSymtab() const 
347 {
348     return isInDynsymtab_;
349 }
350
351 DLLEXPORT bool Symbol::isInSymtab() const 
352 {
353     return isInSymtab_;
354 }
355
356 DLLEXPORT unsigned Symbol::getSize() const 
357 {
358     return size_;
359 }
360
361 DLLEXPORT bool  Symbol::setSize(unsigned ns)
362 {
363         size_ = ns;
364         return true;
365 }
366
367 DLLEXPORT Symbol::SymbolTag Symbol::tag() const 
368 {
369     return tag_;
370 }
371
372 DLLEXPORT bool Symbol::setModuleName(string module)
373 {
374         moduleName_ = module;
375         return true;
376 }
377
378 DLLEXPORT bool Symbol::setAddr (Offset newAddr) 
379 {
380       addr_ = newAddr;
381       return true;
382 }
383
384 DLLEXPORT bool Symbol::setDynSymtab() 
385 {
386     isInDynsymtab_= true;
387     return true;
388 }
389
390 DLLEXPORT bool Symbol::clearDynSymtab() 
391 {
392     isInDynsymtab_ = false;
393     return true;
394 }
395
396 DLLEXPORT bool Symbol::setIsInSymtab() 
397 {
398     isInSymtab_= true;
399     return true;
400 }
401
402 DLLEXPORT bool Symbol::clearIsInSymtab() 
403 {
404     isInSymtab_= false;
405     return true;
406 }
407
408 DLLEXPORT Symbol::Symbol()
409    : //name_("*bad-symbol*"), module_("*bad-module*"),
410     module_(NULL), type_(ST_UNKNOWN), linkage_(SL_UNKNOWN), addr_(0), sec_(NULL), size_(0),
411     isInDynsymtab_(false), isInSymtab_(true), tag_(TAG_UNKNOWN), framePtrRegNum_(-1), 
412     retType_(NULL), moduleName_("")
413 {
414    // note: this ctor is called surprisingly often (when we have
415    // vectors of Symbols and/or dictionaries of Symbols).  So, make it fast.
416 }
417
418 DLLEXPORT const std::vector<string>& Symbol::getAllMangledNames() const 
419 {
420     return mangledNames;
421 }
422
423 DLLEXPORT const std::vector<string>& Symbol::getAllPrettyNames() const 
424 {
425         return prettyNames;
426 }               
427     
428 DLLEXPORT const std::vector<string>& Symbol::getAllTypedNames() const 
429 {
430         return typedNames;
431 }
432
433 DLLEXPORT Symbol::Symbol(const string iname, const string imodule,
434     SymbolType itype, SymbolLinkage ilinkage, Offset iaddr,
435     Region *isec, unsigned size,  bool isInDynSymtab, bool isInSymtab)
436     : type_(itype),
437     linkage_(ilinkage), addr_(iaddr), sec_(isec), size_(size), isInDynsymtab_(isInDynSymtab),
438     isInSymtab_(isInSymtab), tag_(TAG_UNKNOWN), framePtrRegNum_(-1), retType_(NULL)
439 {
440         module_ = NULL;
441         moduleName_ = imodule;
442         mangledNames.push_back(iname);
443 }
444
445 DLLEXPORT Symbol::Symbol(const string iname, Module *mod,
446     SymbolType itype, SymbolLinkage ilinkage, Offset iaddr,
447     Region *isec, unsigned size,  bool isInDynSymtab, bool isInSymtab)
448     : module_(mod), type_(itype),
449     linkage_(ilinkage), addr_(iaddr), sec_(isec), size_(size),  isInDynsymtab_(isInDynSymtab), 
450     isInSymtab_(isInSymtab), tag_(TAG_UNKNOWN), framePtrRegNum_(-1), retType_(NULL)
451 {
452         mangledNames.push_back(iname);
453 }
454
455 DLLEXPORT bool Symbol::addMangledName(string name, bool isPrimary) 
456 {
457    std::vector<string> newMangledNames;
458
459    // isPrimary defaults to false
460    if (isPrimary)
461       newMangledNames.push_back(name);
462    bool found = false;
463    for (unsigned i = 0; i < mangledNames.size(); i++) {
464       if (mangledNames[i] == name) {
465          found = true;
466       }
467       else {
468          newMangledNames.push_back(mangledNames[i]);
469       }
470    }
471    if (!isPrimary)
472       newMangledNames.push_back(name);
473    mangledNames = newMangledNames;
474
475    if (!found && module_->exec())
476    {            //add it to the lookUps
477       if(type_ == ST_FUNCTION)
478          module_->exec()->addFunctionName(this,name,true);
479       else if(type_ == ST_OBJECT)
480          module_->exec()->addVariableName(this,name,true);
481       else if(type_ == ST_MODULE)
482          module_->exec()->addModuleName(this,name);
483    }
484
485    // Bool: true if the name is new; AKA !found
486    return (!found);
487 }                                                                                                                                       
488
489 DLLEXPORT bool Symbol::addPrettyName(string name, bool isPrimary) 
490 {
491    std::vector<string> newPrettyNames;
492
493    // isPrimary defaults to false
494    if (isPrimary)
495       newPrettyNames.push_back(name);
496    bool found = false;
497    for (unsigned i = 0; i < prettyNames.size(); i++) {
498       if (prettyNames[i] == name) {
499          found = true;
500       }
501       else {
502          newPrettyNames.push_back(prettyNames[i]);
503       }
504    }
505
506    if (!isPrimary)
507       newPrettyNames.push_back(name);
508    prettyNames = newPrettyNames;
509
510    if (!found && module_->exec())
511    {            //add it to the lookUps
512       if (type_ == ST_FUNCTION)
513          module_->exec()->addFunctionName(this,name,false);
514       else if (type_ == ST_OBJECT)
515          module_->exec()->addVariableName(this,name,false);
516       else if (type_ == ST_MODULE)
517          module_->exec()->addModuleName(this,name);
518    }
519
520    // Bool: true if the name is new; AKA !found
521    return (!found);
522 }
523
524 DLLEXPORT bool Symbol::addTypedName(string name, bool isPrimary) 
525 {
526    std::vector<string> newTypedNames;
527
528    // isPrimary defaults to false
529    if (isPrimary)
530       newTypedNames.push_back(name);
531
532    bool found = false;
533    for (unsigned i = 0; i < typedNames.size(); i++) {
534       if (typedNames[i] == name) {
535          found = true;
536       }
537       else {
538          newTypedNames.push_back(typedNames[i]);
539       }
540    }
541
542    if (!isPrimary)
543       newTypedNames.push_back(name);
544    typedNames = newTypedNames;
545
546    if (!found && module_->exec())
547    {            //add it to the lookUps
548       if (type_ == ST_FUNCTION)
549          module_->exec()->addFunctionName(this,name,false);
550       else if (type_ == ST_OBJECT)
551          module_->exec()->addVariableName(this,name,false);
552    }
553
554    // Bool: true if the name is new; AKA !found
555    return (!found);
556 }
557
558 DLLEXPORT bool Symbol::setSymbolType(SymbolType sType)
559 {
560    if ((sType != ST_UNKNOWN)&&
561          (sType != ST_FUNCTION)&&
562          (sType != ST_OBJECT)&&
563          (sType != ST_MODULE)&&
564          (sType != ST_NOTYPE))
565       return false;
566
567    SymbolType oldType = type_;  
568    type_ = sType;
569    if (module_->exec())
570       module_->exec()->changeType(this, oldType);
571
572    return true;
573 }
574
575 DLLEXPORT Type *Symbol::getReturnType()
576 {
577    return retType_;
578 }
579
580 DLLEXPORT bool  Symbol::setReturnType(Type *retType)
581 {
582    retType_ = retType;
583    return true;
584 }
585
586 DLLEXPORT bool Symbol::setFramePtrRegnum(int regnum)
587 {
588    framePtrRegNum_ = regnum;
589    return true;
590 }
591
592 DLLEXPORT int Symbol::getFramePtrRegnum()
593 {
594    return framePtrRegNum_;
595 }
596
597 DLLEXPORT bool Symbol::setVersionFileName(std::string &fileName)
598 {
599    Annotatable<std::string, symbol_file_name_a> &fn = *this;
600    if (fn.size()) {
601       fn.clearAnnotations();
602       //fprintf(stderr, "%s[%d]:  WARNING, already have filename set for symbol %s\n", FILE__, __LINE__, getName().c_str());
603       //return false;
604    }
605    fn.addAnnotation(fileName);
606    return true;
607 }
608
609 DLLEXPORT bool Symbol::setVersions(std::vector<std::string> &vers)
610 {
611    Annotatable<std::vector<std::string>, symbol_version_names_a> &sv = *this;
612    if (sv.size()) {
613       sv.clearAnnotations();
614       //fprintf(stderr, "%s[%d]:  WARNING, already have versions set for symbol %s\n", FILE__, __LINE__, getName().c_str());
615       //return false;
616    }
617    sv.addAnnotation(vers);
618    return true;
619 }
620
621 DLLEXPORT bool Symbol::getVersionFileName(std::string &fileName)
622 {
623    Annotatable<std::string, symbol_file_name_a> &fn = *this;
624    if (!fn.size()) {
625       return false;
626    }
627
628    fileName = fn[0];
629    return true;
630 }
631
632 DLLEXPORT bool Symbol::getVersions(std::vector<std::string> *&vers)
633 {
634    Annotatable<std::vector<std::string>, symbol_version_names_a> &sv = *this;
635    if (!sv.size()) {
636       return false;
637    }
638
639    vers = &(sv[0]);
640    return true;
641 }
642
643 DLLEXPORT bool Symbol::getLocalVariables(std::vector<localVar *>&vars)
644 {
645    if (type_ != ST_FUNCTION || !module_ )
646       return false;
647
648    module_->exec()->parseTypesNow();    
649
650    Annotatable<localVarCollection, symbol_variables_a, true> &svA = *this;
651    if (!svA.size())
652       return false;
653
654    if (svA.size() > 1) {
655       fprintf(stderr, "%s[%d]:  FIXME:  unexpected size for annotation\n", FILE__, __LINE__);
656    }
657
658    localVarCollection &lvc = svA[0];
659    vars = *(lvc.getAllVars());
660
661    if (vars.size())
662       return true;
663
664    //  this should not occur since annotation should not exist if no data inside it
665    fprintf(stderr, "%s[%d]:  FIXME:  bad sizing for annotation\n", FILE__, __LINE__);
666    return false;
667
668 }
669
670 DLLEXPORT bool Symbol::getParams(std::vector<localVar *>&params)
671 {
672    if (type_ != ST_FUNCTION || !module_ )
673       return false;
674
675    module_->exec()->parseTypesNow();    
676
677    Annotatable<localVarCollection, symbol_parameters_a, true> &pA = *this;
678    if (!pA.size())
679       return false;
680
681    if (pA.size() > 1) {
682       fprintf(stderr, "%s[%d]:  FIXME:  unexpected size for annotation\n", FILE__, __LINE__);
683    }
684
685    localVarCollection &lvc = pA[0];
686    params = *(lvc.getAllVars());
687
688    if (params.size())
689       return true;
690
691    //  this should not occur since annotation should not exist if no data inside it
692    fprintf(stderr, "%s[%d]:  FIXME:  bad sizing for annotation\n", FILE__, __LINE__);
693    return false;
694
695 }
696
697 DLLEXPORT bool Symbol::findLocalVariable(std::vector<localVar *>&vars, string name)
698 {
699    if (type_ != ST_FUNCTION || !module_ )
700       return false;
701
702    module_->exec()->parseTypesNow();    
703
704    Annotatable<localVarCollection, symbol_variables_a, true> &lvA = *this;
705    Annotatable<localVarCollection, symbol_parameters_a, true> &pA = *this;
706    if (!lvA.size() && !pA.size()) 
707       return false;
708
709    unsigned origSize = vars.size();     
710
711    if (lvA.size()) {
712       localVarCollection &lvc = lvA[0];
713       localVar *var = lvc.findLocalVar(name);
714       if (var) 
715          vars.push_back(var);
716    }
717
718    if (pA.size()) {
719       localVarCollection &lvc = pA[0];
720       localVar *var = lvc.findLocalVar(name);
721       if (var) 
722          vars.push_back(var);
723    }
724
725    if (vars.size() > origSize)
726       return true;
727
728    return false;
729 }
730
731 ostream& Dyninst::SymtabAPI::operator<< (ostream &os, const Symbol &s) 
732 {
733    return os << "{"
734       << " mangled=" << s.getName()
735       << " pretty="  << s.getPrettyName()
736       << " module="  << s.module_
737       << " type="    << (unsigned) s.type_
738       << " linkage=" << (unsigned) s.linkage_
739       << " addr="    << s.addr_
740       << " tag="     << (unsigned) s.tag_
741       << " }" << endl;
742 }
743
744 #ifdef DEBUG 
745
746 ostream & relocationEntry::operator<< (ostream &s) const {
747    s << "target_addr_ = " << target_addr_ << endl;
748    s << "rel_addr_ = " << rel_addr_ << endl;
749    s << "name_ = " << name_ << endl;
750    return s; 
751 }
752
753 ostream &operator<<(ostream &os, relocationEntry &q) {
754    return q.operator<<(os);
755 }
756
757 /**************************************************
758  *
759  *  Stream based debuggering output - for regreesion testing.
760  *  Dump info on state of object *this....
761  *
762  **************************************************/
763
764
765 const ostream &AObject::dump_state_info(ostream &s) {
766
767    // key and value for distc hash iter.... 
768    string str;
769    Symbol sym;
770    hash_map<string, std::vector <Symbol> >::iterator symbols_iter = symbols_.begin();
771
772    s << "Debugging Info for AObject (address) : " << this << endl;
773
774    s << " file_ = " << file_ << endl;
775    s << " symbols_ = " << endl;
776
777    // and loop over all the symbols, printing symbol name and data....
778    //  or try at least....
779    for(;symbols_iter!=symbols_.end();symbols_iter++)
780    {
781       str = symbols_iter->first
782          for(int i = 0; i<symbols_iter->second->size(); i++)
783          {
784             sym = (*(symbols_iter->second))[i];
785             s << "  key = " << str << " val " << sym << endl;
786          }
787    }
788    s << " code_ptr_ = " << code_ptr_ << endl;
789    s << " code_off_ = " << code_off_ << endl;
790    s << " code_len_ = " << code_len_ << endl;
791    s << " data_ptr_ = " << data_ptr_ << endl;
792    s << " data_off_ = " << data_off_ << endl;
793    s << " data_len_ = " << data_len_ << endl;
794    return s;
795 }
796
797 #endif
798
799 DLLEXPORT AObject::AObject()
800 {
801 }       
802
803 DLLEXPORT unsigned AObject::nsymbols () const 
804
805    return symbols_.size(); 
806 }
807
808 DLLEXPORT bool AObject::get_symbols(string & name, 
809       std::vector<Symbol *> &symbols ) 
810 {
811    if ( symbols_.find(name) == symbols_.end()) {
812       return false;
813    }
814
815    symbols = symbols_[name];
816    return true;
817 }
818
819 DLLEXPORT char* AObject::code_ptr () const 
820
821    return code_ptr_; 
822 }
823
824 DLLEXPORT Offset AObject::code_off () const 
825
826    return code_off_; 
827 }
828
829 DLLEXPORT Offset AObject::code_len () const 
830
831    return code_len_; 
832 }
833
834 DLLEXPORT char* AObject::data_ptr () const 
835
836    return data_ptr_; 
837 }
838
839 DLLEXPORT Offset AObject::data_off () const 
840
841    return data_off_; 
842 }
843
844 DLLEXPORT Offset AObject::data_len () const 
845
846    return data_len_; 
847 }
848
849 DLLEXPORT Offset AObject::code_vldS() const 
850
851    return code_vldS_; 
852 }
853
854 DLLEXPORT Offset AObject::code_vldE () const
855
856    return code_vldE_;
857 }
858
859 DLLEXPORT Offset AObject::data_vldS() const 
860 {
861    return data_vldS_; 
862 }
863
864 DLLEXPORT Offset AObject::data_vldE () const 
865 {
866    return data_vldE_; 
867 }
868
869 DLLEXPORT bool AObject::is_aout() const 
870 {
871    return is_aout_;  
872 }
873
874 DLLEXPORT unsigned AObject::no_of_sections() const 
875
876    return no_of_sections_; 
877 }
878
879 DLLEXPORT unsigned AObject::no_of_symbols() const 
880
881    return no_of_symbols_;  
882 }
883
884 DLLEXPORT bool AObject::getAllExceptions(std::vector<ExceptionBlock *>&excpBlocks) const
885 {
886    for (unsigned i=0;i<catch_addrs_.size();i++)
887       excpBlocks.push_back(new ExceptionBlock(catch_addrs_[i]));
888
889    return true;
890 }
891
892 DLLEXPORT std::vector<Region *> AObject::getAllRegions() const
893 {
894    return regions_;     
895 }
896
897 DLLEXPORT Offset AObject::loader_off() const 
898
899    return loader_off_; 
900 }
901
902 DLLEXPORT unsigned AObject::loader_len() const 
903
904    return loader_len_; 
905 }
906
907 DLLEXPORT int AObject::getAddressWidth() const 
908
909    return addressWidth_nbytes; 
910 }
911
912 DLLEXPORT bool AObject::have_deferred_parsing(void) const
913
914    return deferredParse;
915 }
916
917 DLLEXPORT void * AObject::getErrFunc() const 
918 {
919    return (void *) err_func_; 
920 }
921
922 DLLEXPORT hash_map< string, std::vector< Symbol *> > *AObject::getAllSymbols() 
923
924    return &(symbols_);
925 }
926
927 DLLEXPORT AObject::~AObject() 
928 {
929 }
930
931 // explicitly protected
932 DLLEXPORT AObject::AObject(MappedFile *mf_ , void (*err_func)(const char *)) 
933 : mf(mf_), code_ptr_(0), code_off_(0),
934    code_len_(0), data_ptr_(0), data_off_(0), data_len_(0),loader_off_(0),
935    loader_len_(0), deferredParse(false), err_func_(err_func),
936    addressWidth_nbytes(4) 
937 {
938 }
939
940 DLLEXPORT AObject::AObject(const AObject &obj)
941 : mf(obj.mf), symbols_(obj.symbols_), 
942    code_ptr_(obj.code_ptr_), code_off_(obj.code_off_), 
943    code_len_(obj.code_len_), data_ptr_(obj.data_ptr_), 
944    data_off_(obj.data_off_), data_len_(obj.data_len_), 
945    loader_off_(obj.loader_off_), loader_len_(obj.loader_len_),
946    deferredParse(false), err_func_(obj.err_func_), addressWidth_nbytes(4)
947 {
948
949
950 DLLEXPORT AObject& AObject::operator=(const AObject &obj) 
951 {   
952    if (this == &obj) {
953       return *this;
954    }
955
956    mf = obj.mf;
957    symbols_   = obj.symbols_;
958    code_ptr_  = obj.code_ptr_;
959    code_off_  = obj.code_off_;
960    code_len_  = obj.code_len_;
961    data_ptr_  = obj.data_ptr_;
962    data_off_  = obj.data_off_;
963    data_len_  = obj.data_len_;
964    err_func_  = obj.err_func_;
965    loader_off_ = obj.loader_off_; 
966    loader_len_ = obj.loader_len_;
967    addressWidth_nbytes = obj.addressWidth_nbytes;
968    return *this;
969 }
970
971 //  a helper routine that selects a language based on information from the symtab
972 supportedLanguages AObject::pickLanguage(string &working_module, char *working_options,
973       supportedLanguages working_lang)
974 {
975    supportedLanguages lang = lang_Unknown;
976    static int sticky_fortran_modifier_flag = 0;
977    // (2) -- check suffixes -- try to keep most common suffixes near the top of the checklist
978    string::size_type len = working_module.length();
979    if((len>2) && (working_module.substr(len-2,2) == string(".c"))) lang = lang_C;
980    else if ((len>2) && (working_module.substr(len-2,2) == string(".C"))) lang = lang_CPlusPlus;
981    else if ((len>4) && (working_module.substr(len-4,4) == string(".cpp"))) lang = lang_CPlusPlus;
982    else if ((len>2) && (working_module.substr(len-2,2) == string(".F"))) lang = lang_Fortran;
983    else if ((len>2) && (working_module.substr(len-2,2) == string(".f"))) lang = lang_Fortran;
984    else if ((len>3) && (working_module.substr(len-3,3) == string(".cc"))) lang = lang_C;
985    else if ((len>2) && (working_module.substr(len-2,2) == string(".a"))) lang = lang_Assembly; // is this right?
986    else if ((len>2) && (working_module.substr(len-2,2) == string(".S"))) lang = lang_Assembly;
987    else if ((len>2) && (working_module.substr(len-2,2) == string(".s"))) lang = lang_Assembly;
988    else
989    {
990       //(3) -- try to use options string -- if we have 'em
991       if (working_options)
992       {
993          //  NOTE:  a binary is labeled "gcc2_compiled" even if compiled w/g77 -- thus this is
994          //  quite inaccurate to make such assumptions
995          if (strstr(working_options, "gcc"))
996             lang = lang_C;
997          else if (strstr(working_options, "g++"))
998             lang = lang_CPlusPlus;
999       }
1000    }
1001    //  This next section tries to determine the version of the debug info generator for a
1002    //  Sun fortran compiler.  Some leave the underscores on names in the debug info, and some
1003    //  have the "pretty" names, we need to detect this in order to properly read the debug.
1004    if (working_lang == lang_Fortran)
1005    {
1006       if (sticky_fortran_modifier_flag)
1007       {
1008          //cerr << FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug." << endl;
1009          working_lang = lang_Fortran_with_pretty_debug;
1010       }
1011       else if (working_options)
1012       {
1013          char *dbg_gen = NULL;
1014          //cerr << FILE__ << __LINE__ << ":  OPT: " << working_options << endl;                 
1015          if (NULL != (dbg_gen = strstr(working_options, "DBG_GEN=")))
1016          {
1017             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen << endl;
1018             // Sun fortran compiler (probably), need to examine version
1019             char *dbg_gen_ver_maj = dbg_gen + strlen("DBG_GEN=");
1020             //cerr << __FILE__ << __LINE__ << ":  OPT: " << dbg_gen_ver_maj << endl;
1021             char *next_dot = strchr(dbg_gen_ver_maj, '.');
1022             if (NULL != next_dot)
1023             {
1024                next_dot = '\0';  //terminate major version number string
1025                int ver_maj = atoi(dbg_gen_ver_maj);
1026                //cerr <<"Major Debug Ver. "<<ver_maj<< endl;
1027                if (ver_maj < 3)
1028                {
1029                   working_lang = lang_Fortran_with_pretty_debug;
1030                   sticky_fortran_modifier_flag = 1;
1031                   //cerr << __FILE__ << __LINE__ << ": UPDATE: lang_Fortran->lang_Fortran_with_pretty_debug.  " << "Major Debug Ver. "<<ver_maj<<endl;
1032                }
1033             }
1034          }
1035       }
1036    }
1037    return lang;
1038 }
1039
1040 SymbolIter::SymbolIter( Object & obj ) 
1041 : symbols(obj.getAllSymbols()), currentPositionInVector(0) 
1042 {
1043    symbolIterator = obj.getAllSymbols()->begin();
1044 }
1045
1046 SymbolIter::SymbolIter( const SymbolIter & src ) 
1047 : symbols(src.symbols),currentPositionInVector(0),
1048    symbolIterator( src.symbolIterator ) 
1049 {
1050 }
1051
1052 SymbolIter::~SymbolIter () 
1053 {
1054 }
1055
1056
1057 void SymbolIter::reset () 
1058 {
1059    currentPositionInVector = 0;
1060    symbolIterator = symbols->begin();
1061 }
1062
1063 SymbolIter::operator bool() const
1064 {
1065    return (symbolIterator!=symbols->end());
1066 }
1067
1068 void SymbolIter::operator++ ( int ) 
1069 {
1070    if ( currentPositionInVector + 1 < (symbolIterator->second).size())
1071    {
1072       currentPositionInVector++;
1073       return;
1074    }
1075
1076    /* Otherwise, we need a new std::vector. */
1077    currentPositionInVector = 0;                 
1078    symbolIterator++;
1079 }
1080
1081 const string & SymbolIter::currkey() const 
1082 {
1083    return symbolIterator->first;
1084 }
1085
1086 /* If it's important that this be const, we could try to initialize
1087    currentVector to '& symbolIterator.currval()' in the constructor. */
1088
1089 Symbol *SymbolIter::currval() 
1090 {
1091    return ((symbolIterator->second)[ currentPositionInVector ]);
1092 }