Determine the architecture of an ELF by looking at the file header instead of the...
[dyninst.git] / symtabAPI / src / Symtab.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * This library is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU Lesser General Public
17  * License as published by the Free Software Foundation; either
18  * version 2.1 of the License, or (at your option) any later version.
19  * 
20  * This library is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * Lesser General Public License for more details.
24  * 
25  * You should have received a copy of the GNU Lesser General Public
26  * License along with this library; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <assert.h>
33 #include <string.h>
34 #include <algorithm>
35 #include <iostream>
36 #include <iomanip>
37 #include <sstream>
38
39 #include "common/src/Timer.h"
40 #include "common/src/debugOstream.h"
41 #include "common/src/serialize.h"
42 #include "common/src/pathName.h"
43
44 #include "Serialization.h"
45 #include "Symtab.h"
46 #include "Module.h"
47 #include "Collections.h"
48 #include "Function.h"
49 #include "Variable.h"
50
51 #include "annotations.h"
52
53 #include "debug.h"
54
55 #include "symtabAPI/src/Object.h"
56
57 #if !defined(os_windows)
58 #include <dlfcn.h>
59 #else
60 #include <windows.h>
61 #endif
62
63 #include <iomanip>
64 #include <stdarg.h>
65
66 #include "version.h"
67
68 using namespace Dyninst;
69 using namespace Dyninst::SymtabAPI;
70 using namespace std;
71
72 static std::string errMsg;
73 extern bool parseCompilerType(Object *);
74
75 static const int Symtab_major_version = DYNINST_MAJOR_VERSION;
76 static const int Symtab_minor_version = DYNINST_MINOR_VERSION;
77 static const int Symtab_maintenance_version = DYNINST_PATCH_VERSION;
78
79
80 void Symtab::version(int& major, int& minor, int& maintenance)
81 {
82     major = Symtab_major_version;
83     minor = Symtab_minor_version;
84     maintenance = Symtab_maintenance_version;
85 }
86
87
88 void symtab_log_perror(const char *msg)
89 {
90    errMsg = std::string(msg);
91 };
92
93
94 SymtabError serr;
95
96 std::vector<Symtab *> Symtab::allSymtabs;
97
98  
99 SymtabError Symtab::getLastSymtabError()
100 {
101     return serr;
102 }
103
104 void setSymtabError(SymtabError new_err)
105 {
106    serr = new_err;
107 }
108
109 std::string Symtab::printError(SymtabError serr)
110 {
111     switch (serr)
112     {
113        case Obj_Parsing:
114            return "Failed to parse the Object"+errMsg;
115        case Syms_To_Functions:
116            return "Failed to convert Symbols to Functions";
117        case No_Such_Function:
118            return "Function does not exist";
119        case No_Such_Variable:
120            return "Variable does not exist";
121        case No_Such_Module:
122           return "Module does not exist";
123        case No_Such_Region:
124            return "Region does not exist";
125        case No_Such_Symbol:
126            return "Symbol does not exist";
127        case Not_A_File:
128            return "Not a File. Call openArchive()";
129        case Not_An_Archive:
130            return "Not an Archive. Call openFile()";
131        case Export_Error:
132            return "Error Constructing XML"+errMsg;
133        case Emit_Error:
134            return "Error rewriting binary: " + errMsg;
135        case Invalid_Flags:
136           return "Flags passed are invalid.";
137        case No_Error:
138           return "No previous Error.";
139        default:
140           return "Unknown Error";
141     }           
142 }
143
144 boost::shared_ptr<Type> Symtab::type_Error()
145 {
146     static boost::shared_ptr<Type> store = 
147        boost::shared_ptr<Type>(new Type(std::string("<error>"), 0, dataUnknownType));
148     return store;
149 }
150 boost::shared_ptr<Type> Symtab::type_Untyped()
151 {
152     static boost::shared_ptr<Type> store =
153        boost::shared_ptr<Type>(new Type(std::string("<no type>"), 0, dataUnknownType));
154     return store;
155 }
156
157 boost::shared_ptr<builtInTypeCollection> Symtab::builtInTypes()
158 {
159     static boost::shared_ptr<builtInTypeCollection> store =
160         setupBuiltinTypes();
161     return store;
162 }
163 boost::shared_ptr<typeCollection> Symtab::stdTypes()
164 {
165     static boost::shared_ptr<typeCollection> store =
166         setupStdTypes();
167     return store;
168 }
169
170 boost::shared_ptr<builtInTypeCollection> Symtab::setupBuiltinTypes()
171 {
172     boost::shared_ptr<builtInTypeCollection> builtInTypes =
173        boost::shared_ptr<builtInTypeCollection>(new builtInTypeCollection);
174
175    typeScalar *newType;
176
177    // NOTE: integral type  mean twos-complement
178    // -1  int, 32 bit signed integral type
179    // in stab document, size specified in bits, system size is in bytes
180    builtInTypes->addBuiltInType(newType = new typeScalar(-1, 4, "int", true));
181    newType->decrRefCount();
182    // -2  char, 8 bit type holding a character. GDB treats as signed
183    builtInTypes->addBuiltInType(newType = new typeScalar(-2, 1, "char", true));
184    newType->decrRefCount();
185    // -3  short, 16 bit signed integral type
186    builtInTypes->addBuiltInType(newType = new typeScalar(-3, 2, "short", true));
187    newType->decrRefCount();
188    // -4  long, 32/64 bit signed integral type
189    builtInTypes->addBuiltInType(newType = new typeScalar(-4, sizeof(long), "long", true));
190    newType->decrRefCount();
191    // -5  unsigned char, 8 bit unsigned integral type
192    builtInTypes->addBuiltInType(newType = new typeScalar(-5, 1, "unsigned char"));
193    newType->decrRefCount();
194    // -6  signed char, 8 bit signed integral type
195    builtInTypes->addBuiltInType(newType = new typeScalar(-6, 1, "signed char", true));
196    newType->decrRefCount();
197    // -7  unsigned short, 16 bit unsigned integral type
198    builtInTypes->addBuiltInType(newType = new typeScalar(-7, 2, "unsigned short"));
199    newType->decrRefCount();
200    // -8  unsigned int, 32 bit unsigned integral type
201    builtInTypes->addBuiltInType(newType = new typeScalar(-8, 4, "unsigned int"));
202    newType->decrRefCount();
203    // -9  unsigned, 32 bit unsigned integral type
204    builtInTypes->addBuiltInType(newType = new typeScalar(-9, 4, "unsigned"));
205    newType->decrRefCount();
206    // -10 unsigned long, 32 bit unsigned integral type
207    builtInTypes->addBuiltInType(newType = new typeScalar(-10, sizeof(unsigned long), "unsigned long"));
208    newType->decrRefCount();
209    // -11 void, type indicating the lack of a value
210    //  XXX-size may not be correct jdd 4/22/99
211    builtInTypes->addBuiltInType(newType = new typeScalar(-11, 0, "void", false));
212    newType->decrRefCount();
213    // -12 float, IEEE single precision
214    builtInTypes->addBuiltInType(newType = new typeScalar(-12, sizeof(float), "float", true));
215    newType->decrRefCount();
216    // -13 double, IEEE double precision
217    builtInTypes->addBuiltInType(newType = new typeScalar(-13, sizeof(double), "double", true));
218    newType->decrRefCount();
219    // -14 long double, IEEE double precision, size may increase in future
220    builtInTypes->addBuiltInType(newType = new typeScalar(-14, sizeof(long double), "long double", true));
221    newType->decrRefCount();
222    // -15 integer, 32 bit signed integral type
223    builtInTypes->addBuiltInType(newType = new typeScalar(-15, 4, "integer", true));
224    newType->decrRefCount();
225    // -16 boolean, 32 bit type. GDB/GCC 0=False, 1=True, all other values
226    //  have unspecified meaning
227    builtInTypes->addBuiltInType(newType = new typeScalar(-16, sizeof(bool), "boolean"));
228    newType->decrRefCount();
229    // -17 short real, IEEE single precision
230    //  XXX-size may not be correct jdd 4/22/99
231    builtInTypes->addBuiltInType(newType = new typeScalar(-17, sizeof(float), "short real", true));
232    newType->decrRefCount();
233    // -18 real, IEEE double precision XXX-size may not be correct jdd 4/22/99
234    builtInTypes->addBuiltInType(newType = new typeScalar(-18, sizeof(double), "real", true));
235    newType->decrRefCount();
236    // -19 stringptr XXX- size of void * -- jdd 4/22/99
237    builtInTypes->addBuiltInType(newType = new typeScalar(-19, sizeof(void *), "stringptr"));
238    newType->decrRefCount();
239    // -20 character, 8 bit unsigned character type
240    builtInTypes->addBuiltInType(newType = new typeScalar(-20, 1, "character"));
241    newType->decrRefCount();
242    // -21 logical*1, 8 bit type (Fortran, used for boolean or unsigned int)
243    builtInTypes->addBuiltInType(newType = new typeScalar(-21, 1, "logical*1"));
244    newType->decrRefCount();
245    // -22 logical*2, 16 bit type (Fortran, some for boolean or unsigned int)
246    builtInTypes->addBuiltInType(newType = new typeScalar(-22, 2, "logical*2"));
247    newType->decrRefCount();
248    // -23 logical*4, 32 bit type (Fortran, some for boolean or unsigned int)
249    builtInTypes->addBuiltInType(newType = new typeScalar(-23, 4, "logical*4"));
250    newType->decrRefCount();
251    // -24 logical, 32 bit type (Fortran, some for boolean or unsigned int)
252    builtInTypes->addBuiltInType(newType = new typeScalar(-24, 4, "logical"));
253    newType->decrRefCount();
254    // -25 complex, consists of 2 IEEE single-precision floating point values
255    builtInTypes->addBuiltInType(newType = new typeScalar(-25, sizeof(float)*2, "complex", true));
256    newType->decrRefCount();
257    // -26 complex, consists of 2 IEEE double-precision floating point values
258    builtInTypes->addBuiltInType(newType = new typeScalar(-26, sizeof(double)*2, "complex*16", true));
259    newType->decrRefCount();
260    // -27 integer*1, 8 bit signed integral type
261    builtInTypes->addBuiltInType(newType = new typeScalar(-27, 1, "integer*1", true));
262    newType->decrRefCount();
263    // -28 integer*2, 16 bit signed integral type
264    builtInTypes->addBuiltInType(newType = new typeScalar(-28, 2, "integer*2", true));
265    newType->decrRefCount();
266
267    /* Quick hack to make integer*4 compatible with int for Fortran
268       jnb 6/20/01 */
269    // This seems questionable - let's try removing that hack - jmo 05/21/04
270    /*
271      builtInTypes->addBuiltInType(newType = new type("int",-29,
272      built_inType, 4));
273      newType->decrRefCount();
274    */
275    // -29 integer*4, 32 bit signed integral type
276    builtInTypes->addBuiltInType(newType = new typeScalar(-29, 4, "integer*4", true));
277    newType->decrRefCount();
278    // -30 wchar, Wide character, 16 bits wide, unsigned (unknown format)
279    builtInTypes->addBuiltInType(newType = new typeScalar(-30, 2, "wchar"));
280    newType->decrRefCount();
281 #if defined(os_windows)
282    // -31 long long, 64 bit signed integral type
283    builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long", true));
284    newType->decrRefCount();
285    // -32 unsigned long long, 64 bit unsigned integral type
286    builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(ULONGLONG), "unsigned long long"));
287    newType->decrRefCount();
288 #else
289    // -31 long long, 64 bit signed integral type
290    builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(long long), "long long", true));
291    newType->decrRefCount();
292    // -32 unsigned long long, 64 bit unsigned integral type
293    builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(unsigned long long), "unsigned long long"));
294    newType->decrRefCount();
295 #endif
296    // -33 logical*8, 64 bit unsigned integral type
297    builtInTypes->addBuiltInType(newType = new typeScalar(-33, 8, "logical*8"));
298    newType->decrRefCount();
299    // -34 integer*8, 64 bit signed integral type
300    builtInTypes->addBuiltInType(newType = new typeScalar(-34, 8, "integer*8", true));
301    newType->decrRefCount();
302
303    return builtInTypes;
304 }
305
306
307 boost::shared_ptr<typeCollection> Symtab::setupStdTypes() 
308 {
309     boost::shared_ptr<typeCollection> stdTypes =
310        boost::shared_ptr<typeCollection>(new typeCollection);
311
312    typeScalar *newType;
313
314    stdTypes->addType(newType = new typeScalar(-1, sizeof(int), "int"));
315    newType->decrRefCount();
316
317    Type *charType = new typeScalar(-2, sizeof(char), "char");
318    stdTypes->addType(charType);
319
320         std::string tName = "char *";
321         typePointer *newPtrType;
322    stdTypes->addType(newPtrType = new typePointer(-3, charType, tName));
323    charType->decrRefCount();
324    newPtrType->decrRefCount();
325
326    Type *voidType = new typeScalar(-11, 0, "void", false);
327    stdTypes->addType(voidType);
328
329         tName = "void *";
330    stdTypes->addType(newPtrType = new typePointer(-4, voidType, tName));
331    voidType->decrRefCount();
332    newPtrType->decrRefCount();
333
334    stdTypes->addType(newType = new typeScalar(-12, sizeof(float), "float"));
335    newType->decrRefCount();
336
337 #if defined(i386_unknown_nt4_0)
338    stdTypes->addType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long"));    
339 #else
340    stdTypes->addType(newType = new typeScalar(-31, sizeof(long long), "long long"));
341 #endif
342
343         newType->decrRefCount();
344
345    return stdTypes;
346 }
347
348 SYMTAB_EXPORT unsigned Symtab::getAddressWidth() const 
349 {
350    return address_width_;
351 }
352  
353 SYMTAB_EXPORT bool Symtab::getABIVersion(int &major, int &minor) const
354 {
355    return obj_private->getABIVersion(major, minor);
356 }
357
358 SYMTAB_EXPORT bool Symtab::isBigEndianDataEncoding() const
359 {
360    return obj_private->isBigEndianDataEncoding();
361 }
362
363 SYMTAB_EXPORT bool Symtab::isNativeCompiler() const 
364 {
365     return nativeCompiler; 
366 }
367
368 SYMTAB_EXPORT Symtab::Symtab(MappedFile *mf_) :
369    AnnotatableSparse(),
370    member_offset_(0),
371    parentArchive_(NULL),
372    mf(mf_), mfForDebugInfo(NULL),
373    imageOffset_(0), imageLen_(0),
374    dataOffset_(0), dataLen_(0),
375    is_a_out(false),
376    main_call_addr_(0),
377    nativeCompiler(false),
378    address_width_(sizeof(int)),
379    code_ptr_(NULL), data_ptr_(NULL),
380    entry_address_(0), base_address_(0), load_address_(0),
381    object_type_(obj_Unknown), is_eel_(false),
382    no_of_sections(0),
383    newSectionInsertPoint(0),
384    no_of_symbols(0),
385    sorted_everyFunction(false),
386    isTypeInfoValid_(false),
387    nlines_(0), fdptr_(0), lines_(NULL),
388    stabstr_(NULL), nstabs_(0), stabs_(NULL),
389    stringpool_(NULL),
390    hasRel_(false), hasRela_(false), hasReldyn_(false),
391    hasReladyn_(false), hasRelplt_(false), hasRelaplt_(false),
392    isStaticBinary_(false), isDefensiveBinary_(false),
393    func_lookup(NULL),
394    mod_lookup_(NULL),
395    obj_private(NULL),
396    _ref_cnt(1)
397 {
398     init_debug_symtabAPI();
399
400 #if defined(os_vxworks)
401     // This is how we initialize objects from WTX information alone.
402     // Basically replaces extractInfo().
403     object_type_ = obj_RelocatableFile;
404     // (... the rest are now initialized for everyone above ...)
405 #endif
406
407 }
408
409 SYMTAB_EXPORT Symtab::Symtab() :
410    LookupInterface(),
411    Serializable(),
412    AnnotatableSparse(),
413    member_offset_(0),
414    parentArchive_(NULL),
415    mf(NULL), mfForDebugInfo(NULL),
416    imageOffset_(0), imageLen_(0),
417    dataOffset_(0), dataLen_(0),
418    is_a_out(false),
419    main_call_addr_(0),
420    nativeCompiler(false),
421    address_width_(sizeof(int)),
422    code_ptr_(NULL), data_ptr_(NULL),
423    entry_address_(0), base_address_(0), load_address_(0),
424    object_type_(obj_Unknown), is_eel_(false),
425    no_of_sections(0),
426    newSectionInsertPoint(0),
427    no_of_symbols(0),
428    sorted_everyFunction(false),
429    isTypeInfoValid_(false),
430    nlines_(0), fdptr_(0), lines_(NULL),
431    stabstr_(NULL), nstabs_(0), stabs_(NULL),
432    stringpool_(NULL),
433    hasRel_(false), hasRela_(false), hasReldyn_(false),
434    hasReladyn_(false), hasRelplt_(false), hasRelaplt_(false),
435    isStaticBinary_(false), isDefensiveBinary_(false),
436    func_lookup(NULL),
437    mod_lookup_(NULL),
438    obj_private(NULL),
439    _ref_cnt(1)
440 {
441     init_debug_symtabAPI();
442     create_printf("%s[%d]: Created symtab via default constructor\n", FILE__, __LINE__);
443 }
444
445 SYMTAB_EXPORT bool Symtab::isExec() const 
446 {
447     return is_a_out; 
448 }
449
450 SYMTAB_EXPORT bool Symtab::isStripped() 
451 {
452 #if defined(os_linux) || defined(os_freebsd)
453     Region *sec;
454     return !findRegion(sec,".symtab");
455 #else
456     return (no_of_symbols==0);
457 #endif
458 }
459
460 SYMTAB_EXPORT Offset Symtab::preferedBase() const 
461 {
462     return preferedBase_;
463 }
464
465 SYMTAB_EXPORT Offset Symtab::imageOffset() const 
466 {
467     return imageOffset_;
468 }
469
470 SYMTAB_EXPORT Offset Symtab::dataOffset() const 
471
472     return dataOffset_;
473 }
474
475 SYMTAB_EXPORT Offset Symtab::dataLength() const 
476 {
477     return dataLen_;
478
479
480 SYMTAB_EXPORT Offset Symtab::imageLength() const 
481 {
482     return imageLen_;
483 }
484
485 SYMTAB_EXPORT void Symtab::fixup_code_and_data(Offset newImageOffset,
486                                                Offset newImageLength,
487                                                Offset newDataOffset,
488                                                Offset newDataLength)
489 {
490     imageOffset_ = newImageOffset;
491     imageLen_ = newImageLength;
492     dataOffset_ = newDataOffset;
493     dataLen_ = newDataLength;
494
495     // Should we update the underlying Object?
496 }
497
498 /*
499 SYMTAB_EXPORT char* Symtab::image_ptr ()  const 
500 {
501    return code_ptr_;
502 }
503
504 SYMTAB_EXPORT char* Symtab::data_ptr ()  const 
505
506    return data_ptr_;
507 }
508 */
509 SYMTAB_EXPORT const char*  Symtab::getInterpreterName() const 
510 {
511    if (interpreter_name_.length())
512       return interpreter_name_.c_str();
513    return NULL;
514 }
515  
516 SYMTAB_EXPORT Offset Symtab::getEntryOffset() const 
517
518    return entry_address_;
519 }
520
521 SYMTAB_EXPORT Offset Symtab::getBaseOffset() const 
522 {
523    return base_address_;
524 }
525
526 SYMTAB_EXPORT Offset Symtab::getLoadOffset() const 
527
528    return load_address_;
529 }
530
531 SYMTAB_EXPORT Offset Symtab::getTOCoffset(Function *func) const 
532 {
533   return getTOCoffset(func ? func->getOffset() : 0); 
534 }
535
536 SYMTAB_EXPORT Offset Symtab::getTOCoffset(Offset off) const
537 {
538   return obj_private->getTOCoffset(off);
539 }
540
541 void Symtab::setTOCOffset(Offset off) {
542   obj_private->setTOCoffset(off);
543   return;
544 }
545
546 SYMTAB_EXPORT string Symtab::getDefaultNamespacePrefix() const
547 {
548     return defaultNamespacePrefix;
549 }
550         
551         
552 // TODO -- is this g++ specific
553 bool Symtab::buildDemangledName( const std::string &mangled, 
554       std::string &pretty,
555       std::string &typed,
556       bool nativeCompiler, 
557       supportedLanguages lang )
558 {
559    /* The C++ demangling function demangles MPI__Allgather (and other MPI__
560     * functions with start with A) into the MPI constructor.  In order to
561     * prevent this a hack needed to be made, and this seemed the cleanest
562     * approach.
563     */
564
565    if ((mangled.length()>5) && (mangled.substr(0,5)==std::string("MPI__"))) 
566    {
567       return false;
568    }      
569
570    /* If it's Fortran, eliminate the trailing underscores, if any. */
571    if (lang == lang_Fortran 
572          || lang == lang_CMFortran 
573          || lang == lang_Fortran_with_pretty_debug )
574    {
575       if ( mangled[ mangled.length() - 1 ] == '_' ) 
576       {
577          char * demangled = P_strdup( mangled.c_str() );
578          demangled[ mangled.length() - 1 ] = '\0';
579          pretty = std::string( demangled );
580
581          free ( demangled );
582          return true;
583       }
584       else 
585       {
586          /* No trailing underscores, do nothing */
587          return false;
588       }
589    } /* end if it's Fortran. */
590
591    //  Check to see if we have a gnu versioned symbol on our hands.
592    //  These are of the form <symbol>@<version> or <symbol>@@<version>
593    //
594    //  If we do, we want to create a "demangled" name for the one that
595    //  is of the form <symbol>@@<version> since this is, by definition,
596    //  the default.  The "demangled" name will just be <symbol>
597
598    //  NOTE:  this is just a 0th order approach to dealing with versioned
599    //         symbols.  We may need to do something more sophisticated
600    //         in the future.  JAW 10/03
601
602 #if !defined(os_windows)
603
604    const char *atat;
605
606    if (NULL != (atat = strstr(mangled.c_str(), "@@"))) 
607    {
608         pretty = mangled.substr(0 /*start pos*/, 
609                         (int)(atat - mangled.c_str())/*len*/);
610         //char msg[256];
611         //sprintf(msg, "%s[%d]: 'demangling' versioned symbol: %s, to %s",
612         //          __FILE__, __LINE__, mangled.c_str(), pretty.c_str());
613
614         //cerr << msg << endl;
615         //logLine(msg);
616       
617         return true;
618     }
619
620 #endif
621
622     bool retval = false;
623   
624     /* Try demangling it. */
625     char * demangled = P_cplus_demangle( mangled.c_str(), nativeCompiler, false);
626     if (demangled) 
627     {
628         pretty = std::string( demangled );
629         retval = true;
630     }
631   
632     char *t_demangled = P_cplus_demangle(mangled.c_str(), nativeCompiler, true);
633     if (t_demangled && (strcmp(t_demangled, demangled) != 0)) 
634     {
635         typed = std::string(t_demangled);
636         retval = true;
637     }
638
639     if (demangled)
640         free(demangled);
641     if (t_demangled)
642         free(t_demangled);
643
644     return retval;
645 } /* end buildDemangledName() */
646
647
648 /*
649  * extractSymbolsFromFile
650  *
651  * Create a Symtab-level list of symbols by pulling out data
652  * from the low-level parse (linkedFile).
653  * Technically this causes a duplication of symbols; however,
654  * we will be rewriting these symbols and so we need our own
655  * copy. 
656  *
657  * TODO: delete the linkedFile once we're done?
658  */
659
660 bool Symtab::extractSymbolsFromFile(Object *linkedFile, std::vector<Symbol *> &raw_syms) 
661 {
662    for (SymbolIter symIter(*linkedFile); symIter; symIter++)  {
663       Symbol *sym = symIter.currval();
664       if (!sym)  {
665          create_printf("%s[%d]:  range error, stopping now\n", FILE__, __LINE__);
666          return true;
667       }
668
669       // If a symbol starts with "." we want to skip it. These indicate labels in the
670       // code. 
671       
672       // removed 1/09: this should be done in Dyninst, not Symtab
673       
674       // Have to do this before the undef check, below. 
675       fixSymRegion(sym);
676       
677       // check for undefined dynamic symbols. Used when rewriting relocation section.
678       // relocation entries have references to these undefined dynamic symbols.
679       // We also have undefined symbols for the static binary case.
680
681 #if !defined(os_vxworks)
682       if (sym->getRegion() == NULL && !sym->isAbsolute() && !sym->isCommonStorage()) {
683          undefDynSyms.insert(sym);
684          continue;
685       }
686 #endif
687       
688       // Check whether this symbol has a valid offset. If they do not we have a
689       // consistency issue. This should be a null check.
690       
691       // Symbols can have an offset of 0 if they don't refer to things within a file.
692       
693       raw_syms.push_back(sym);
694    }
695    
696    return true;
697 }
698
699 bool Symtab::fixSymRegion(Symbol *sym) {
700    if (!sym->getRegion()) return true;
701    
702    if (sym->getType() != Symbol::ST_FUNCTION &&
703        sym->getType() != Symbol::ST_OBJECT) return true;
704    
705    if (sym->getRegion()->getMemOffset() <= sym->getOffset() &&
706        (sym->getRegion()->getMemOffset() + sym->getRegion()->getMemSize()) > sym->getOffset())
707       return true;
708    
709    sym->setRegion(findEnclosingRegion(sym->getOffset()));
710    
711    return true;
712 }
713
714 /*
715  * fixSymModules
716  * 
717  * Add Module information to all symbols. 
718  */
719
720 bool Symtab::fixSymModules(std::vector<Symbol *> &raw_syms) 
721 {
722     Object *obj = getObject();
723     if (!obj) {
724        return false;
725     }
726     for (auto i = indexed_modules.begin(); i != indexed_modules.end(); ++i)
727     {
728         (*i)->finalizeRanges();
729     }
730
731 //    const std::vector<std::pair<std::string, Offset> > &mods = obj->modules_;
732 //    for (unsigned i=0; i< mods.size(); i++) {
733 //       getOrCreateModule(mods[i].first, mods[i].second);
734 //    }
735     for (unsigned i = 0; i < raw_syms.size(); i++) {
736         fixSymModule(raw_syms[i]);
737     }
738
739     return true;
740 }
741
742 /*
743  * demangleSymbols
744  *
745  * Perform name demangling on all symbols.
746  */
747
748 bool Symtab::demangleSymbols(std::vector<Symbol *> &raw_syms) 
749 {
750     for (unsigned i = 0; i < raw_syms.size(); i++) {
751         demangleSymbol(raw_syms[i]);
752     }
753     return true;
754 }
755
756 /*
757  * createIndices
758  *
759  * We index symbols by various attributes for quick lookup. Build those
760  * indices here. 
761  */
762
763 bool Symtab::createIndices(std::vector<Symbol *> &raw_syms, bool undefined) {
764     for (unsigned i = 0; i < raw_syms.size(); i++) {
765        addSymbolToIndices(raw_syms[i], undefined);
766     }
767     return true;
768 }
769
770 /*
771  * createAggregates
772  *
773  * Frequently there will be multiple Symbols that refer to a single 
774  * code object (e.g., function or variable). We use separate objects
775  * to refer to these aggregates, and build those objects here. 
776  */
777
778 bool Symtab::createAggregates() 
779 {
780 #if !defined(os_vxworks)
781     // In VxWorks, symbol offsets are not complete until object is loaded.
782
783   for(auto i = everyDefinedSymbol.begin();
784       i != everyDefinedSymbol.end();
785       ++i)
786   {
787     if (!doNotAggregate(*i)) {
788       addSymbolToAggregates(*i);
789     }
790   }
791 #endif
792
793     return true;
794 }
795  
796 bool Symtab::fixSymModule(Symbol *&sym) 
797 {
798     Module* mod = NULL;
799     findModuleByOffset(mod, sym->getOffset());
800     if(!mod) mod = getDefaultModule();
801     sym->setModule(mod);
802     return true;
803 }
804
805 bool Symtab::demangleSymbol(Symbol *&sym) {
806    bool typed_demangle = false;
807    if (sym->getType() == Symbol::ST_FUNCTION) typed_demangle = true;
808
809    // This is a bit of a hack; we're trying to demangle undefined symbols which don't necessarily
810    // have a ST_FUNCTION type. 
811    if (sym->getRegion() == NULL && !sym->isAbsolute() && !sym->isCommonStorage())
812       typed_demangle = true;
813
814    if (typed_demangle) {
815       Module *rawmod = sym->getModule();
816
817       // At this point we need to generate the following information:
818       // A symtab name.
819       // A pretty (demangled) name.
820       // The symtab name goes in the global list as well as the module list.
821       // Same for the pretty name.
822       // Finally, check addresses to find aliases.
823       
824       std::string mangled_name = sym->getMangledName();
825       std::string working_name = mangled_name;
826       
827 #if !defined(os_windows)        
828       //Remove extra stabs information
829        size_t colon = working_name.find(":");
830        if(colon != std::string::npos) {
831            working_name = working_name.substr(0, colon);
832        }
833 #endif
834       
835       std::string pretty_name = working_name;
836       std::string typed_name = working_name;
837       
838       if (!buildDemangledName(working_name, pretty_name, typed_name,
839                               nativeCompiler, (rawmod ? rawmod->language() : lang_Unknown))) {
840          pretty_name = working_name;
841       }
842       
843       //sym->prettyName_ = pretty_name;
844       //sym->typedName_ = typed_name;
845    }
846    else {
847        // All cases where there really shouldn't be a mangled
848       // name, since mangling is for functions.
849       
850       char *prettyName = P_cplus_demangle(sym->getMangledName().c_str(), nativeCompiler, false);
851       if (prettyName) {
852         //sym->prettyName_ = std::string(prettyName);
853          // XXX caller-freed
854          free(prettyName); 
855       }
856    }
857
858    return true;
859 }
860
861 bool Symtab::addSymbolToIndices(Symbol *&sym, bool undefined) 
862 {
863    assert(sym);
864    if (!undefined) {
865      if(everyDefinedSymbol.find(sym) == everyDefinedSymbol.end())
866        everyDefinedSymbol.insert(sym);
867       //      symsByMangledName[sym->getMangledName()].push_back(sym);
868       //symsByPrettyName[sym->getPrettyName()].push_back(sym);
869       //symsByTypedName[sym->getTypedName()].push_back(sym);
870 #if !defined(os_vxworks)    
871       // VxWorks doesn't know symbol addresses until object is loaded.
872       //symsByOffset[sym->getOffset()].push_back(sym);
873 #endif
874    }
875    else {
876       // We keep a different index for undefined symbols
877       //undefDynSymsByMangledName[sym->getMangledName()].push_back(sym);
878       //undefDynSymsByPrettyName[sym->getPrettyName()].push_back(sym);
879       //undefDynSymsByTypedName[sym->getTypedName()].push_back(sym);
880       // And undefDynSyms is already filled in
881    }
882    
883     return true;
884 }
885
886 bool Symtab::addSymbolToAggregates(const Symbol *sym_tmp) 
887 {
888   Symbol* sym = const_cast<Symbol*>(sym_tmp);
889   
890     switch(sym->getType()) {
891     case Symbol::ST_FUNCTION: 
892     case Symbol::ST_INDIRECT:
893       {
894         // We want to do the following:
895         // If no function exists, create and add. 
896         // Combine this information
897         //   Add this symbol's names to the function.
898         //   Keep module information 
899
900         Function *func = NULL;
901         findFuncByEntryOffset(func, sym->getOffset());
902         if (!func) {
903             // Create a new function
904             // Also, update the symbol to point to this function.
905
906             func = new Function(sym);
907
908             everyFunction.push_back(func);
909             sorted_everyFunction = false;
910             funcsByOffset[sym->getOffset()] = func;
911         }
912         else {
913             /* XXX 
914              * For relocatable files, the offset of a symbol is relative to the
915              * beginning of a Region. Therefore, a symbol in a relocatable file
916              * is not uniquely identifiable by its offset, but it is uniquely
917              * identifiable by its Region and its offset.
918              *
919              * For now, do not add these functions to funcsByOffset collection.
920              */
921
922             if( func->getRegion() != sym->getRegion() ) {
923                 func = new Function(sym);
924                 everyFunction.push_back(func);
925                 sorted_everyFunction = false;
926             }
927             func->addSymbol(sym);
928         } 
929         sym->setFunction(func);
930
931         break;
932     }
933     case Symbol::ST_TLS:
934     case Symbol::ST_OBJECT: {
935         // The same as the above, but with variables.
936         Variable *var = NULL;
937         findVariableByOffset(var, sym->getOffset());
938         if (!var) {
939             // Create a new function
940             // Also, update the symbol to point to this function.
941             var = new Variable(sym);
942             
943             everyVariable.push_back(var);
944             varsByOffset[sym->getOffset()] = var;
945         }
946         else {
947             /* XXX
948              * For relocatable files, the offset is not a unique identifier for
949              * a Symbol. With functions, the Region and offset could be used to
950              * identify the symbol. With variables, the Region and offset may 
951              * not uniquely identify the symbol. The only case were this occurs
952              * is with COMMON symbols -- their offset is their memory alignment
953              * and their Region is undefined. In this case, always create a 
954              * new variable.
955              */
956             if( obj_RelocatableFile == getObjectType() &&
957                 ( var->getRegion() != sym->getRegion() ||
958                   NULL == sym->getRegion() ) )
959             {
960                 var = new Variable(sym);
961                 everyVariable.push_back(var);
962             }else{
963                 var->addSymbol(sym);
964             }
965         }
966         sym->setVariable(var);
967         break;
968     }
969     default: {
970         break;
971     }
972     }
973     return true;
974 }
975
976 // A hacky override for specially treating symbols that appear
977 // to be functions or variables but aren't.
978 //
979 // Example: IA-32/AMD-64 libc (and others compiled with libc headers)
980 // uses outlined locking primitives. These are named _L_lock_<num>
981 // and _L_unlock_<num> and labelled as functions. We explicitly do
982 // not include them in function scope.
983 //
984 // Also, exclude symbols that begin with _imp_ in defensive mode.
985 // These symbols are entries in the IAT and shouldn't be treated
986 // as functions.
987 bool Symtab::doNotAggregate(const Symbol* sym) {
988     const std::string& mangled = sym->getMangledName();
989
990     if (isDefensiveBinary() && mangled.compare(0, 5, "_imp_", 5) == 0) {
991         return true;
992     }
993
994   if (mangled.compare(0, strlen("_L_lock_"), "_L_lock_") == 0) {
995     return true;
996   }
997   if (mangled.compare(0, strlen("_L_unlock_"), "_L_unlock_") == 0) {
998     return true;
999   }
1000
1001 #if 0
1002   // Disabling as a test; this means we find _zero_ Function objects. 
1003   // PPC64 Linux symbols in the .opd section appear to be functions,
1004   // but are not.
1005   if (sym->getRegion() && sym->getRegion()->getRegionName() == ".opd") {
1006       return true;
1007   }
1008 #endif
1009   return false;
1010 }
1011
1012 /* Add the new name to the appropriate symbol index */
1013
1014 bool Symtab::updateIndices(Symbol * /*sym*/, std::string /*newName*/, NameType /*nameType*/) {
1015
1016 #if 0
1017      if (nameType & mangledName) {
1018         // Add this symbol under the given name (as mangled)
1019         symsByMangledName[newName].push_back(sym);
1020     }
1021     if (nameType & prettyName) {
1022         // Add this symbol under the given name (as pretty)
1023         symsByPrettyName[newName].push_back(sym);
1024     }
1025     if (nameType & typedName) {
1026         // Add this symbol under the given name (as typed)
1027         symsByTypedName[newName].push_back(sym);
1028     }
1029 #endif
1030     return true;
1031 }
1032
1033 #if 0
1034 /* checkPPC64DescriptorSymbols() is no longer needed.  3-word descriptor
1035  * symbols are properly taken care of during symbol parsing.  See
1036  * parse_symbols() in Object-elf.C for details.
1037  */
1038
1039 #if defined(ppc64_linux)
1040 /* Special case for ppc64 ELF binaries. Sometimes a function has a 3-byte descriptor symbol
1041  * along with it in the symbol table and "." preceding its original pretty name for the correct
1042  * function symbol. This checks to see if we have a corresponding 3-byte descriptor symbol existing
1043  * and if it does we remove the preceding "." from the name of the symbol
1044  */
1045
1046 void Symtab::checkPPC64DescriptorSymbols(Object *linkedFile)
1047 {
1048    // find the real functions -- those with the correct type in the symbol table
1049    for(SymbolIter symIter(*linkedFile); symIter;symIter++)
1050    {
1051       Symbol *lookUp = symIter.currval();
1052       const char *np = lookUp->getMangledName().c_str();
1053       if(!np)
1054          continue;
1055
1056       if(np[0] == '.' && (lookUp->getType() == Symbol::ST_FUNCTION))
1057       {
1058          std::vector<Symbol *>syms;
1059          std::string newName = np+1;
1060          if(linkedFile->get_symbols(newName, syms) && (syms[0]->getSize() == 24 || syms[0]->getSize() == 0))
1061          {
1062             //Remove the "." from the name
1063             lookUp->mangledNames[0] = newName;
1064
1065             //Change the type of the descriptor symbol
1066             syms[0]->type_ = Symbol::ST_NOTYPE;
1067          }
1068       }
1069    }
1070
1071 }
1072
1073 #endif
1074 #endif
1075
1076 //  setModuleLanguages is only called after modules have been defined.
1077 //  it attempts to set each module's language, information which is needed
1078 //  before names can be demangled.
1079 void Symtab::setModuleLanguages(dyn_hash_map<std::string, supportedLanguages> *mod_langs)
1080 {
1081    if (!mod_langs->size())
1082       return;  // cannot do anything here
1083    //  this case will arise on non-stabs platforms until language parsing can be introduced at this level
1084    Module *currmod = NULL;
1085    //int dump = 0;
1086
1087     for (auto i = indexed_modules.begin(); i != indexed_modules.end(); ++i)
1088    {
1089       currmod = (*i);
1090       supportedLanguages currLang;
1091       if (currmod->isShared()) {
1092          continue;  // need to find some way to get shared object languages?
1093       }
1094
1095       const std::string fn = currmod->fileName();
1096       if (mod_langs->find(currmod->fileName()) != mod_langs->end())
1097       {
1098          currLang = (*mod_langs)[fn];
1099       }
1100       else if (fn.rfind(".s") != std::string::npos ||
1101             fn.rfind(".asm") != std::string::npos)
1102       {
1103          currLang = lang_Assembly;
1104       }
1105       else if (fn.rfind(".c") != std::string::npos)
1106       {
1107          currLang = lang_C;
1108       }
1109       else if (fn.rfind(".cpp") != std::string::npos ||
1110             fn.rfind(".cc") != std::string::npos ||
1111             fn.rfind(".C") != std::string::npos)
1112       {
1113          currLang = lang_CPlusPlus;
1114       }
1115       else
1116       {
1117          continue;
1118       }
1119       currmod->setLanguage(currLang);
1120    }
1121 }
1122
1123 void Symtab::createDefaultModule() {
1124     assert(indexed_modules.empty());
1125     Module *mod = new Module(lang_Unknown,
1126                      imageOffset_,
1127                      name(),
1128                      this);
1129     mod->addRange(imageOffset_, imageLen_ + imageOffset_);
1130     indexed_modules.push_back(mod);
1131     mod->finalizeRanges();
1132 }
1133
1134
1135
1136 Module *Symtab::getOrCreateModule(const std::string &modName, 
1137                                   const Offset modAddr)
1138 {
1139     if(indexed_modules.empty()) {
1140         createDefaultModule();
1141     }
1142    std::string nameToUse;
1143    if (modName.length() > 0)
1144       nameToUse = modName;
1145    else
1146       nameToUse = "DEFAULT_MODULE";
1147
1148    Module *fm = NULL;
1149    if (findModuleByName(fm, nameToUse)) 
1150    {
1151        if(modAddr && (modAddr < fm->addr()))
1152        {
1153            fm->addr_ = modAddr;
1154        }
1155       return fm;
1156    }
1157
1158     const char *str = nameToUse.c_str();
1159     int len = nameToUse.length();
1160     assert(len>0);
1161
1162     // TODO ignore directory definitions for now
1163     if (str[len-1] == '/') 
1164         return NULL;
1165
1166     return (newModule(nameToUse, modAddr, lang_Unknown));
1167 }
1168  
1169 Module *Symtab::newModule(const std::string &name, const Offset addr, supportedLanguages lang)
1170 {
1171     Module *ret = NULL;
1172     // modules can be defined several times in C++ due to templates and
1173     //   in-line member functions.
1174
1175     if (findModuleByName(ret, name)) 
1176     {
1177         return(ret);
1178     }
1179
1180     //parsing_printf("=== image, creating new pdmodule %s, addr 0x%x\n",
1181     //                          name.c_str(), addr);
1182     
1183     std::string fileNm, fullNm;
1184     fullNm = name;
1185     fileNm = extract_pathname_tail(name);
1186
1187     create_printf("%s[%d]: In %p: Creating new module '%s'/'%s'\n", FILE__, __LINE__, this, fileNm.c_str(), fullNm.c_str());
1188
1189     ret = new Module(lang, addr, fullNm, this);
1190     assert(ret);
1191
1192     /*
1193      * FIXME
1194      *
1195      * There are cases where the fileName can be the same, but the full name is
1196      * different and the modules are actually different. This is an inherent
1197      * problem with how modules are processed.
1198      */
1199     if (indexed_modules.get<2>().end() != indexed_modules.get<2>().find(ret->fileName()))
1200     {
1201        create_printf("%s[%d]:  WARN:  LEAK?  already have module with name %s\n", 
1202              FILE__, __LINE__, ret->fileName().c_str());
1203     }
1204
1205     if (indexed_modules.get<3>().end() != indexed_modules.get<3>().find(ret->fullName()))
1206     {
1207        create_printf("%s[%d]:  WARN:  LEAK?  already have module with name %s\n", 
1208                      FILE__, __LINE__, ret->fullName().c_str());
1209     }
1210
1211     indexed_modules.push_back(ret);
1212     
1213     return (ret);
1214 }
1215
1216 Symtab::Symtab(std::string filename, bool defensive_bin, bool &err) :
1217    LookupInterface(),
1218    Serializable(),
1219    AnnotatableSparse(),
1220    member_offset_(0),
1221    parentArchive_(NULL),
1222    mf(NULL), mfForDebugInfo(NULL),
1223    imageOffset_(0), imageLen_(0),
1224    dataOffset_(0), dataLen_(0),
1225    is_a_out(false),
1226    main_call_addr_(0),
1227    nativeCompiler(false),
1228    address_width_(sizeof(int)),
1229    code_ptr_(NULL), data_ptr_(NULL),
1230    entry_address_(0), base_address_(0), load_address_(0),
1231    object_type_(obj_Unknown), is_eel_(false),
1232    no_of_sections(0),
1233    newSectionInsertPoint(0),
1234    no_of_symbols(0),
1235    sorted_everyFunction(false),
1236    isTypeInfoValid_(false),
1237    nlines_(0), fdptr_(0), lines_(NULL),
1238    stabstr_(NULL), nstabs_(0), stabs_(NULL),
1239    stringpool_(NULL),
1240    hasRel_(false), hasRela_(false), hasReldyn_(false),
1241    hasReladyn_(false), hasRelplt_(false), hasRelaplt_(false),
1242    isStaticBinary_(false), isDefensiveBinary_(defensive_bin),
1243    func_lookup(NULL),
1244    mod_lookup_(NULL),
1245    obj_private(NULL),
1246    _ref_cnt(1)
1247 {
1248     init_debug_symtabAPI();
1249    // Initialize error parameter
1250    err = false;
1251    
1252    create_printf("%s[%d]: created symtab for %s\n", FILE__, __LINE__, filename.c_str());
1253
1254 #if defined (os_windows)
1255    extern void fixup_filename(std::string &);
1256    fixup_filename(filename);
1257 #endif
1258
1259    //  createMappedFile handles reference counting
1260    mf = MappedFile::createMappedFile(filename);
1261    if (!mf) {
1262       create_printf("%s[%d]: WARNING: creating symtab for %s, " 
1263                     "createMappedFile() failed\n", FILE__, __LINE__, 
1264                     filename.c_str());
1265       err = true;
1266       return;
1267    }
1268
1269    obj_private = new Object(mf, defensive_bin, 
1270                             symtab_log_perror, true, this);
1271    if (obj_private->hasError()) {
1272      err = true;
1273      return;
1274    }
1275    if (!extractInfo(obj_private))
1276    {
1277       create_printf("%s[%d]: WARNING: creating symtab for %s, extractInfo() " 
1278                     "failed\n", FILE__, __LINE__, filename.c_str());
1279       err = true;
1280    }
1281
1282    member_name_ = mf->filename();
1283
1284    defaultNamespacePrefix = "";
1285 }
1286
1287 Symtab::Symtab(unsigned char *mem_image, size_t image_size, 
1288                const std::string &name, bool defensive_bin, bool &err) :
1289    LookupInterface(),
1290    Serializable(),
1291    AnnotatableSparse(),
1292    member_offset_(0),
1293    parentArchive_(NULL),
1294    mf(NULL), mfForDebugInfo(NULL),
1295    imageOffset_(0), imageLen_(0),
1296    dataOffset_(0), dataLen_(0),
1297    is_a_out(false),
1298    main_call_addr_(0),
1299    nativeCompiler(false),
1300    address_width_(sizeof(int)),
1301    code_ptr_(NULL), data_ptr_(NULL),
1302    entry_address_(0), base_address_(0), load_address_(0),
1303    object_type_(obj_Unknown), is_eel_(false),
1304    no_of_sections(0),
1305    newSectionInsertPoint(0),
1306    no_of_symbols(0),
1307    sorted_everyFunction(false),
1308    isTypeInfoValid_(false),
1309    nlines_(0), fdptr_(0), lines_(NULL),
1310    stabstr_(NULL), nstabs_(0), stabs_(NULL),
1311    stringpool_(NULL),
1312    hasRel_(false), hasRela_(false), hasReldyn_(false),
1313    hasReladyn_(false), hasRelplt_(false), hasRelaplt_(false),
1314    isStaticBinary_(false),
1315    isDefensiveBinary_(defensive_bin),
1316    func_lookup(NULL),
1317    mod_lookup_(NULL),
1318    obj_private(NULL),
1319    _ref_cnt(1)
1320 {
1321    // Initialize error parameter
1322    err = false;
1323   
1324    create_printf("%s[%d]: created symtab for memory image at addr %u\n", 
1325                  FILE__, __LINE__, mem_image);
1326
1327    //  createMappedFile handles reference counting
1328    mf = MappedFile::createMappedFile(mem_image, image_size, name);
1329    if (!mf) {
1330       create_printf("%s[%d]: WARNING: creating symtab for memory image at " 
1331                     "addr %u, createMappedFile() failed\n", FILE__, __LINE__, 
1332                     mem_image);
1333       err = true;
1334       return;
1335    }
1336
1337    obj_private = new Object(mf, defensive_bin, 
1338                             symtab_log_perror, true, this);
1339    if (obj_private->hasError()) {
1340      err = true;
1341      return;
1342    }
1343
1344    if (!extractInfo(obj_private))
1345    {
1346       create_printf("%s[%d]: WARNING: creating symtab for memory image at addr" 
1347                     "%u, extractInfo() failed\n", FILE__, __LINE__, mem_image);
1348       err = true;
1349    }
1350
1351    member_name_ = mf->filename();
1352
1353    defaultNamespacePrefix = "";
1354 }
1355
1356 bool sort_reg_by_addr(const Region* a, const Region* b)
1357 {
1358   if (a->getMemOffset() == b->getMemOffset())
1359     return a->getMemSize() < b->getMemSize();
1360   return a->getMemOffset() < b->getMemOffset();
1361 }
1362
1363 extern void print_symbols( std::vector< Symbol *>& allsymbols );
1364 extern void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols);
1365
1366 static bool ExceptionBlockCmp(ExceptionBlock *a, ExceptionBlock *b) {
1367     return a->catchStart() < b->catchStart();
1368 }
1369
1370 bool Symtab::extractInfo(Object *linkedFile)
1371 {
1372 #if defined(TIMED_PARSE)
1373     struct timeval starttime;
1374     gettimeofday(&starttime, NULL);
1375 #endif
1376
1377     /* FIXME 
1378      *
1379      * Some ELF .o's don't have contiguous code and data Regions so these data
1380      * members are imprecise. These members should probably be deprecated in
1381      * favor of the getCodeRegions and getDataRegions functions.
1382      */
1383 #if defined(os_windows)
1384         preferedBase_ = linkedFile->getPreferedBase();
1385 #else
1386         preferedBase_ = 0;
1387 #endif
1388     imageOffset_ = linkedFile->code_off();
1389     dataOffset_ = linkedFile->data_off();
1390
1391 #if defined(os_windows)
1392         preferedBase_ = linkedFile->getPreferedBase();
1393 #else
1394         preferedBase_ = 0;
1395 #endif
1396
1397     imageLen_ = linkedFile->code_len();
1398     dataLen_ = linkedFile->data_len();
1399     
1400     if (0 == imageLen_ || 0 == linkedFile->code_ptr()) 
1401     {
1402        if (0 == linkedFile->code_ptr()) {
1403           linkedFile->code_ptr_ = (char *) linkedFile->code_off();
1404        }
1405        else 
1406        {
1407            if( object_type_ != obj_RelocatableFile ||
1408                linkedFile->code_ptr() == 0)
1409            {
1410                 serr = Obj_Parsing;
1411                 return false;
1412            }
1413        }
1414    }
1415         
1416   //  if (!imageLen_ || !linkedFile->code_ptr()) {
1417   //      serr = Obj_Parsing; 
1418   //      return false; 
1419    // }
1420
1421     no_of_sections = linkedFile->no_of_sections();
1422     newSectionInsertPoint = no_of_sections;
1423     no_of_symbols = linkedFile->no_of_symbols();
1424     
1425     isStaticBinary_ = linkedFile->isStaticBinary();
1426
1427     hasRel_ = false;
1428     hasRela_ = false;
1429     hasReldyn_ = false;
1430     hasReladyn_ = false;
1431     hasRelplt_ = false;
1432     hasRelaplt_ = false;
1433     regions_ = linkedFile->getAllRegions();
1434
1435     for (unsigned index=0;index<regions_.size();index++)
1436       {
1437       regions_[index]->setSymtab(this);
1438
1439         if ( regions_[index]->isLoadable() ) 
1440         {
1441            if (     (regions_[index]->getRegionPermissions() == Region::RP_RX) 
1442                  || (isDefensiveBinary_ && 
1443                      regions_[index]->getRegionPermissions() == Region::RP_RW)
1444                  || (regions_[index]->getRegionPermissions() == Region::RP_RWX)) 
1445            {
1446               codeRegions_.push_back(regions_[index]);
1447            }
1448            else 
1449            {
1450               dataRegions_.push_back(regions_[index]);
1451            }
1452         }
1453
1454         regionsByEntryAddr[regions_[index]->getMemOffset()] = regions_[index];
1455
1456         if (regions_[index]->getRegionType() == Region::RT_REL) 
1457         {
1458             hasRel_ = true;
1459         }
1460
1461         if (regions_[index]->getRegionType() == Region::RT_RELA) 
1462         {
1463             hasRela_ = true;
1464         }
1465
1466 #if defined(os_linux) || defined(os_freebsd)
1467         hasReldyn_ = linkedFile->hasReldyn();
1468         hasReladyn_ = linkedFile->hasReladyn();
1469         hasRelplt_ = linkedFile->hasRelplt();
1470         hasRelaplt_ = linkedFile->hasRelaplt();
1471 #endif  
1472
1473     }
1474     // sort regions_ & codeRegions_ vectors
1475
1476     std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
1477     std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
1478     std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
1479
1480     /* insert error check here. check if parsed */
1481     address_width_ = linkedFile->getAddressWidth();
1482     is_a_out = linkedFile->is_aout();
1483     code_ptr_ = linkedFile->code_ptr();
1484     data_ptr_ = linkedFile->data_ptr();
1485
1486     if (linkedFile->interpreter_name())
1487        interpreter_name_ = std::string(linkedFile->interpreter_name());
1488
1489     entry_address_ = linkedFile->getEntryAddress();
1490     base_address_ = linkedFile->getBaseAddress();
1491     load_address_ = linkedFile->getLoadAddress();
1492     object_type_  = linkedFile->objType();
1493     is_eel_ = linkedFile->isEEL();
1494     linkedFile->getSegments(segments_);
1495
1496 #if defined(os_linux) || defined(os_freebsd)
1497     // make sure we're using the right demangler
1498     
1499     nativeCompiler = parseCompilerType(linkedFile);
1500     //parsing_printf("isNativeCompiler: %d\n", nativeCompiler);
1501 #endif
1502     
1503     // define all of the functions
1504     //statusLine("winnowing functions");
1505
1506     // a vector to hold all created symbols until they are properly classified
1507     std::vector<Symbol *> raw_syms;
1508
1509 #ifdef BINEDIT_DEBUG
1510     printf("== from linkedFile...\n");
1511     print_symbol_map(linkedFile->getAllSymbols());
1512 #endif
1513
1514     if (!extractSymbolsFromFile(linkedFile, raw_syms)) 
1515     {
1516         serr = Syms_To_Functions;
1517         return false;
1518     }
1519
1520     if (!fixSymModules(raw_syms)) 
1521     {
1522         serr = Syms_To_Functions;
1523         return false;
1524     }
1525         Object *obj = getObject();
1526         if (!obj)
1527         {
1528                 return false;
1529         }
1530     obj->clearSymsToMods();
1531
1532     // wait until all modules are defined before applying languages to
1533     // them we want to do it this way so that module information comes
1534     // from the function symbols, first and foremost, to avoid any
1535     // internal module-function mismatching.
1536             
1537     // get Information on the language each modules is written in
1538     // (prior to making modules)
1539
1540     dyn_hash_map<std::string, supportedLanguages> mod_langs;
1541     linkedFile->getModuleLanguageInfo(&mod_langs);
1542     setModuleLanguages(&mod_langs);
1543         
1544     // Be sure that module languages are set before demangling, or
1545     // we won't get very far.
1546
1547     /*    if (!demangleSymbols(raw_syms)) 
1548     {
1549         serr = Syms_To_Functions;
1550         return false;
1551     }
1552     
1553     if (!demangleSymbols(undefDynSyms)) {
1554        serr = Syms_To_Functions;
1555        return false;
1556     }
1557     */
1558     if (!createIndices(raw_syms, false)) 
1559     {
1560         serr = Syms_To_Functions;
1561         return false;
1562     }
1563
1564     //if (!createIndices(undefDynSyms, true)) 
1565     //{
1566     //    serr = Syms_To_Functions;
1567     //    return false;
1568     //}
1569     
1570     if (!createAggregates()) 
1571     {
1572         serr = Syms_To_Functions;
1573         return false;
1574     }
1575         
1576     // Once languages are assigned, we can build demangled names (in
1577     // the wider sense of demangling which includes stripping _'s from
1578     // fortran names -- this is why language information must be
1579     // determined before this step).
1580     
1581     // Also identifies aliases (multiple names with equal addresses)
1582 #if !defined(os_windows)
1583     linkedFile->getDependencies(deps_);
1584 #endif
1585
1586     
1587     //addSymtabVariables();
1588     linkedFile->getAllExceptions(excpBlocks);
1589     sort(excpBlocks.begin(), excpBlocks.end(), ExceptionBlockCmp);
1590
1591     vector<relocationEntry >fbt;
1592     linkedFile->get_func_binding_table(fbt);
1593     for(unsigned i=0; i<fbt.size();i++)
1594         relocation_table_.push_back(fbt[i]);
1595     return true;
1596 }
1597
1598 Symtab::Symtab(const Symtab& obj) :
1599    LookupInterface(),
1600    Serializable(),
1601    AnnotatableSparse(),
1602    member_name_(obj.member_name_),
1603    member_offset_(obj.member_offset_),
1604    parentArchive_(NULL),
1605    mf(NULL), mfForDebugInfo(NULL),
1606    imageOffset_(obj.imageOffset_), imageLen_(obj.imageLen_),
1607    dataOffset_(obj.dataOffset_), dataLen_(obj.dataLen_),
1608    is_a_out(obj.is_a_out),
1609    main_call_addr_(obj.main_call_addr_),
1610    nativeCompiler(obj.nativeCompiler),
1611    address_width_(sizeof(int)),
1612    code_ptr_(NULL), data_ptr_(NULL),
1613    entry_address_(0), base_address_(0), load_address_(0),
1614    object_type_(obj_Unknown), is_eel_(false),
1615    defaultNamespacePrefix(obj.defaultNamespacePrefix),
1616    no_of_sections(0),
1617    newSectionInsertPoint(0),
1618    no_of_symbols(obj.no_of_symbols),
1619    sorted_everyFunction(false),
1620    isTypeInfoValid_(obj.isTypeInfoValid_),
1621    nlines_(0), fdptr_(0), lines_(NULL),
1622    stabstr_(NULL), nstabs_(0), stabs_(NULL),
1623    stringpool_(NULL),
1624    hasRel_(false), hasRela_(false), hasReldyn_(false),
1625    hasReladyn_(false), hasRelplt_(false), hasRelaplt_(false),
1626    isStaticBinary_(false), isDefensiveBinary_(obj.isDefensiveBinary_),
1627    func_lookup(NULL),
1628    mod_lookup_(NULL),
1629    obj_private(NULL),
1630    _ref_cnt(1)
1631 {
1632     create_printf("%s[%d]: Creating symtab 0x%p from symtab 0x%p\n", FILE__, __LINE__, this, &obj);
1633
1634    unsigned i;
1635
1636    for (i=0;i<obj.regions_.size();i++) {
1637      regions_.push_back(new Region(*(obj.regions_[i])));
1638      regions_.back()->setSymtab(this);
1639    }
1640
1641    for (i=0;i<regions_.size();i++)
1642       regionsByEntryAddr[regions_[i]->getMemOffset()] = regions_[i];
1643
1644    // TODO FIXME: copying symbols/Functions/Variables
1645    // (and perhaps anything else initialized zero above)
1646
1647
1648    for (i=0;i<obj.indexed_modules.size();i++)
1649    {
1650       Module *m = new Module(*(obj.indexed_modules[i]));
1651       indexed_modules.push_back(m);
1652    }
1653
1654    for (i=0; i<relocation_table_.size();i++) 
1655    {
1656       relocation_table_.push_back(relocationEntry(obj.relocation_table_[i]));
1657    }
1658
1659    for (i=0;i<obj.excpBlocks.size();i++)
1660    {
1661       excpBlocks.push_back(new ExceptionBlock(*(obj.excpBlocks[i])));
1662    }
1663
1664    deps_ = obj.deps_;
1665 }
1666
1667 // Address must be in code or data range since some code may end up
1668 // in the data segment
1669 bool Symtab::isValidOffset(const Offset where) const
1670 {
1671    return isCode(where) || isData(where);
1672 }
1673
1674 /* Performs a binary search on the codeRegions_ vector, which must
1675  * be kept in sorted order
1676  */
1677 bool Symtab::isCode(const Offset where)  const
1678 {
1679 #if defined(os_vxworks)
1680     // All memory is valid in the kernel.  Kinda.
1681     //return true;
1682 #endif
1683
1684    if (!codeRegions_.size()) 
1685    {
1686       create_printf("%s[%d] No code regions in %s \n",
1687                     __FILE__, __LINE__, mf->filename().c_str());
1688       return false;
1689    }
1690
1691    // search for "where" in codeRegions_ (code regions must not overlap)
1692    int first = 0; 
1693    int last = codeRegions_.size() - 1;
1694
1695    while (last >= first) 
1696    {
1697       Region *curreg = codeRegions_[(first + last) / 2];
1698       if (where >= curreg->getMemOffset()
1699             && where < (curreg->getMemOffset()
1700                + curreg->getMemSize())) 
1701       {
1702          if (curreg->getRegionType() == Region::RT_BSS)
1703             return false;
1704          return true;
1705       }
1706       else if (where < curreg->getMemOffset()) 
1707       {
1708          last = ((first + last) / 2) - 1;
1709       }
1710       else if (where >= (curreg->getMemOffset() + curreg->getMemSize()))
1711       {
1712          first = ((first + last) / 2) + 1;
1713       }
1714       else 
1715       {  // "where" is in the range: 
1716          // [memOffset + diskSize , memOffset + memSize)
1717          // meaning that it's in an uninitialized data region 
1718          return false;
1719       }
1720    }
1721
1722    return false;
1723 }
1724
1725 /* Performs a binary search on the dataRegions_ vector, which must
1726  * be kept in sorted order */
1727 bool Symtab::isData(const Offset where)  const
1728 {
1729    if (!dataRegions_.size()) 
1730    {
1731       create_printf("%s[%d] No data regions in %s \n",
1732                     __FILE__,__LINE__,mf->filename().c_str());
1733       return false;
1734    }
1735
1736    int first = 0; 
1737    int last = dataRegions_.size() - 1;
1738
1739    while (last >= first) 
1740    {
1741       Region *curreg = dataRegions_[(first + last) / 2];
1742
1743       if (     (where >= curreg->getMemOffset())
1744             && (where < (curreg->getMemOffset() + curreg->getMemSize())))
1745       {
1746          return true;
1747       }
1748       else if (where < curreg->getMemOffset()) 
1749       {
1750          last = ((first + last) / 2) - 1;
1751       }
1752       else 
1753       {
1754          first = ((first + last) / 2) + 1;
1755       }
1756    }
1757
1758    return false;
1759 }
1760
1761 SYMTAB_EXPORT bool Symtab::getFuncBindingTable(std::vector<relocationEntry> &fbt) const
1762 {
1763    fbt = relocation_table_;
1764    return true;
1765 }
1766
1767 SYMTAB_EXPORT bool Symtab::updateFuncBindingTable(Offset stub_addr, Offset plt_addr)
1768 {
1769     int stub_idx = -1, plt_idx = -1;
1770
1771     for (unsigned i = 0; i < relocation_table_.size(); ++i) {
1772         if (stub_addr == relocation_table_[i].target_addr())
1773             stub_idx = i;
1774         if (plt_addr  == relocation_table_[i].target_addr())
1775             plt_idx = i;
1776         if (stub_idx >= 0 && plt_idx >= 0)
1777             break;
1778     }
1779     if (stub_idx >= 0 && plt_idx >= 0) {
1780         relocation_table_[stub_idx] = relocation_table_[plt_idx];
1781         relocation_table_[stub_idx].setTargetAddr(stub_addr);
1782         return true;
1783     }
1784     return false;
1785 }
1786
1787 SYMTAB_EXPORT std::vector<std::string> &Symtab::getDependencies(){
1788     return deps_;
1789 }
1790
1791 SYMTAB_EXPORT Archive *Symtab::getParentArchive() const {
1792     return parentArchive_;
1793 }
1794
1795 Symtab::~Symtab()
1796 {
1797    // Doesn't do anything yet, moved here so we don't mess with symtab.h
1798    // Only called if we fail to create a process.
1799    // Or delete the a.out...
1800
1801
1802    for (unsigned i = 0; i < regions_.size(); i++) 
1803    {
1804       delete regions_[i];
1805    }
1806
1807    regions_.clear();
1808    codeRegions_.clear();
1809    dataRegions_.clear();
1810    regionsByEntryAddr.clear();
1811
1812    std::vector<Region *> *user_regions = NULL;
1813    getAnnotation(user_regions, UserRegionsAnno);
1814
1815    if (user_regions)
1816    {
1817       for (unsigned i = 0; i < user_regions->size(); ++i) 
1818          delete (*user_regions)[i];
1819       user_regions->clear();
1820    }
1821
1822    // Symbols are copied from linkedFile, and NOT deleted
1823    everyDefinedSymbol.clear();
1824    undefDynSyms.clear();
1825
1826
1827    for (unsigned i = 0; i < everyFunction.size(); i++) 
1828    {
1829       delete everyFunction[i];
1830    }
1831
1832    everyFunction.clear();
1833    funcsByOffset.clear();
1834
1835    for (unsigned i = 0; i < everyVariable.size(); i++) 
1836    {
1837       delete everyVariable[i];
1838    }
1839
1840    everyVariable.clear();
1841    varsByOffset.clear();
1842
1843     for (auto i = indexed_modules.begin(); i != indexed_modules.end(); ++i)
1844    {
1845       delete (*i);
1846    }
1847    indexed_modules.clear();
1848
1849    for (unsigned i=0;i<excpBlocks.size();i++)
1850       delete excpBlocks[i];
1851
1852    create_printf("%s[%d]: Symtab::~Symtab removing %p from allSymtabs\n", 
1853          FILE__, __LINE__, this);
1854
1855    deps_.clear();
1856
1857    for (unsigned i = 0; i < allSymtabs.size(); i++) 
1858    {
1859       if (allSymtabs[i] == this)
1860          allSymtabs.erase(allSymtabs.begin()+i);
1861    }
1862
1863     delete func_lookup;
1864     delete mod_lookup_;
1865
1866    // Make sure to free the underlying Object as it doesn't have a factory
1867    // open method
1868    delete obj_private;
1869
1870    if (mf) MappedFile::closeMappedFile(mf);
1871
1872 }       
1873
1874 #if !defined(SERIALIZATION_DISABLED)
1875 bool Symtab::exportXML(string file)
1876 {
1877 #if defined (cap_serialization)
1878    try 
1879    {
1880            SerContext<Symtab> *scs = new SerContext<Symtab>(this, file);
1881            serialize(file, scs, ser_xml);
1882 #if 0
1883            SerContext<Symtab> *scs = new SerContext<Symtab>(this);
1884            SerializerXML *ser = new SerializerXML(scs, "XMLTranslator", file, sd_serialize, true);
1885            serialize(ser, "Symtab");
1886 #endif
1887 #if 0
1888       SerializerXML sb("XMLTranslator", file, sd_serialize, true);
1889       serialize(&sb, "Symtab");
1890 #endif
1891    } 
1892    catch (const SerializerError &err) 
1893    {
1894       return false;
1895    }
1896
1897    return false;
1898 #else
1899    return false;
1900 #endif
1901 }
1902
1903 bool Symtab::exportBin(string file)
1904 {
1905    try
1906    {
1907            SerContext<Symtab> *scs = new SerContext<Symtab>(this, file);
1908            serialize(file, scs, ser_bin);
1909            return true;
1910    }
1911
1912    catch (const SerializerError &err)
1913    {
1914       if (err.code() == SerializerError::ser_err_disabled) 
1915       {
1916          return false;
1917       }
1918
1919    }
1920
1921    return false;
1922 }
1923
1924 Symtab *Symtab::importBin(std::string file)
1925 {
1926 #if defined (cap_serialization)
1927    MappedFile *mf= MappedFile::createMappedFile(file);
1928    if (!mf) 
1929    {
1930       return NULL;
1931    }
1932
1933    Symtab *st = new Symtab(mf);
1934
1935    try
1936    {
1937            SerContext<Symtab> *scs = new SerContext<Symtab>(st, file);
1938            if (!st->deserialize(file, scs))
1939            {
1940                    delete st;
1941                    return NULL;
1942            }
1943
1944            return st;
1945    }
1946
1947    catch (const SerializerError &err)
1948    {
1949       if (err.code() == SerializerError::ser_err_disabled) 
1950       {
1951          serialize_printf("%s[%d]:  WARN:  serialization is disabled for file %s\n",
1952                FILE__, __LINE__, file.c_str());
1953          return NULL;
1954       }
1955
1956       serialize_printf("%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
1957             err.what(), err.file().c_str(), err.line());
1958    }
1959
1960
1961    serialize_printf("%s[%d]:  error doing binary deserialization\n", __FILE__, __LINE__);
1962    delete st;
1963    return NULL;
1964 #else
1965    serialize_printf("%s[%d]:  WARNING:  cannot produce %s, serialization not available\n", FILE__, __LINE__, file.c_str());
1966    return NULL;
1967 #endif
1968 }
1969
1970 #else
1971 bool Symtab::exportXML(string)
1972 {
1973    return false;
1974 }
1975
1976 bool Symtab::exportBin(string) 
1977 {
1978    return false;
1979 }
1980
1981 Symtab *Symtab::importBin(std::string)
1982 {
1983    return NULL;
1984 }
1985 #endif
1986
1987 bool Symtab::openFile(Symtab *&obj, void *mem_image, size_t size, 
1988                       std::string name, def_t def_bin)
1989 {
1990    bool err = false;
1991 #if defined(TIMED_PARSE)
1992    struct timeval starttime;
1993    gettimeofday(&starttime, NULL);
1994 #endif
1995
1996    obj = new Symtab((unsigned char *) mem_image, size, name, (def_bin == Defensive), err);
1997
1998 #if defined(TIMED_PARSE)
1999     struct timeval endtime;
2000     gettimeofday(&endtime, NULL);
2001     unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
2002     unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
2003     unsigned long difftime = lendtime - lstarttime;
2004     double dursecs = difftime/(1000 );
2005     cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
2006 #endif
2007     if(!err)
2008     {
2009        allSymtabs.push_back(obj);
2010     }
2011     else
2012     {
2013         delete obj;
2014        obj = NULL;
2015     }
2016     // returns true on success (not an error)
2017     return !err;
2018 }
2019
2020 bool Symtab::closeSymtab(Symtab *st)
2021 {
2022         bool found = false;
2023         if (!st) return false;
2024
2025     --(st->_ref_cnt);
2026
2027         std::vector<Symtab *>::reverse_iterator iter;
2028         for (iter = allSymtabs.rbegin(); iter != allSymtabs.rend() ; iter++)
2029         {
2030                 if (*iter == st)
2031                 {
2032             found = true;
2033                         if(0 == st->_ref_cnt) {
2034                             allSymtabs.erase(iter.base() -1);
2035                                 break;
2036                         }
2037                 }
2038         }
2039     if(0 == st->_ref_cnt)
2040             delete(st);
2041         return found;
2042 }
2043
2044 Symtab *Symtab::findOpenSymtab(std::string filename)
2045 {
2046    unsigned numSymtabs = allSymtabs.size();
2047         for (unsigned u=0; u<numSymtabs; u++) 
2048         {
2049                 assert(allSymtabs[u]);
2050                 if (filename == allSymtabs[u]->file() && 
2051           allSymtabs[u]->mf->canBeShared()) 
2052                 {
2053             allSymtabs[u]->_ref_cnt++;
2054                         // return it
2055                         return allSymtabs[u];
2056                 }
2057         }   
2058         return NULL;
2059 }
2060
2061 bool Symtab::openFile(Symtab *&obj, std::string filename, def_t def_binary)
2062 {
2063    bool err = false;
2064 #if defined(TIMED_PARSE)
2065    struct timeval starttime;
2066    gettimeofday(&starttime, NULL);
2067 #endif
2068
2069    // AIX: it's possible that we're reparsing a file with better information
2070    // about it. If so, yank the old one out of the allSymtabs std::vector -- replace
2071    // it, basically.
2072    if ( filename.find("/proc") == std::string::npos)
2073    {
2074            obj = findOpenSymtab(filename);
2075            if (obj)
2076            {
2077                    return true;
2078    }
2079    }
2080
2081
2082 #if defined (cap_serialization)
2083 #if 0
2084    obj = importBin(filename);
2085
2086    if (NULL == obj) 
2087    {
2088            if (deserializeEnforced<Symtab>(filename))
2089           {
2090                           serialize_printf("%s[%d]: aborting new symtab, expected deserialize failed\n",
2091                                           FILE__, __LINE__);
2092                           return false;
2093           }
2094    }
2095    else 
2096    {
2097       return true;
2098    }
2099 #endif
2100 #endif
2101
2102    obj = new Symtab(filename, (def_binary == Defensive), err);
2103
2104 #if defined(TIMED_PARSE)
2105    struct timeval endtime;
2106    gettimeofday(&endtime, NULL);
2107    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
2108    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
2109    unsigned long difftime = lendtime - lstarttime;
2110    double dursecs = difftime/(1000 );
2111    cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
2112 #endif
2113
2114    if (!err)
2115    {
2116       if (filename.find("/proc") == std::string::npos)
2117          allSymtabs.push_back(obj);
2118
2119
2120 #if defined (cap_serialization)
2121 #if 0
2122       serialize_printf("%s[%d]:  doing bin-serialize for %s\n", 
2123             FILE__, __LINE__, filename.c_str());
2124
2125       if (!obj->exportBin(filename))
2126       {
2127          serialize_printf("%s[%d]:  failed to export symtab\n", FILE__, __LINE__);
2128       }
2129       else
2130          serialize_printf("%s[%d]:  did bin-serialize for %s\n", 
2131                           FILE__, __LINE__, filename.c_str());
2132 #endif
2133 #endif
2134
2135     }
2136     else
2137     {
2138        create_printf("%s[%d]: WARNING: failed to open symtab for %s\n", 
2139              FILE__, __LINE__, filename.c_str());
2140        delete obj;
2141        obj = NULL;
2142     }
2143
2144    // returns true on success (not an error)
2145    return !err;
2146 }
2147
2148 bool Symtab::addRegion(Offset vaddr, void *data, unsigned int dataSize, std::string name, 
2149         Region::RegionType rType_, bool loadable, unsigned long memAlign, bool tls)
2150 {
2151    Region *sec;
2152    unsigned i;
2153    if (loadable)
2154    {
2155       sec = new Region(newSectionInsertPoint, name, vaddr, dataSize, vaddr, 
2156             dataSize, (char *)data, Region::RP_R, rType_, true, tls, memAlign);
2157       sec->setSymtab(this);
2158
2159       regions_.insert(regions_.begin()+newSectionInsertPoint, sec);
2160
2161       for (i = newSectionInsertPoint+1; i < regions_.size(); i++)
2162       {
2163          regions_[i]->setRegionNumber(regions_[i]->getRegionNumber() + 1);
2164       }
2165
2166       if (    (sec->getRegionType() == Region::RT_TEXT) 
2167             || (sec->getRegionType() == Region::RT_TEXTDATA))
2168       {
2169          codeRegions_.push_back(sec);
2170          std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
2171       }
2172
2173       if (    (sec->getRegionType() == Region::RT_DATA) 
2174             || (sec->getRegionType() == Region::RT_TEXTDATA))
2175       {
2176          dataRegions_.push_back(sec);
2177          std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
2178       }
2179    }
2180    else
2181    {
2182       sec = new Region(regions_.size()+1, name, vaddr, dataSize, 0, 0, 
2183             (char *)data, Region::RP_R, rType_, loadable, tls, memAlign);
2184       sec->setSymtab(this);
2185       regions_.push_back(sec);
2186    }
2187
2188    addUserRegion(sec);
2189    std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
2190    return true;
2191 }
2192
2193 bool Symtab::addUserRegion(Region *reg)
2194 {
2195    std::vector<Region *> *user_regions = NULL;
2196
2197    if (!getAnnotation(user_regions, UserRegionsAnno))
2198    {
2199       user_regions = new std::vector<Region *>();
2200       if (!addAnnotation(user_regions, UserRegionsAnno))
2201       {
2202          create_printf("%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
2203          return false;
2204       }
2205    }
2206
2207    if (!user_regions)
2208    {
2209       create_printf("%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
2210       return false;
2211    }
2212
2213    user_regions->push_back(reg);
2214
2215    return true;
2216 }
2217
2218 bool Symtab::addUserType(Type *t)
2219 {
2220    std::vector<Type *> *user_types = NULL;
2221
2222    //  need to change this to something based on AnnotationContainer
2223    //  for it to work with serialization
2224    if (!getAnnotation(user_types, UserTypesAnno))
2225    {
2226       user_types = new std::vector<Type *>();
2227       if (!addAnnotation(user_types, UserTypesAnno))
2228       {
2229          create_printf("%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
2230          return false;
2231       }
2232    }
2233    if (!user_types)
2234    {
2235       create_printf("%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
2236       return false;
2237    }
2238
2239    user_types->push_back(t);
2240
2241    return true;
2242 }
2243
2244 bool Symtab::addRegion(Region *sec)
2245 {
2246   regions_.push_back(sec);
2247   sec->setSymtab(this);
2248   std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
2249   addUserRegion(sec);
2250    return true;
2251 }
2252
2253 void Symtab::parseLineInformation()
2254 {
2255    Object *linkedFile = getObject();
2256    if (!linkedFile)
2257    {
2258      return;
2259    }
2260     linkedFile->parseFileLineInfo();
2261 }
2262
2263 SYMTAB_EXPORT bool Symtab::getAddressRanges(std::vector<AddressRange > &ranges,
2264                                             std::string lineSource, unsigned int lineNo)
2265 {
2266    unsigned int originalSize = ranges.size();
2267    parseLineInformation();
2268    
2269    /* Iteratate over the modules, looking for ranges in each. */
2270     for (auto i = indexed_modules.begin(); i != indexed_modules.end(); ++i)
2271    {
2272        StringTablePtr s = (*i)->getStrings();
2273        // Only check modules that have this filename present
2274        if(s->get<1>().find(lineSource) == s->get<1>().end()) continue;
2275        LineInformation *lineInformation = (*i)->parseLineInformation();
2276        if (lineInformation)
2277            lineInformation->getAddressRanges( lineSource.c_str(), lineNo, ranges );
2278
2279    } /* end iteration over modules */
2280
2281    if ( ranges.size() != originalSize )
2282       return true;
2283
2284    return false;
2285 }
2286
2287 SYMTAB_EXPORT bool Symtab::getSourceLines(std::vector<Statement::Ptr> &lines, Offset addressInRange)
2288 {
2289    unsigned int originalSize = lines.size();
2290     std::set<Module*> mods_for_offset;
2291     findModuleByOffset(mods_for_offset, addressInRange);
2292     for(auto i = mods_for_offset.begin();
2293             i != mods_for_offset.end();
2294             ++i)
2295     {
2296         (*i)->getSourceLines(lines, addressInRange);
2297     }
2298
2299    if ( lines.size() != originalSize )
2300       return true;
2301
2302    return false;
2303
2304 }
2305
2306 SYMTAB_EXPORT bool Symtab::getSourceLines(std::vector<LineNoTuple> &lines, Offset addressInRange)
2307 {
2308     std::vector<Statement::Ptr> tmp;
2309     getSourceLines(tmp, addressInRange);
2310     if(tmp.empty()) return false;
2311     for(auto i = tmp.begin(); i != tmp.end(); ++i)
2312     {
2313         lines.push_back(**i);
2314     }
2315     return true;
2316 }
2317
2318 SYMTAB_EXPORT bool Symtab::addLine(std::string lineSource, unsigned int lineNo,
2319       unsigned int lineOffset, Offset lowInclAddr,
2320       Offset highExclAddr)
2321 {
2322    Module *mod;
2323
2324    if (!findModuleByName(mod, lineSource))
2325    {
2326       std::string fileNm = extract_pathname_tail(lineSource);
2327
2328       if (!findModuleByName(mod, fileNm))
2329       {
2330          if (!findModuleByName(mod, mf->pathname()))
2331             return false;
2332       }    
2333    }
2334
2335    LineInformation *lineInfo = mod->getLineInformation();
2336
2337    if (!lineInfo)
2338       return false;
2339
2340    return (lineInfo->addLine(lineSource.c_str(), lineNo, lineOffset, 
2341             lowInclAddr, highExclAddr));
2342 }
2343
2344 SYMTAB_EXPORT bool Symtab::addAddressRange( Offset lowInclusiveAddr, Offset highExclusiveAddr,
2345       std::string lineSource, unsigned int lineNo,
2346       unsigned int lineOffset)
2347 {
2348    Module *mod;
2349
2350    if (!findModuleByName(mod, lineSource))
2351    {
2352       std::string fileNm = extract_pathname_tail(lineSource);
2353
2354       if (!findModuleByName(mod, fileNm))
2355          return false;
2356    }
2357
2358    LineInformation *lineInfo = mod->getLineInformation();
2359
2360    if (!lineInfo)
2361       return false;
2362
2363    return (lineInfo->addAddressRange(lowInclusiveAddr, highExclusiveAddr, 
2364             lineSource.c_str(), lineNo, lineOffset));
2365 }
2366
2367 void Symtab::setTruncateLinePaths(bool value)
2368 {
2369    getObject()->setTruncateLinePaths(value);
2370 }
2371
2372 bool Symtab::getTruncateLinePaths()
2373 {
2374    return getObject()->getTruncateLinePaths();
2375 }
2376
2377 void Symtab::parseTypes()
2378 {
2379    Object *linkedFile = getObject();
2380         if (!linkedFile)
2381         {
2382                 return;
2383         }
2384     linkedFile->parseTypeInfo();
2385
2386     for (auto i = indexed_modules.begin(); i != indexed_modules.end(); ++i)
2387    {
2388        (*i)->setModuleTypes(typeCollection::getModTypeCollection((*i)));
2389        (*i)->finalizeRanges();
2390    }
2391
2392    //  optionally we might want to clear the static data struct in typeCollection
2393    //  here....  the parsing is over, and we have added all typeCollections as
2394    //  annotations proper.
2395
2396    typeCollection::fileToTypesMap.clear();
2397
2398 }
2399
2400 bool Symtab::addType(Type *type)
2401 {
2402   bool result = addUserType(type);
2403   if (!result)
2404     return false;
2405
2406   return true;
2407 }
2408
2409 SYMTAB_EXPORT vector<Type *> *Symtab::getAllstdTypes()
2410 {
2411    return stdTypes()->getAllTypes();    
2412 }
2413
2414 SYMTAB_EXPORT vector<Type *> *Symtab::getAllbuiltInTypes()
2415 {
2416    return builtInTypes()->getAllBuiltInTypes();
2417 }
2418
2419 SYMTAB_EXPORT bool Symtab::findType(Type *&type, std::string name)
2420 {
2421    parseTypesNow();
2422
2423    if (indexed_modules.empty())
2424       return false;
2425
2426    for (auto i = indexed_modules.begin(); i != indexed_modules.end(); ++i)
2427    {
2428            typeCollection *tc = (*i)->getModuleTypes();
2429            if (!tc) continue;
2430            type = tc->findType(name);
2431            if (type) return true;
2432    }
2433
2434    if (type == NULL)
2435       return false;
2436
2437    return true; 
2438 }
2439
2440 SYMTAB_EXPORT Type *Symtab::findType(unsigned type_id)
2441 {
2442         Type *t = NULL;
2443    parseTypesNow();
2444
2445    if (indexed_modules.empty())
2446    {
2447       return NULL;
2448    }
2449
2450    for (auto i = indexed_modules.begin(); i != indexed_modules.end(); ++i)
2451    {
2452            typeCollection *tc = (*i)->getModuleTypes();
2453            if (!tc) continue;
2454            t = tc->findType(type_id);
2455            if (t)  break;
2456    }
2457
2458    if (t == NULL)
2459    {
2460            if (builtInTypes())
2461            {
2462                    t = builtInTypes()->findBuiltInType(type_id);
2463                    if (t) return t;
2464            }
2465
2466            if (stdTypes())
2467            {
2468                    t = stdTypes()->findType(type_id);
2469                    if (t) return t;
2470            }
2471
2472            return NULL;
2473    }
2474
2475    return t;    
2476 }
2477
2478 SYMTAB_EXPORT bool Symtab::findVariableType(Type *&type, std::string name)
2479 {
2480    parseTypesNow();
2481     type = NULL;
2482    for (auto i = indexed_modules.begin(); i != indexed_modules.end(); ++i)
2483    {
2484            typeCollection *tc = (*i)->getModuleTypes();
2485            if (!tc) continue;
2486            type = tc->findVariableType(name);
2487            if (type) break;
2488    }
2489
2490    if (type == NULL)
2491       return false;
2492
2493    return true; 
2494 }
2495
2496 SYMTAB_EXPORT bool Symtab::findLocalVariable(std::vector<localVar *>&vars, std::string name)
2497 {
2498    parseTypesNow();
2499    unsigned origSize = vars.size();
2500
2501    for (unsigned i = 0; i < everyFunction.size(); i++)
2502    {
2503       everyFunction[i]->findLocalVariable(vars, name);
2504    }
2505
2506    if (vars.size()>origSize)
2507       return true;
2508
2509    return false;        
2510 }
2511
2512 SYMTAB_EXPORT bool Symtab::hasRel() const
2513 {
2514    return hasRel_;
2515 }
2516
2517 SYMTAB_EXPORT bool Symtab::hasRela() const
2518 {
2519    return hasRela_;
2520 }
2521
2522 SYMTAB_EXPORT bool Symtab::hasReldyn() const
2523 {
2524    return hasReldyn_;
2525 }
2526
2527 SYMTAB_EXPORT bool Symtab::hasReladyn() const
2528 {
2529    return hasReladyn_;
2530 }
2531
2532 SYMTAB_EXPORT bool Symtab::hasRelplt() const
2533 {
2534    return hasRelplt_;
2535 }
2536
2537 SYMTAB_EXPORT bool Symtab::hasRelaplt() const
2538 {
2539    return hasRelaplt_;
2540 }
2541
2542 SYMTAB_EXPORT bool Symtab::isStaticBinary() const
2543 {
2544    return isStaticBinary_;
2545 }
2546
2547 bool Symtab::setDefaultNamespacePrefix(string &str)
2548 {
2549    defaultNamespacePrefix = str;
2550    return true;
2551 }
2552
2553 SYMTAB_EXPORT bool Symtab::emitSymbols(Object *linkedFile,std::string filename, unsigned flag)
2554 {
2555     // Start with all the defined symbols
2556   std::vector<Symbol* > allSyms;
2557     allSyms.insert(allSyms.end(), everyDefinedSymbol.begin(), everyDefinedSymbol.end());
2558
2559     // Add the undefined dynamic symbols
2560
2561     allSyms.insert(allSyms.end(), undefDynSyms.begin(), undefDynSyms.end());
2562
2563     // Write the new file
2564     return linkedFile->emitDriver(filename, allSyms, flag);
2565 }
2566
2567 SYMTAB_EXPORT bool Symtab::emit(std::string filename, unsigned flag)
2568 {
2569         Object *obj = getObject();
2570         if (!obj)
2571         {
2572                 return false;
2573         }
2574    obj->mf->setSharing(false);
2575    return emitSymbols(obj, filename, flag);
2576 }
2577
2578 SYMTAB_EXPORT void Symtab::addDynLibSubstitution(std::string oldName, std::string newName)
2579 {
2580    dynLibSubs[oldName] = newName;
2581 }
2582
2583 SYMTAB_EXPORT std::string Symtab::getDynLibSubstitution(std::string name)
2584 {
2585 #ifdef BINEDIT_DEBUG
2586    map<std::string, std::string>::iterator iter = dynLibSubs.begin();
2587
2588    printf ("substitutions for %s:\n", mf->filename().c_str());
2589
2590    while (iter != dynLibSubs.end()) 
2591    {
2592       printf("  \"%s\" => \"%s\"\n", iter->first.c_str(), iter->second.c_str());
2593       iter++;
2594    }
2595 #endif
2596
2597    map<std::string, std::string>::iterator loc = dynLibSubs.find(name);
2598
2599    if (loc == dynLibSubs.end())
2600       return name;
2601    else
2602       return loc->second;
2603 }
2604
2605 SYMTAB_EXPORT bool Symtab::getSegments(vector<Segment> &segs) const
2606 {
2607    segs = segments_;
2608
2609    if (!segments_.size()) 
2610       return false;
2611
2612    return true;
2613 }
2614
2615 SYMTAB_EXPORT bool Symtab::getMappedRegions(std::vector<Region *> &mappedRegs) const
2616 {
2617    unsigned origSize = mappedRegs.size();
2618
2619    for (unsigned i = 0; i < regions_.size(); i++)
2620    {
2621       if (regions_[i]->isLoadable())
2622          mappedRegs.push_back(regions_[i]);
2623    }
2624
2625    if (mappedRegs.size() > origSize)
2626       return true;
2627
2628    return false;
2629 }
2630
2631 SYMTAB_EXPORT bool Symtab::fixup_RegionAddr(const char* name, Offset memOffset, long memSize)
2632 {
2633     Region *sec;
2634
2635     if (!findRegion(sec, name)) {
2636         return false;
2637     }
2638
2639     vector<relocationEntry> relocs;
2640     Object *obj = getObject();
2641
2642     // Fix relocation table with correct memory address
2643     if (obj) {
2644         obj->get_func_binding_table(relocs);
2645
2646         for (unsigned i=0; i < relocs.size(); i++) {
2647             Offset value = relocs[i].rel_addr();
2648             relocs[i].setRelAddr(memOffset + value);
2649         }
2650     }
2651     relocation_table_ = relocs;
2652
2653     vector<relocationEntry> &relref = sec->getRelocations();
2654     for (unsigned i=0; i < relref.size(); i++) {
2655         Offset value = relref[i].rel_addr();
2656         relref[i].setRelAddr(memOffset + value);
2657     }
2658
2659 #if defined(_MSC_VER)
2660     regionsByEntryAddr.erase(sec->getMemOffset());
2661 #endif
2662
2663     sec->setMemOffset(memOffset);
2664     sec->setMemSize(memSize);
2665
2666 #if defined(_MSC_VER)
2667     regionsByEntryAddr[sec->getMemOffset()] = sec;
2668 #endif
2669
2670     std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
2671     std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
2672     std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
2673     return true;
2674 }
2675
2676 SYMTAB_EXPORT bool Symtab::fixup_SymbolAddr(const char* name, Offset newOffset)
2677 {
2678   indexed_symbols::index<mangled>::type& mangled_syms = everyDefinedSymbol.get<mangled>();
2679   // Find the symbol.
2680   //if (symsByMangledName.count(name) == 0) return false;
2681   if(mangled_syms.count(name) == 0) return false;
2682   if(mangled_syms.count(name) > 1)
2683     // /* DEBUG
2684     //if (symsByMangledName[name].size() != 1)
2685      create_printf("*** Found %zu symbols with name %s.  Expecting 1.\n",
2686                    mangled_syms.count(name), name); // */
2687   indexed_symbols::index<mangled>::type::iterator sym = mangled_syms.find(name);
2688   Symbol* new_sym = *sym;
2689   
2690   // Update symbol.
2691   new_sym->setOffset(newOffset);
2692   indexed_symbols::index<offset>::type& syms_by_offset = everyDefinedSymbol.get<offset>();
2693   syms_by_offset.replace(everyDefinedSymbol.project<offset>(sym), new_sym);
2694   
2695     // Update hashes.
2696   /*   if (symsByOffset.count(oldOffset)) {
2697         std::vector<Symbol *>::iterator iter = symsByOffset[oldOffset].begin();
2698         while (iter != symsByOffset[oldOffset].end()) {
2699             if (*iter == sym) {
2700                 symsByOffset[oldOffset].erase(iter);
2701                 iter = symsByOffset[oldOffset].begin();
2702
2703             } else iter++;
2704         }
2705     }
2706     if (!findSymbolByOffset(newOffset))
2707         symsByOffset[newOffset].push_back(sym);
2708   */
2709     // Update aggregates.
2710     if (!doNotAggregate(new_sym)) {
2711       addSymbolToAggregates(new_sym);
2712     }
2713
2714     return true;
2715 }
2716
2717 SYMTAB_EXPORT bool Symtab::updateRegion(const char* name, void *buffer, unsigned size)
2718 {
2719    Region *sec;
2720
2721    if (!findRegion(sec, name))
2722       return false;
2723
2724    sec->setPtrToRawData(buffer, size);
2725
2726    return true;
2727 }
2728
2729 SYMTAB_EXPORT bool Symtab::updateCode(void *buffer, unsigned size)
2730 {
2731   return updateRegion(".text", buffer, size);
2732 }
2733
2734 SYMTAB_EXPORT bool Symtab::updateData(void *buffer, unsigned size)
2735 {
2736   return updateRegion(".data", buffer, size);
2737 }
2738
2739 SYMTAB_EXPORT Offset Symtab::getFreeOffset(unsigned size) 
2740 {
2741    // Look through sections until we find a gap with
2742    // sufficient space.
2743    Offset highWaterMark = 0;
2744    Offset secoffset = 0;
2745    Offset prevSecoffset = 0;
2746    Object *linkedFile = getObject();
2747    if (!linkedFile)
2748      {
2749        return 0;
2750      }
2751    
2752    for (unsigned i = 0; i < regions_.size(); i++) 
2753    {
2754       Offset end = regions_[i]->getMemOffset() + regions_[i]->getMemSize();
2755       if (regions_[i]->getMemOffset() == 0) 
2756          continue;
2757
2758       prevSecoffset = secoffset;
2759
2760       unsigned region_offset = (unsigned)((char *)(regions_[i]->getPtrToRawData())
2761                                           - linkedFile->mem_image());
2762
2763       if (region_offset < (unsigned)prevSecoffset)
2764       {
2765          secoffset += regions_[i]->getMemSize();
2766       }
2767       else 
2768       {
2769          secoffset = (char *)(regions_[i]->getPtrToRawData()) - linkedFile->mem_image();
2770          secoffset += regions_[i]->getMemSize();
2771       }
2772
2773       if (end > highWaterMark) 
2774       {
2775          newSectionInsertPoint = i+1;
2776          highWaterMark = end;
2777       }
2778
2779       if (     (i < (regions_.size()-2)) 
2780                && ((end + size) < regions_[i+1]->getMemOffset())) 
2781       {
2782          newSectionInsertPoint = i+1;
2783          highWaterMark = end;
2784          break;
2785       }
2786    }
2787
2788    //   return highWaterMark;
2789 #if defined (os_windows)
2790         Object *obj = getObject();
2791         if (!obj)
2792         {
2793                 return 0;
2794         }
2795         unsigned pgSize = obj->getSecAlign();
2796         //printf("pgSize:0x%x\n", pgSize);
2797         Offset newaddr = highWaterMark  - (highWaterMark & (pgSize-1));
2798         while(newaddr < highWaterMark)
2799       newaddr += pgSize;
2800         //printf("getfreeoffset:%lu\n", newaddr);
2801         return newaddr;
2802
2803 #else
2804         unsigned pgSize = P_getpagesize();
2805
2806 #if defined(os_linux)
2807         // Bluegene compute nodes have a 1MB alignment restructions on PT_LOAD section
2808         Object *obj = getObject();
2809         if (!obj)
2810         {
2811                 return 0;
2812         }
2813         bool isBlueGeneQ = obj->isBlueGeneQ();
2814         bool isBlueGeneP = obj->isBlueGeneP();
2815         bool hasNoteSection = obj->hasNoteSection();
2816         bool isStaticBinary = obj->isStaticBinary();
2817         /* In BlueGeneQ static binary, we extend the existing LOAD section to add Dyninst code and data
2818                 In BlueGeneQ dynamic binary, we add a new LOAD section
2819            In BlueGeneP, we replace NOTE section with new LOAD section, else we extend existing LOAD section
2820                 If we add a new LOAD section in BlueGene, it needs to be aligned to 1MB
2821         */
2822         if ((isBlueGeneQ && !isStaticBinary) || (isBlueGeneP && hasNoteSection)) {
2823                 pgSize = 0x100000; 
2824         } else if( isBlueGeneQ && isStaticBinary ) {
2825         /* UGLY:: The maximum offset from TOC pointer is 0x7fff (15 bits + 1 sign bit).
2826            For static binaries, the TOC pointer must be able to reach the new load segment.
2827                 If we align by page size (1MB), the TOC pointer will not be able to reach the new segment.
2828                 Since we do not create a new PT_LOAD segment, but rather extend the existing PT_LOAD segment,
2829                 we do not need to align by page size. 
2830                 Note1: 64 bytes is just random number I choose. 
2831                 Note2: We need to do this only for memory offset and not disk offset as TOC pointer
2832                 uses only memory offset */
2833                 pgSize = 64;
2834         }       
2835
2836                 
2837 #endif  
2838         Offset newaddr = highWaterMark  - (highWaterMark & (pgSize-1));
2839         if(newaddr < highWaterMark)
2840                 newaddr += pgSize;
2841    return newaddr;
2842 #endif  
2843 }
2844
2845 SYMTAB_EXPORT ObjectType Symtab::getObjectType() const 
2846 {
2847    return object_type_;
2848 }
2849
2850 SYMTAB_EXPORT Dyninst::Architecture Symtab::getArchitecture() const
2851 {
2852    return getObject()->getArch();
2853 }
2854
2855 SYMTAB_EXPORT char *Symtab::mem_image() const 
2856 {
2857    return (char *)mf->base_addr();
2858 }
2859
2860 SYMTAB_EXPORT std::string Symtab::file() const 
2861 {
2862    assert(mf);
2863    return mf->pathname();
2864 }
2865
2866 SYMTAB_EXPORT std::string Symtab::name() const 
2867 {
2868   return mf->filename();
2869 }
2870
2871 SYMTAB_EXPORT std::string Symtab::memberName() const 
2872 {
2873     return member_name_;
2874 }
2875
2876 SYMTAB_EXPORT unsigned Symtab::getNumberOfRegions() const 
2877 {
2878    return no_of_sections; 
2879 }
2880
2881 SYMTAB_EXPORT unsigned Symtab::getNumberOfSymbols() const 
2882 {
2883    return no_of_symbols; 
2884 }
2885
2886
2887 SYMTAB_EXPORT LookupInterface::LookupInterface() 
2888 {
2889 }
2890
2891 SYMTAB_EXPORT LookupInterface::~LookupInterface()
2892 {
2893 }
2894
2895
2896 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset tStart, 
2897       unsigned tSize, 
2898       Offset cStart) 
2899 : tryStart_(tStart), trySize_(tSize), catchStart_(cStart), hasTry_(true),
2900   tryStart_ptr(0), tryEnd_ptr(0), catchStart_ptr(0), fdeStart_ptr(0), fdeEnd_ptr(0)
2901 {
2902 }
2903
2904    SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset cStart) 
2905 : tryStart_(0), trySize_(0), catchStart_(cStart), hasTry_(false),
2906   tryStart_ptr(0), tryEnd_ptr(0), catchStart_ptr(0), fdeStart_ptr(0), fdeEnd_ptr(0)
2907 {
2908 }
2909
2910 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(const ExceptionBlock &eb) :
2911    Serializable(),
2912    tryStart_(eb.tryStart_), trySize_(eb.trySize_), 
2913    catchStart_(eb.catchStart_), hasTry_(eb.hasTry_),
2914    tryStart_ptr(eb.tryStart_ptr),
2915    tryEnd_ptr(eb.tryEnd_ptr),
2916    catchStart_ptr(eb.catchStart_ptr),
2917    fdeStart_ptr(eb.fdeStart_ptr),
2918    fdeEnd_ptr(eb.fdeEnd_ptr)
2919 {
2920 }
2921 SYMTAB_EXPORT bool ExceptionBlock::hasTry() const
2922
2923    return hasTry_; 
2924 }
2925
2926 SYMTAB_EXPORT Offset ExceptionBlock::tryStart() const
2927
2928    return tryStart_; 
2929 }
2930
2931 SYMTAB_EXPORT Offset ExceptionBlock::tryEnd() const
2932
2933    return tryStart_ + trySize_; 
2934 }
2935
2936 SYMTAB_EXPORT Offset ExceptionBlock::trySize() const
2937 {
2938    return trySize_; 
2939 }
2940
2941 SYMTAB_EXPORT bool ExceptionBlock::contains(Offset a) const
2942
2943    return (a >= tryStart_ && a < tryStart_ + trySize_); 
2944 }
2945
2946 #if !defined(SERIALIZATION_DISABLED)
2947 Serializable * ExceptionBlock::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
2948 {
2949         ifxml_start_element(sb, tag);
2950         gtranslate(sb, tryStart_, "tryStart");
2951         gtranslate(sb, trySize_, "trySize");
2952         gtranslate(sb, catchStart_, "catchStart");
2953         gtranslate(sb, hasTry_, "hasTry");
2954         ifxml_end_element(sb, tag);
2955         return NULL;
2956 }
2957 #else
2958 Serializable * ExceptionBlock::serialize_impl(SerializerBase *, const char *) THROW_SPEC (SerializerError)
2959 {
2960    return NULL;
2961 }
2962 #endif
2963
2964 SYMTAB_EXPORT relocationEntry::relocationEntry() :
2965    target_addr_(0), 
2966    rel_addr_(0), 
2967    addend_(0), 
2968    rtype_(Region::RT_REL), 
2969    name_(""), 
2970    dynref_(NULL), 
2971    relType_(0),
2972    rel_struct_addr_(0)
2973 {
2974 }   
2975
2976 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, std::string n, 
2977       Symbol *dynref, unsigned long relType) :
2978    target_addr_(ta), 
2979    rel_addr_(ra), 
2980    addend_(0), 
2981    rtype_(Region::RT_REL), 
2982    name_(n), 
2983    dynref_(dynref), 
2984    relType_(relType),
2985    rel_struct_addr_(0)
2986 {
2987 }
2988
2989 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, Offset add, 
2990       std::string n, Symbol *dynref, unsigned long relType) :
2991    target_addr_(ta), 
2992    rel_addr_(ra), 
2993    addend_(add), 
2994    rtype_(Region::RT_REL), 
2995    name_(n), 
2996    dynref_(dynref), 
2997    relType_(relType),
2998    rel_struct_addr_(0)
2999 {
3000 }
3001
3002 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ra, std::string n, 
3003       Symbol *dynref, unsigned long relType, Region::RegionType rtype) :
3004    target_addr_(0), 
3005    rel_addr_(ra), 
3006    addend_(0), 
3007    rtype_(rtype), 
3008    name_(n), 
3009    dynref_(dynref), 
3010    relType_(relType),
3011    rel_struct_addr_(0)
3012 {
3013 }
3014
3015 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, Offset add,
3016         std::string n, Symbol *dynref, unsigned long relType,
3017         Region::RegionType rtype) :
3018     target_addr_(ta),
3019     rel_addr_(ra),
3020     addend_(add),
3021     rtype_(rtype),
3022     name_(n),
3023     dynref_(dynref),
3024     relType_(relType),
3025     rel_struct_addr_(0)
3026 {
3027 }
3028
3029 SYMTAB_EXPORT Offset relocationEntry::target_addr() const 
3030 {
3031     return target_addr_;
3032 }
3033
3034 SYMTAB_EXPORT void relocationEntry::setTargetAddr(const Offset off)
3035 {
3036     target_addr_ = off;
3037 }
3038
3039 SYMTAB_EXPORT Offset relocationEntry::rel_addr() const 
3040 {
3041     return rel_addr_;
3042 }
3043
3044 SYMTAB_EXPORT void relocationEntry::setRelAddr(const Offset value)
3045 {
3046     rel_addr_ = value;
3047 }
3048
3049 SYMTAB_EXPORT const string &relocationEntry::name() const 
3050 {
3051     return name_;
3052 }
3053
3054 SYMTAB_EXPORT Symbol *relocationEntry::getDynSym() const 
3055 {
3056     return dynref_;
3057 }
3058
3059 SYMTAB_EXPORT bool relocationEntry::addDynSym(Symbol *dynref) 
3060 {
3061     dynref_ = dynref;
3062     return true;
3063 }
3064
3065 SYMTAB_EXPORT Region::RegionType relocationEntry::regionType() const
3066 {
3067         return rtype_;
3068 }
3069
3070 SYMTAB_EXPORT unsigned long relocationEntry::getRelType() const 
3071 {
3072     return relType_;
3073 }
3074
3075 SYMTAB_EXPORT Offset relocationEntry::addend() const
3076 {
3077         return addend_;
3078 }
3079
3080 SYMTAB_EXPORT void relocationEntry::setAddend(const Offset value)
3081 {
3082         addend_ = value;
3083 }
3084
3085 SYMTAB_EXPORT void relocationEntry::setRegionType(const Region::RegionType value)
3086 {
3087         rtype_ = value;
3088 }
3089
3090 SYMTAB_EXPORT void relocationEntry::setName(const std::string &newName) {
3091     name_ = newName;
3092 }
3093
3094 bool relocationEntry::operator==(const relocationEntry &r) const
3095 {
3096         if (target_addr_ != r.target_addr_) return false;
3097         if (rel_addr_ != r.rel_addr_) return false;
3098         if (addend_ != r.addend_) return false;
3099         if (rtype_ != r.rtype_) return false;
3100         if (name_ != r.name_) return false;
3101         if (relType_ != r.relType_) return false;
3102         if (dynref_ && !r.dynref_) return false;
3103         if (!dynref_ && r.dynref_) return false;
3104         if (dynref_)
3105         {
3106                 if (dynref_->getMangledName() != r.dynref_->getMangledName()) return false;
3107                 if (dynref_->getOffset() != r.dynref_->getOffset()) return false;
3108         }
3109
3110         return true;
3111 }
3112
3113 #if !defined(SERIALIZATION_DISABLED)
3114 Serializable *relocationEntry::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
3115 {
3116         //  on deserialize need to rebuild symtab::undefDynSyms before deserializing relocations
3117
3118         std::string symname = dynref_ ? dynref_->getName() : std::string("");
3119         Offset symoff = dynref_ ? dynref_->getOffset() : (Offset) -1;
3120
3121       ifxml_start_element(sb, tag);
3122       gtranslate(sb, target_addr_, "targetAddress");
3123       gtranslate(sb, rel_addr_, "relocationAddress");
3124       gtranslate(sb, addend_, "Addend");
3125       gtranslate(sb, name_, "relocationName");
3126       gtranslate(sb,  rtype_, Region::regionType2Str, "regionType");
3127       gtranslate(sb, relType_, "relocationType");
3128       gtranslate(sb, symname, "SymbolName");
3129       gtranslate(sb, symoff, "SymbolOffset");
3130       ifxml_end_element(sb, tag);
3131
3132           if (sb->isInput())
3133           {
3134                   dynref_ = NULL;
3135                   if (symname != std::string(""))
3136                   {
3137                           SerContextBase *scb = sb->getContext();
3138                           if (!scb)
3139                           {
3140                                   SER_ERR("FIXME");
3141                           }
3142
3143                           SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
3144
3145                           if (!scs)
3146                           {
3147                                   SER_ERR("FIXME");
3148                           }
3149
3150                           Symtab *st = scs->getScope();
3151
3152                           if (!st)
3153                           {
3154                                   SER_ERR("FIXME");
3155                           }
3156
3157                           std::vector<Symbol *> *syms = st->findSymbolByOffset(symoff);
3158                           if (!syms || !syms->size())
3159                           {
3160                                   serialize_printf("%s[%d]:  cannot find symbol by offset %p\n", 
3161                                                   FILE__, __LINE__, (void *)symoff);
3162                                   return NULL;
3163                           }
3164
3165                           //  Might want to try to select the "best" symbol here if there is
3166                           //  more than one.  Or Maybe just returning the first is sufficient.
3167
3168                           dynref_ = (*syms)[0];
3169                   }
3170           }
3171           return NULL;
3172 }
3173 #else
3174 Serializable *relocationEntry::serialize_impl(SerializerBase *, const char *) THROW_SPEC (SerializerError)
3175 {
3176    return NULL;
3177 }
3178 #endif
3179
3180 ostream & Dyninst::SymtabAPI::operator<< (ostream &os, const relocationEntry &r) 
3181 {
3182     if( r.getDynSym() != NULL ) {
3183         os << "Name: " << setw(20) << ( "'" + r.getDynSym()->getMangledName() + "'" );
3184     }else{
3185         os << "Name: " << setw(20) << r.name();
3186     }
3187     os << " Offset: " << std::hex << std::setfill('0') << setw(8) << r.rel_addr() 
3188        << std::dec << std::setfill(' ')
3189        << " Offset: " << std::hex << std::setfill('0') << setw(8) << r.target_addr() 
3190        << std::dec << std::setfill(' ')
3191        << " Addend: " << r.addend()
3192        << " Region: " << Region::regionType2Str(r.regionType())
3193        << " Type: " << setw(15) << relocationEntry::relType2Str(r.getRelType())
3194        << "(" << r.getRelType() << ")";
3195     if( r.getDynSym() != NULL ) {
3196         os << " Symbol Offset: " << std::hex << std::setfill('0') << setw(8) << r.getDynSym()->getOffset();
3197         os << std::setfill(' ');
3198         if( r.getDynSym()->isCommonStorage() ) {
3199             os << " COM";
3200         }else if( r.getDynSym()->getRegion() == NULL ) {
3201             os << " UND";
3202         }
3203     }
3204     return os;
3205 }
3206
3207 const char *Symbol::symbolType2Str(SymbolType t) 
3208 {
3209    switch (t) 
3210    {
3211       CASE_RETURN_STR(ST_UNKNOWN);
3212       CASE_RETURN_STR(ST_FUNCTION);
3213       CASE_RETURN_STR(ST_OBJECT);
3214       CASE_RETURN_STR(ST_MODULE);
3215       CASE_RETURN_STR(ST_SECTION);
3216       CASE_RETURN_STR(ST_TLS);
3217       CASE_RETURN_STR(ST_DELETED);
3218       CASE_RETURN_STR(ST_NOTYPE);
3219       CASE_RETURN_STR(ST_INDIRECT);
3220    };
3221
3222    return "invalid symbol type";
3223 }
3224
3225 const char *Symbol::symbolLinkage2Str(SymbolLinkage t) 
3226 {
3227    switch (t) 
3228    {
3229       CASE_RETURN_STR(SL_UNKNOWN);
3230       CASE_RETURN_STR(SL_GLOBAL);
3231       CASE_RETURN_STR(SL_LOCAL);
3232       CASE_RETURN_STR(SL_WEAK);
3233       CASE_RETURN_STR(SL_UNIQUE);
3234    };
3235
3236    return "invalid symbol linkage";
3237 }
3238
3239 const char *Symbol::symbolTag2Str(SymbolTag t) 
3240 {
3241    switch (t) 
3242    {
3243       CASE_RETURN_STR(TAG_UNKNOWN);
3244       CASE_RETURN_STR(TAG_USER);
3245       CASE_RETURN_STR(TAG_LIBRARY);
3246       CASE_RETURN_STR(TAG_INTERNAL);
3247    };
3248
3249    return "invalid symbol tag";
3250 }
3251
3252 const char *Symbol::symbolVisibility2Str(SymbolVisibility t) 
3253 {
3254    switch(t) {
3255       CASE_RETURN_STR(SV_UNKNOWN);
3256       CASE_RETURN_STR(SV_DEFAULT);
3257       CASE_RETURN_STR(SV_INTERNAL);
3258       CASE_RETURN_STR(SV_HIDDEN);
3259       CASE_RETURN_STR(SV_PROTECTED);
3260    }
3261    return "invalid symbol visibility";
3262 }
3263
3264 bool Symtab::hasStackwalkDebugInfo()
3265 {
3266
3267         Object *obj = getObject();
3268         if (!obj)
3269         {
3270                 return false;
3271         }
3272    return obj->hasFrameDebugInfo();
3273 }
3274
3275 bool Symtab::getRegValueAtFrame(Address pc, 
3276                                 Dyninst::MachRegister reg, 
3277                                 Dyninst::MachRegisterVal &reg_result,
3278                                 MemRegReader *reader)
3279 {
3280         Object *obj = getObject();
3281         if (!obj)
3282         {
3283                 return false;
3284         }
3285    return obj->getRegValueAtFrame(pc, reg, reg_result, reader);
3286 }
3287
3288 Object *Symtab::getObject()
3289 {
3290    if (obj_private)
3291       return obj_private;
3292
3293    //TODO: This likely triggered because we serialized in an object
3294    // from cache, but now the user is requesting more information from
3295    // the on disk object.  We should create a new 'Object' from data
3296    // (likely a file path) serialized in.
3297    
3298    return NULL;
3299    //obj_private = new Object();
3300    //return obj_private;
3301 }
3302
3303 const Object *Symtab::getObject() const
3304 {
3305     return obj_private;
3306 }
3307
3308 void Symtab::parseTypesNow()
3309 {
3310    if (isTypeInfoValid_)
3311       return;
3312    isTypeInfoValid_ = true;
3313
3314    parseTypes();
3315 }
3316
3317 #if defined (cap_serialization)
3318 //  Not sure this is strictly necessary, problems only seem to exist with Module 
3319 // annotations when the file was split off, so there's probably something else that
3320 //  can be done to instantiate the relevant functions.
3321
3322 bool dummy_for_ser_instance(std::string file, SerializerBase *sb)
3323 {
3324    if (file == std::string("no_such_file")) 
3325    {
3326       if (!sb) 
3327       {
3328          return false;
3329       }
3330    }
3331    return true;
3332 }
3333
3334 #endif
3335
3336
3337 #if !defined(SERIALIZATION_DISABLED)
3338 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_serializer(Symtab *t, std::string file)
3339 {
3340         SerializerBin *ser;
3341         SerContext<Symtab> *scs = new SerContext<Symtab>(t, file);
3342         ser = new SerializerBin(scs, "SerializerBin", file, sd_serialize, false);
3343         return ser;
3344 }
3345
3346 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_deserializer(Symtab *t, std::string file)
3347 {
3348         SerializerBin *ser;
3349         SerContext<Symtab> *scs = new SerContext<Symtab>(t, file);
3350         ser = new SerializerBin(scs, "DeserializerBin", file, sd_deserialize, false);
3351         return ser;
3352 }
3353
3354 SYMTAB_EXPORT void nonpublic_free_bin_symtab_serializer(SerializerBase *sb)
3355 {
3356         SerializerBin *sbin = dynamic_cast<SerializerBin *>(sb);
3357         if (sbin)
3358         {
3359                 delete(sbin);
3360         }
3361
3362 }
3363 #endif
3364
3365 SYMTAB_EXPORT Offset Symtab::getElfDynamicOffset()
3366 {
3367 #if defined(os_linux) || defined(os_freebsd)
3368         Object *obj = getObject();
3369         if (!obj)
3370         {
3371                 return 0;
3372         }
3373    return obj->getDynamicAddr();
3374 #else
3375    return 0;
3376 #endif
3377 }
3378
3379 SYMTAB_EXPORT bool Symtab::removeLibraryDependency(std::string lib)
3380 {
3381 #if defined(os_windows)
3382    return false;
3383 #else
3384    Object *obj = getObject();
3385         if (!obj) {
3386                 return false;
3387         }
3388    return obj->removePrereqLibrary(lib);
3389 #endif
3390 }
3391    
3392 SYMTAB_EXPORT bool Symtab::addLibraryPrereq(std::string name)
3393 {
3394    Object *obj = getObject();
3395         if (!obj)
3396         {
3397                 return false;
3398         }
3399    // remove forward slashes and back slashes
3400    size_t size = name.find_last_of("/");
3401    size_t lastBS = name.find_last_of("\\");
3402    if (lastBS > size) {
3403       size = lastBS;
3404    }
3405
3406    string filename = name.substr(size+1);
3407
3408 #if ! defined(os_windows) 
3409    obj->insertPrereqLibrary(filename);
3410 #else 
3411    // must add a symbol for an exported function belonging to the library 
3412    // to get the Windows loader to load the library
3413
3414    Symtab *symtab = Symtab::findOpenSymtab(name);
3415    if (!symtab) {
3416       if (!Symtab::openFile(symtab, name)) {
3417          return false;
3418       }
3419    }
3420    
3421    // find an exported function
3422    vector<Symbol*> funcs;
3423    symtab->getAllSymbolsByType(funcs, Symbol::ST_FUNCTION);
3424    vector<Symbol*>::iterator fit = funcs.begin(); 
3425    for (; fit != funcs.end() && !(*fit)->isInDynSymtab(); fit++);
3426    if (fit == funcs.end()) {
3427       return false;
3428    }
3429    
3430    string funcName = string((*fit)->getPrettyName());
3431    if (funcName.empty()) {
3432       funcName = string((*fit)->getMangledName());
3433       if (funcName.empty()) {
3434          assert(0);
3435          return false;
3436       }
3437    }
3438    symtab->getObject()->addReference((*fit)->getOffset(), 
3439                                      name, 
3440                                      funcName);
3441    obj->addReference((*fit)->getOffset(), filename, funcName);
3442 #endif
3443    return true;
3444 }
3445
3446 SYMTAB_EXPORT bool Symtab::addSysVDynamic(long name, long value)
3447 {
3448 #if defined(os_linux) || defined(os_freebsd)
3449         Object *obj = getObject();
3450         if (!obj)
3451         {
3452                 return false;
3453         }
3454   obj->insertDynamicEntry(name, value);
3455    return true;
3456 #else
3457    return false;
3458 #endif
3459 }
3460
3461 SYMTAB_EXPORT bool Symtab::addExternalSymbolReference(Symbol *externalSym, Region *localRegion,
3462         relocationEntry localRel)
3463 {
3464     // Adjust this to the correct value
3465     localRel.setRegionType(getObject()->getRelType());
3466
3467     // Create placeholder Symbol for external Symbol reference
3468     // Bernat, 7SEP2010 - according to Matt, these symbols should have
3469     // type "undefined", which means a region of NULL. Changing
3470     // from "localRegion" to NULL. 
3471     Symbol *symRef = new Symbol(externalSym->getMangledName(),
3472                                 externalSym->getType(),
3473                                 Symbol::SL_GLOBAL,
3474                                 Symbol::SV_DEFAULT,
3475                                 (Address)0,
3476                                 getDefaultModule(),
3477                                 NULL, // localRegion,
3478                                 externalSym->getSize(),
3479                                 true,
3480                                 false);
3481
3482    if( !addSymbol(symRef, externalSym) ) return false;
3483
3484    localRegion->addRelocationEntry(localRel);
3485
3486    // Make sure the Symtab holding the external symbol gets linked
3487    // with this Symtab
3488    explicitSymtabRefs_.insert(externalSym->getSymtab());
3489
3490    return true;
3491 }
3492
3493 // on windows we can't specify the trap table's location by adding a dynamic
3494 // symbol as we don on windows
3495 SYMTAB_EXPORT bool Symtab::addTrapHeader_win(Address ptr)
3496 {
3497 #if defined(os_windows)
3498    getObject()->setTrapHeader(ptr);
3499    return true;
3500 #else
3501    (void) ptr; //keep compiler happy
3502    assert(0);
3503    return false;
3504 #endif
3505 }
3506
3507 bool Symtab::getExplicitSymtabRefs(std::set<Symtab *> &refs) {
3508     refs = explicitSymtabRefs_;
3509     return (refs.size() != 0);
3510 }
3511
3512 SYMTAB_EXPORT bool Symtab::addLinkingResource(Archive *library) {
3513     linkingResources_.push_back(library);
3514
3515     return true;
3516 }
3517
3518 SYMTAB_EXPORT bool Symtab::getLinkingResources(std::vector<Archive *> &libs) {
3519     libs = linkingResources_;
3520     return (linkingResources_.size() != 0);
3521 }
3522
3523 SYMTAB_EXPORT Address Symtab::getLoadAddress()
3524 {
3525 #if defined(os_linux) || defined(os_freebsd)
3526    return getObject()->getLoadAddress();
3527 #else
3528    return 0x0;
3529 #endif
3530 }
3531
3532 SYMTAB_EXPORT bool Symtab::isDefensiveBinary() const
3533 {
3534     return isDefensiveBinary_;
3535 }
3536
3537 SYMTAB_EXPORT bool Symtab::canBeShared()
3538 {
3539    return mf->canBeShared();
3540 }
3541
3542 SYMTAB_EXPORT Offset Symtab::getInitOffset()
3543 {
3544 #if defined(os_linux) || defined(os_freebsd)
3545    return getObject()->getInitAddr();
3546 #else
3547    return 0x0;
3548 #endif
3549
3550 }
3551
3552 SYMTAB_EXPORT Offset Symtab::getFiniOffset()
3553 {
3554 #if defined(os_linux) || defined(os_freebsd)
3555    return getObject()->getFiniAddr();
3556 #else
3557    return 0x0;
3558 #endif
3559
3560 }
3561
3562 void Symtab::getSegmentsSymReader(std::vector<SymSegment> &segs) {
3563 #if !defined(os_windows)
3564    obj_private->getSegmentsSymReader(segs);
3565 #endif
3566 }
3567
3568 void Symtab::rebase(Offset loadOff)
3569 {
3570         getObject()->rebase(loadOff);
3571         load_address_ = loadOff;
3572 }
3573
3574 ModRangeLookup *Symtab::mod_lookup() {
3575     if(!mod_lookup_) mod_lookup_ = new ModRangeLookup;
3576     return mod_lookup_;
3577
3578 }