Symtab.C

Go to the documentation of this file.
00001 /*
00002  * See the dyninst/COPYRIGHT file for copyright information.
00003  * 
00004  * We provide the Paradyn Tools (below described as "Paradyn")
00005  * on an AS IS basis, and do not warrant its validity or performance.
00006  * We reserve the right to update, modify, or discontinue this
00007  * software at any time.  We shall have no obligation to supply such
00008  * updates or modifications or any other form of support to you.
00009  * 
00010  * By your use of Paradyn, you understand and agree that we (or any
00011  * other person or entity with proprietary rights in Paradyn) are
00012  * under no obligation to provide either maintenance services,
00013  * update services, notices of latent defects, or correction of
00014  * defects for Paradyn.
00015  * 
00016  * This library is free software; you can redistribute it and/or
00017  * modify it under the terms of the GNU Lesser General Public
00018  * License as published by the Free Software Foundation; either
00019  * version 2.1 of the License, or (at your option) any later version.
00020  * 
00021  * This library is distributed in the hope that it will be useful,
00022  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00023  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00024  * Lesser General Public License for more details.
00025  * 
00026  * You should have received a copy of the GNU Lesser General Public
00027  * License along with this library; if not, write to the Free Software
00028  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00029  */
00030 
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <assert.h>
00034 #include <string.h>
00035 #include <algorithm>
00036 #include <iostream>
00037 #include <iomanip>
00038 #include <sstream>
00039 
00040 #include "common/h/Timer.h"
00041 #include "common/h/debugOstream.h"
00042 #include "common/h/serialize.h"
00043 #include "common/h/pathName.h"
00044 
00045 #include "Serialization.h"
00046 #include "Symtab.h"
00047 #include "Module.h"
00048 #include "Collections.h"
00049 #include "Function.h"
00050 #include "Variable.h"
00051 
00052 #include "annotations.h"
00053 
00054 #include "debug.h"
00055 
00056 #include "symtabAPI/src/Object.h"
00057 
00058 #if !defined(os_windows)
00059 #include <dlfcn.h>
00060 #else
00061 #include <windows.h>
00062 #endif
00063 
00064 #include <iomanip>
00065 #include <stdarg.h>
00066 
00067 using namespace Dyninst;
00068 using namespace Dyninst::SymtabAPI;
00069 using namespace std;
00070 
00071 static std::string errMsg;
00072 extern bool parseCompilerType(Object *);
00073 
00074 static const int Symtab_major_version = 8;
00075 static const int Symtab_minor_version = 1;
00076 static const int Symtab_maintenance_version = 2;
00077 
00078 
00079 void Symtab::version(int& major, int& minor, int& maintenance)
00080 {
00081     major = Symtab_major_version;
00082     minor = Symtab_minor_version;
00083     maintenance = Symtab_maintenance_version;
00084 }
00085 
00086 
00087 void symtab_log_perror(const char *msg)
00088 {
00089    errMsg = std::string(msg);
00090 };
00091 
00092 
00093 SymtabError serr;
00094 
00095 std::vector<Symtab *> Symtab::allSymtabs;
00096 
00097  
00098 SymtabError Symtab::getLastSymtabError()
00099 {
00100     return serr;
00101 }
00102 
00103 void setSymtabError(SymtabError new_err)
00104 {
00105    serr = new_err;
00106 }
00107 
00108 std::string Symtab::printError(SymtabError serr)
00109 {
00110     switch (serr)
00111     {
00112        case Obj_Parsing:
00113            return "Failed to parse the Object"+errMsg;
00114        case Syms_To_Functions:
00115            return "Failed to convert Symbols to Functions";
00116        case No_Such_Function:
00117            return "Function does not exist";
00118        case No_Such_Variable:
00119            return "Variable does not exist";
00120        case No_Such_Module:
00121           return "Module does not exist";
00122        case No_Such_Region:
00123            return "Region does not exist";
00124        case No_Such_Symbol:
00125            return "Symbol does not exist";
00126        case Not_A_File:
00127            return "Not a File. Call openArchive()";
00128        case Not_An_Archive:
00129            return "Not an Archive. Call openFile()";
00130        case Export_Error:
00131            return "Error Constructing XML"+errMsg;
00132        case Emit_Error:
00133            return "Error rewriting binary: " + errMsg;
00134        case Invalid_Flags:
00135           return "Flags passed are invalid.";
00136        case No_Error:
00137           return "No previous Error.";
00138        default:
00139           return "Unknown Error";
00140     }       
00141 }
00142 
00143 boost::shared_ptr<Type> Symtab::type_Error()
00144 {
00145     static boost::shared_ptr<Type> store = 
00146        boost::shared_ptr<Type>(new Type(std::string("<error>"), 0, dataUnknownType));
00147     return store;
00148 }
00149 boost::shared_ptr<Type> Symtab::type_Untyped()
00150 {
00151     static boost::shared_ptr<Type> store =
00152        boost::shared_ptr<Type>(new Type(std::string("<no type>"), 0, dataUnknownType));
00153     return store;
00154 }
00155 
00156 boost::shared_ptr<builtInTypeCollection> Symtab::builtInTypes()
00157 {
00158     static boost::shared_ptr<builtInTypeCollection> store =
00159         setupBuiltinTypes();
00160     return store;
00161 }
00162 boost::shared_ptr<typeCollection> Symtab::stdTypes()
00163 {
00164     static boost::shared_ptr<typeCollection> store =
00165         setupStdTypes();
00166     return store;
00167 }
00168 
00169 boost::shared_ptr<builtInTypeCollection> Symtab::setupBuiltinTypes()
00170 {
00171     boost::shared_ptr<builtInTypeCollection> builtInTypes =
00172        boost::shared_ptr<builtInTypeCollection>(new builtInTypeCollection);
00173 
00174    typeScalar *newType;
00175 
00176    // NOTE: integral type  mean twos-complement
00177    // -1  int, 32 bit signed integral type
00178    // in stab document, size specified in bits, system size is in bytes
00179    builtInTypes->addBuiltInType(newType = new typeScalar(-1, 4, "int", true));
00180    newType->decrRefCount();
00181    // -2  char, 8 bit type holding a character. GDB & dbx(AIX) treat as signed
00182    builtInTypes->addBuiltInType(newType = new typeScalar(-2, 1, "char", true));
00183    newType->decrRefCount();
00184    // -3  short, 16 bit signed integral type
00185    builtInTypes->addBuiltInType(newType = new typeScalar(-3, 2, "short", true));
00186    newType->decrRefCount();
00187    // -4  long, 32/64 bit signed integral type
00188    builtInTypes->addBuiltInType(newType = new typeScalar(-4, sizeof(long), "long", true));
00189    newType->decrRefCount();
00190    // -5  unsigned char, 8 bit unsigned integral type
00191    builtInTypes->addBuiltInType(newType = new typeScalar(-5, 1, "unsigned char"));
00192    newType->decrRefCount();
00193    // -6  signed char, 8 bit signed integral type
00194    builtInTypes->addBuiltInType(newType = new typeScalar(-6, 1, "signed char", true));
00195    newType->decrRefCount();
00196    // -7  unsigned short, 16 bit unsigned integral type
00197    builtInTypes->addBuiltInType(newType = new typeScalar(-7, 2, "unsigned short"));
00198    newType->decrRefCount();
00199    // -8  unsigned int, 32 bit unsigned integral type
00200    builtInTypes->addBuiltInType(newType = new typeScalar(-8, 4, "unsigned int"));
00201    newType->decrRefCount();
00202    // -9  unsigned, 32 bit unsigned integral type
00203    builtInTypes->addBuiltInType(newType = new typeScalar(-9, 4, "unsigned"));
00204    newType->decrRefCount();
00205    // -10 unsigned long, 32 bit unsigned integral type
00206    builtInTypes->addBuiltInType(newType = new typeScalar(-10, sizeof(unsigned long), "unsigned long"));
00207    newType->decrRefCount();
00208    // -11 void, type indicating the lack of a value
00209    //  XXX-size may not be correct jdd 4/22/99
00210    builtInTypes->addBuiltInType(newType = new typeScalar(-11, 0, "void", false));
00211    newType->decrRefCount();
00212    // -12 float, IEEE single precision
00213    builtInTypes->addBuiltInType(newType = new typeScalar(-12, sizeof(float), "float", true));
00214    newType->decrRefCount();
00215    // -13 double, IEEE double precision
00216    builtInTypes->addBuiltInType(newType = new typeScalar(-13, sizeof(double), "double", true));
00217    newType->decrRefCount();
00218    // -14 long double, IEEE double precision, size may increase in future
00219    builtInTypes->addBuiltInType(newType = new typeScalar(-14, sizeof(long double), "long double", true));
00220    newType->decrRefCount();
00221    // -15 integer, 32 bit signed integral type
00222    builtInTypes->addBuiltInType(newType = new typeScalar(-15, 4, "integer", true));
00223    newType->decrRefCount();
00224    // -16 boolean, 32 bit type. GDB/GCC 0=False, 1=True, all other values
00225    //  have unspecified meaning
00226    builtInTypes->addBuiltInType(newType = new typeScalar(-16, sizeof(bool), "boolean"));
00227    newType->decrRefCount();
00228    // -17 short real, IEEE single precision
00229    //  XXX-size may not be correct jdd 4/22/99
00230    builtInTypes->addBuiltInType(newType = new typeScalar(-17, sizeof(float), "short real", true));
00231    newType->decrRefCount();
00232    // -18 real, IEEE double precision XXX-size may not be correct jdd 4/22/99
00233    builtInTypes->addBuiltInType(newType = new typeScalar(-18, sizeof(double), "real", true));
00234    newType->decrRefCount();
00235    // -19 stringptr XXX- size of void * -- jdd 4/22/99
00236    builtInTypes->addBuiltInType(newType = new typeScalar(-19, sizeof(void *), "stringptr"));
00237    newType->decrRefCount();
00238    // -20 character, 8 bit unsigned character type
00239    builtInTypes->addBuiltInType(newType = new typeScalar(-20, 1, "character"));
00240    newType->decrRefCount();
00241    // -21 logical*1, 8 bit type (Fortran, used for boolean or unsigned int)
00242    builtInTypes->addBuiltInType(newType = new typeScalar(-21, 1, "logical*1"));
00243    newType->decrRefCount();
00244    // -22 logical*2, 16 bit type (Fortran, some for boolean or unsigned int)
00245    builtInTypes->addBuiltInType(newType = new typeScalar(-22, 2, "logical*2"));
00246    newType->decrRefCount();
00247    // -23 logical*4, 32 bit type (Fortran, some for boolean or unsigned int)
00248    builtInTypes->addBuiltInType(newType = new typeScalar(-23, 4, "logical*4"));
00249    newType->decrRefCount();
00250    // -24 logical, 32 bit type (Fortran, some for boolean or unsigned int)
00251    builtInTypes->addBuiltInType(newType = new typeScalar(-24, 4, "logical"));
00252    newType->decrRefCount();
00253    // -25 complex, consists of 2 IEEE single-precision floating point values
00254    builtInTypes->addBuiltInType(newType = new typeScalar(-25, sizeof(float)*2, "complex", true));
00255    newType->decrRefCount();
00256    // -26 complex, consists of 2 IEEE double-precision floating point values
00257    builtInTypes->addBuiltInType(newType = new typeScalar(-26, sizeof(double)*2, "complex*16", true));
00258    newType->decrRefCount();
00259    // -27 integer*1, 8 bit signed integral type
00260    builtInTypes->addBuiltInType(newType = new typeScalar(-27, 1, "integer*1", true));
00261    newType->decrRefCount();
00262    // -28 integer*2, 16 bit signed integral type
00263    builtInTypes->addBuiltInType(newType = new typeScalar(-28, 2, "integer*2", true));
00264    newType->decrRefCount();
00265 
00266    /* Quick hack to make integer*4 compatible with int for Fortran
00267       jnb 6/20/01 */
00268    // This seems questionable - let's try removing that hack - jmo 05/21/04
00269    /*
00270      builtInTypes->addBuiltInType(newType = new type("int",-29,
00271      built_inType, 4));
00272      newType->decrRefCount();
00273    */
00274    // -29 integer*4, 32 bit signed integral type
00275    builtInTypes->addBuiltInType(newType = new typeScalar(-29, 4, "integer*4", true));
00276    newType->decrRefCount();
00277    // -30 wchar, Wide character, 16 bits wide, unsigned (unknown format)
00278    builtInTypes->addBuiltInType(newType = new typeScalar(-30, 2, "wchar"));
00279    newType->decrRefCount();
00280 #if defined(os_windows)
00281    // -31 long long, 64 bit signed integral type
00282    builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long", true));
00283    newType->decrRefCount();
00284    // -32 unsigned long long, 64 bit unsigned integral type
00285    builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(ULONGLONG), "unsigned long long"));
00286    newType->decrRefCount();
00287 #else
00288    // -31 long long, 64 bit signed integral type
00289    builtInTypes->addBuiltInType(newType = new typeScalar(-31, sizeof(long long), "long long", true));
00290    newType->decrRefCount();
00291    // -32 unsigned long long, 64 bit unsigned integral type
00292    builtInTypes->addBuiltInType(newType = new typeScalar(-32, sizeof(unsigned long long), "unsigned long long"));
00293    newType->decrRefCount();
00294 #endif
00295    // -33 logical*8, 64 bit unsigned integral type
00296    builtInTypes->addBuiltInType(newType = new typeScalar(-33, 8, "logical*8"));
00297    newType->decrRefCount();
00298    // -34 integer*8, 64 bit signed integral type
00299    builtInTypes->addBuiltInType(newType = new typeScalar(-34, 8, "integer*8", true));
00300    newType->decrRefCount();
00301 
00302    return builtInTypes;
00303 }
00304 
00305 
00306 boost::shared_ptr<typeCollection> Symtab::setupStdTypes() 
00307 {
00308     boost::shared_ptr<typeCollection> stdTypes =
00309        boost::shared_ptr<typeCollection>(new typeCollection);
00310 
00311    typeScalar *newType;
00312 
00313    stdTypes->addType(newType = new typeScalar(-1, sizeof(int), "int"));
00314    newType->decrRefCount();
00315 
00316    Type *charType = new typeScalar(-2, sizeof(char), "char");
00317    stdTypes->addType(charType);
00318 
00319     std::string tName = "char *";
00320     typePointer *newPtrType;
00321    stdTypes->addType(newPtrType = new typePointer(-3, charType, tName));
00322    charType->decrRefCount();
00323    newPtrType->decrRefCount();
00324 
00325    Type *voidType = new typeScalar(-11, 0, "void", false);
00326    stdTypes->addType(voidType);
00327 
00328     tName = "void *";
00329    stdTypes->addType(newPtrType = new typePointer(-4, voidType, tName));
00330    voidType->decrRefCount();
00331    newPtrType->decrRefCount();
00332 
00333    stdTypes->addType(newType = new typeScalar(-12, sizeof(float), "float"));
00334    newType->decrRefCount();
00335 
00336 #if defined(i386_unknown_nt4_0)
00337    stdTypes->addType(newType = new typeScalar(-31, sizeof(LONGLONG), "long long"));    
00338 #else
00339    stdTypes->addType(newType = new typeScalar(-31, sizeof(long long), "long long"));
00340 #endif
00341 
00342     newType->decrRefCount();
00343 
00344    return stdTypes;
00345 }
00346 
00347 SYMTAB_EXPORT unsigned Symtab::getAddressWidth() const 
00348 {
00349    return address_width_;
00350 }
00351  
00352 SYMTAB_EXPORT bool Symtab::isNativeCompiler() const 
00353 {
00354     return nativeCompiler; 
00355 }
00356 
00357 SYMTAB_EXPORT Symtab::Symtab(MappedFile *mf_) :
00358    AnnotatableSparse(),
00359    mf(mf_), 
00360    imageOffset_(0),   
00361    address_width_(sizeof(int)),
00362    object_type_(obj_Unknown),
00363    defaultNamespacePrefix(""),
00364    no_of_sections(0),
00365    newSectionInsertPoint(0),
00366    no_of_symbols(0),
00367    obj_private(NULL),
00368    _ref_cnt(1)
00369 {
00370     init_debug_symtabAPI();
00371 
00372 #if defined(os_vxworks)
00373     // This is how we initialize objects from WTX information alone.
00374     // Basically replaces extractInfo().
00375     object_type_ = obj_RelocatableFile;
00376     imageOffset_ = 0;
00377     dataOffset_ = 0;
00378     imageLen_ = 0;
00379     dataLen_ = 0;
00380     isStaticBinary_ = false;
00381     hasRel_ = false;
00382     hasRela_ = false;
00383     hasReldyn_ = false;
00384     hasReladyn_ = false;
00385     hasRelplt_ = false;
00386     hasRelaplt_ = false;
00387     is_a_out = false;
00388     code_ptr_ = NULL;
00389     data_ptr_ = NULL;
00390     entry_address_ = 0;
00391     base_address_ = 0;
00392     load_address_ = 0;
00393     is_eel_ = false;
00394 #endif
00395 
00396     createDefaultModule();
00397 }
00398 
00399 SYMTAB_EXPORT Symtab::Symtab() :
00400    imageOffset_(0),
00401    address_width_(sizeof(int)),
00402    object_type_(obj_Unknown),
00403    defaultNamespacePrefix(""),
00404    no_of_sections(0),
00405    newSectionInsertPoint(0),
00406    no_of_symbols(0),
00407    obj_private(NULL),
00408    _ref_cnt(1)
00409 {
00410     init_debug_symtabAPI();
00411     create_printf("%s[%d]: Created symtab via default constructor\n", FILE__, __LINE__);
00412     createDefaultModule();
00413 }
00414 
00415 SYMTAB_EXPORT bool Symtab::isExec() const 
00416 {
00417     return is_a_out; 
00418 }
00419 
00420 SYMTAB_EXPORT bool Symtab::isStripped() 
00421 {
00422 #if defined(os_linux) || defined(os_freebsd)
00423     Region *sec;
00424     return !findRegion(sec,".symtab");
00425 #else
00426     return (no_of_symbols==0);
00427 #endif
00428 }
00429 
00430 SYMTAB_EXPORT Offset Symtab::imageOffset() const 
00431 {
00432     return imageOffset_;
00433 }
00434 
00435 SYMTAB_EXPORT Offset Symtab::dataOffset() const 
00436 { 
00437     return dataOffset_;
00438 }
00439 
00440 SYMTAB_EXPORT Offset Symtab::dataLength() const 
00441 {
00442     return dataLen_;
00443 } 
00444 
00445 SYMTAB_EXPORT Offset Symtab::imageLength() const 
00446 {
00447     return imageLen_;
00448 }
00449 
00450 SYMTAB_EXPORT void Symtab::fixup_code_and_data(Offset newImageOffset,
00451                                                Offset newImageLength,
00452                                                Offset newDataOffset,
00453                                                Offset newDataLength)
00454 {
00455     imageOffset_ = newImageOffset;
00456     imageLen_ = newImageLength;
00457     dataOffset_ = newDataOffset;
00458     dataLen_ = newDataLength;
00459 
00460     // Should we update the underlying Object?
00461 }
00462 
00463 /*
00464 SYMTAB_EXPORT char* Symtab::image_ptr ()  const 
00465 {
00466    return code_ptr_;
00467 }
00468 
00469 SYMTAB_EXPORT char* Symtab::data_ptr ()  const 
00470 { 
00471    return data_ptr_;
00472 }
00473 */
00474 SYMTAB_EXPORT const char*  Symtab::getInterpreterName() const 
00475 {
00476    if (interpreter_name_.length())
00477       return interpreter_name_.c_str();
00478    return NULL;
00479 }
00480  
00481 SYMTAB_EXPORT Offset Symtab::getEntryOffset() const 
00482 { 
00483    return entry_address_;
00484 }
00485 
00486 SYMTAB_EXPORT Offset Symtab::getBaseOffset() const 
00487 {
00488    return base_address_;
00489 }
00490 
00491 SYMTAB_EXPORT Offset Symtab::getLoadOffset() const 
00492 { 
00493    return load_address_;
00494 }
00495 
00496 SYMTAB_EXPORT Offset Symtab::getTOCoffset(Function *func) const 
00497 {
00498   return getTOCoffset(func ? func->getOffset() : 0); 
00499 }
00500 
00501 SYMTAB_EXPORT Offset Symtab::getTOCoffset(Offset off) const
00502 {
00503   return obj_private->getTOCoffset(off);
00504 }
00505 
00506 void Symtab::setTOCOffset(Offset off) {
00507   obj_private->setTOCoffset(off);
00508   return;
00509 }
00510 
00511 SYMTAB_EXPORT string Symtab::getDefaultNamespacePrefix() const
00512 {
00513     return defaultNamespacePrefix;
00514 }
00515     
00516     
00517 // TODO -- is this g++ specific
00518 bool Symtab::buildDemangledName( const std::string &mangled, 
00519       std::string &pretty,
00520       std::string &typed,
00521       bool nativeCompiler, 
00522       supportedLanguages lang )
00523 {
00524    /* The C++ demangling function demangles MPI__Allgather (and other MPI__
00525     * functions with start with A) into the MPI constructor.  In order to
00526     * prevent this a hack needed to be made, and this seemed the cleanest
00527     * approach.
00528     */
00529 
00530    if ((mangled.length()>5) && (mangled.substr(0,5)==std::string("MPI__"))) 
00531    {
00532       return false;
00533    }      
00534 
00535    /* If it's Fortran, eliminate the trailing underscores, if any. */
00536    if (lang == lang_Fortran 
00537          || lang == lang_CMFortran 
00538          || lang == lang_Fortran_with_pretty_debug )
00539    {
00540       if ( mangled[ mangled.length() - 1 ] == '_' ) 
00541       {
00542          char * demangled = P_strdup( mangled.c_str() );
00543          demangled[ mangled.length() - 1 ] = '\0';
00544          pretty = std::string( demangled );
00545 
00546          free ( demangled );
00547          return true;
00548       }
00549       else 
00550       {
00551          /* No trailing underscores, do nothing */
00552          return false;
00553       }
00554    } /* end if it's Fortran. */
00555 
00556    //  Check to see if we have a gnu versioned symbol on our hands.
00557    //  These are of the form <symbol>@<version> or <symbol>@@<version>
00558    //
00559    //  If we do, we want to create a "demangled" name for the one that
00560    //  is of the form <symbol>@@<version> since this is, by definition,
00561    //  the default.  The "demangled" name will just be <symbol>
00562 
00563    //  NOTE:  this is just a 0th order approach to dealing with versioned
00564    //         symbols.  We may need to do something more sophisticated
00565    //         in the future.  JAW 10/03
00566 
00567 #if !defined(os_windows)
00568 
00569    const char *atat;
00570 
00571    if (NULL != (atat = strstr(mangled.c_str(), "@@"))) 
00572    {
00573         pretty = mangled.substr(0 /*start pos*/, 
00574                         (int)(atat - mangled.c_str())/*len*/);
00575         //char msg[256];
00576         //sprintf(msg, "%s[%d]: 'demangling' versioned symbol: %s, to %s",
00577         //          __FILE__, __LINE__, mangled.c_str(), pretty.c_str());
00578 
00579         //cerr << msg << endl;
00580         //logLine(msg);
00581       
00582         return true;
00583     }
00584 
00585 #endif
00586 
00587     bool retval = false;
00588   
00589     /* Try demangling it. */
00590     char * demangled = P_cplus_demangle( mangled.c_str(), nativeCompiler, false);
00591     if (demangled) 
00592     {
00593         pretty = std::string( demangled );
00594         retval = true;
00595     }
00596   
00597     char *t_demangled = P_cplus_demangle(mangled.c_str(), nativeCompiler, true);
00598     if (t_demangled && (strcmp(t_demangled, demangled) != 0)) 
00599     {
00600         typed = std::string(t_demangled);
00601         retval = true;
00602     }
00603 
00604     if (demangled)
00605         free(demangled);
00606     if (t_demangled)
00607         free(t_demangled);
00608 
00609     return retval;
00610 } /* end buildDemangledName() */
00611 
00612 
00613 /*
00614  * extractSymbolsFromFile
00615  *
00616  * Create a Symtab-level list of symbols by pulling out data
00617  * from the low-level parse (linkedFile).
00618  * Technically this causes a duplication of symbols; however,
00619  * we will be rewriting these symbols and so we need our own
00620  * copy. 
00621  *
00622  * TODO: delete the linkedFile once we're done?
00623  */
00624 
00625 bool Symtab::extractSymbolsFromFile(Object *linkedFile, std::vector<Symbol *> &raw_syms) 
00626 {
00627    for (SymbolIter symIter(*linkedFile); symIter; symIter++)  {
00628       Symbol *sym = symIter.currval();
00629       if (!sym)  {
00630          fprintf(stderr, "%s[%d]:  range error, stopping now\n", FILE__, __LINE__);
00631          return true;
00632       }
00633 
00634       // If a symbol starts with "." we want to skip it. These indicate labels in the
00635       // code. 
00636       
00637       // removed 1/09: this should be done in Dyninst, not Symtab
00638       
00639       // Have to do this before the undef check, below. 
00640       fixSymRegion(sym);
00641       
00642       // check for undefined dynamic symbols. Used when rewriting relocation section.
00643       // relocation entries have references to these undefined dynamic symbols.
00644       // We also have undefined symbols for the static binary case.
00645 
00646 #if !defined(os_vxworks)
00647       if (sym->getRegion() == NULL && !sym->isAbsolute() && !sym->isCommonStorage()) {
00648          undefDynSyms.push_back(sym);
00649          continue;
00650       }
00651 #endif
00652       
00653       // Check whether this symbol has a valid offset. If they do not we have a
00654       // consistency issue. This should be a null check.
00655       
00656       // Symbols can have an offset of 0 if they don't refer to things within a file.
00657       
00658       raw_syms.push_back(sym);
00659    }
00660    
00661    return true;
00662 }
00663 
00664 bool Symtab::fixSymRegion(Symbol *sym) {
00665    if (!sym->getRegion()) return true;
00666    
00667    if (sym->getType() != Symbol::ST_FUNCTION &&
00668        sym->getType() != Symbol::ST_OBJECT) return true;
00669    
00670    if (sym->getRegion()->getMemOffset() <= sym->getOffset() &&
00671        (sym->getRegion()->getMemOffset() + sym->getRegion()->getMemSize()) > sym->getOffset())
00672       return true;
00673    
00674    sym->setRegion(findEnclosingRegion(sym->getOffset()));
00675    
00676    return true;
00677 }
00678 
00679 /*
00680  * fixSymModules
00681  * 
00682  * Add Module information to all symbols. 
00683  */
00684 
00685 bool Symtab::fixSymModules(std::vector<Symbol *> &raw_syms) 
00686 {
00687     for (unsigned i = 0; i < raw_syms.size(); i++) {
00688         fixSymModule(raw_syms[i]);
00689     }
00690     Object *obj = getObject();
00691     if (!obj) {
00692 #if !defined(os_vxworks)
00693        fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
00694 #endif
00695        return false;
00696     }
00697     const std::vector<std::pair<std::string, Offset> > &mods = obj->modules_;
00698     for (unsigned i=0; i< mods.size(); i++) {
00699        getOrCreateModule(mods[i].first, mods[i].second);
00700     }
00701     
00702     return true;
00703 }
00704 
00705 /*
00706  * demangleSymbols
00707  *
00708  * Perform name demangling on all symbols.
00709  */
00710 
00711 bool Symtab::demangleSymbols(std::vector<Symbol *> &raw_syms) 
00712 {
00713     for (unsigned i = 0; i < raw_syms.size(); i++) {
00714         demangleSymbol(raw_syms[i]);
00715     }
00716     return true;
00717 }
00718 
00719 /*
00720  * createIndices
00721  *
00722  * We index symbols by various attributes for quick lookup. Build those
00723  * indices here. 
00724  */
00725 
00726 bool Symtab::createIndices(std::vector<Symbol *> &raw_syms, bool undefined) {
00727     for (unsigned i = 0; i < raw_syms.size(); i++) {
00728        addSymbolToIndices(raw_syms[i], undefined);
00729     }
00730     return true;
00731 }
00732 
00733 /*
00734  * createAggregates
00735  *
00736  * Frequently there will be multiple Symbols that refer to a single 
00737  * code object (e.g., function or variable). We use separate objects
00738  * to refer to these aggregates, and build those objects here. 
00739  */
00740 
00741 bool Symtab::createAggregates() 
00742 {
00743 #if !defined(os_vxworks)
00744     // In VxWorks, symbol offsets are not complete until object is loaded.
00745 
00746     for (unsigned i = 0; i < everyDefinedSymbol.size(); i++) 
00747       {
00748     if (!doNotAggregate(everyDefinedSymbol[i])) {
00749       addSymbolToAggregates(everyDefinedSymbol[i]);
00750     }
00751       }
00752 #endif
00753 
00754     return true;
00755 }
00756  
00757 bool Symtab::fixSymModule(Symbol *&sym) 
00758 {
00759     //////////
00760     //////////
00761     //////////
00762     //
00763     // It has been decided that all libraries shall have only one
00764     // module named after the library. The a.out has one module
00765     // per (reported) source file, plus DEFAULT_MODULE for everything
00766     // else. This is enforced here, although the Object-* files might
00767     // do it as well.
00768     Module *mod = NULL;
00769     if (getObjectType() == obj_SharedLib) {
00770        mod = getDefaultModule();
00771     }
00772     else {
00773        Object *obj = getObject();
00774        if (!obj)
00775        {
00776 #if !defined(os_vxworks)
00777           fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
00778 #endif
00779           return false;
00780        }
00781        std::string modName = obj->findModuleForSym(sym);
00782        if (modName.length() == 0) {
00783           mod = getDefaultModule();
00784        }
00785        else {
00786           mod = getOrCreateModule(modName, sym->getOffset());
00787        }
00788     }
00789 
00790 
00791     if (!mod)
00792        return false;
00793     
00794     sym->setModule(mod);
00795     return true;
00796 }
00797 
00798 bool Symtab::demangleSymbol(Symbol *&sym) {
00799    bool typed_demangle = false;
00800    if (sym->getType() == Symbol::ST_FUNCTION) typed_demangle = true;
00801 
00802    // This is a bit of a hack; we're trying to demangle undefined symbols which don't necessarily
00803    // have a ST_FUNCTION type. 
00804    if (sym->getRegion() == NULL && !sym->isAbsolute() && !sym->isCommonStorage())
00805       typed_demangle = true;
00806 
00807    if (typed_demangle) {
00808       Module *rawmod = sym->getModule();
00809 
00810       // At this point we need to generate the following information:
00811       // A symtab name.
00812       // A pretty (demangled) name.
00813       // The symtab name goes in the global list as well as the module list.
00814       // Same for the pretty name.
00815       // Finally, check addresses to find aliases.
00816       
00817       std::string mangled_name = sym->getMangledName();
00818       std::string working_name = mangled_name;
00819       
00820 #if !defined(os_windows)        
00821       //Remove extra stabs information
00822       const char *p = strchr(working_name.c_str(), ':');
00823       if( p ) {
00824          unsigned nchars = p - mangled_name.c_str();
00825          working_name = std::string(mangled_name.c_str(), nchars);
00826       }
00827 #endif        
00828       
00829       std::string pretty_name = working_name;
00830       std::string typed_name = working_name;
00831       
00832       if (!buildDemangledName(working_name, pretty_name, typed_name,
00833                               nativeCompiler, (rawmod ? rawmod->language() : lang_Unknown))) {
00834          pretty_name = working_name;
00835       }
00836       
00837       sym->prettyName_ = pretty_name;
00838       sym->typedName_ = typed_name;
00839    }
00840    else {
00841        // All cases where there really shouldn't be a mangled
00842       // name, since mangling is for functions.
00843       
00844       char *prettyName = P_cplus_demangle(sym->getMangledName().c_str(), nativeCompiler, false);
00845       if (prettyName) {
00846          sym->prettyName_ = std::string(prettyName);
00847          // XXX caller-freed
00848          free(prettyName); 
00849       }
00850    }
00851 
00852    return true;
00853 }
00854 
00855 bool Symtab::addSymbolToIndices(Symbol *&sym, bool undefined) 
00856 {
00857    assert(sym);
00858    if (!undefined) {
00859       everyDefinedSymbol.push_back(sym);
00860       symsByMangledName[sym->getMangledName()].push_back(sym);
00861       symsByPrettyName[sym->getPrettyName()].push_back(sym);
00862       symsByTypedName[sym->getTypedName()].push_back(sym);
00863 #if !defined(os_vxworks)    
00864       // VxWorks doesn't know symbol addresses until object is loaded.
00865       symsByOffset[sym->getOffset()].push_back(sym);
00866 #endif
00867    }
00868    else {
00869       // We keep a different index for undefined symbols
00870       undefDynSymsByMangledName[sym->getMangledName()].push_back(sym);
00871       undefDynSymsByPrettyName[sym->getPrettyName()].push_back(sym);
00872       undefDynSymsByTypedName[sym->getTypedName()].push_back(sym);
00873       // And undefDynSyms is already filled in
00874    }
00875     return true;
00876 }
00877 
00878 bool Symtab::addSymbolToAggregates(Symbol *&sym) 
00879 {
00880 
00881     switch(sym->getType()) {
00882     case Symbol::ST_FUNCTION: {
00883         // We want to do the following:
00884         // If no function exists, create and add. 
00885         // Combine this information
00886         //   Add this symbol's names to the function.
00887         //   Keep module information 
00888 
00889         Function *func = NULL;
00890         findFuncByEntryOffset(func, sym->getOffset());
00891         if (!func) {
00892             // Create a new function
00893             // Also, update the symbol to point to this function.
00894 
00895             func = new Function(sym);
00896 
00897             everyFunction.push_back(func);
00898             sorted_everyFunction = false;
00899             funcsByOffset[sym->getOffset()] = func;
00900         }
00901         else {
00902             /* XXX 
00903              * For relocatable files, the offset of a symbol is relative to the
00904              * beginning of a Region. Therefore, a symbol in a relocatable file
00905              * is not uniquely identifiable by its offset, but it is uniquely
00906              * identifiable by its Region and its offset.
00907              *
00908              * For now, do not add these functions to funcsByOffset collection.
00909              */
00910 
00911             if( func->getRegion() != sym->getRegion() ) {
00912                 func = new Function(sym);
00913                 everyFunction.push_back(func);
00914                 sorted_everyFunction = false;
00915             }
00916             func->addSymbol(sym);
00917         } 
00918         sym->setFunction(func);
00919 
00920         break;
00921     }
00922     case Symbol::ST_TLS:
00923     case Symbol::ST_OBJECT: {
00924         // The same as the above, but with variables.
00925         Variable *var = NULL;
00926         findVariableByOffset(var, sym->getOffset());
00927         if (!var) {
00928             // Create a new function
00929             // Also, update the symbol to point to this function.
00930             var = new Variable(sym);
00931             
00932             everyVariable.push_back(var);
00933             varsByOffset[sym->getOffset()] = var;
00934         }
00935         else {
00936             /* XXX
00937              * For relocatable files, the offset is not a unique identifier for
00938              * a Symbol. With functions, the Region and offset could be used to
00939              * identify the symbol. With variables, the Region and offset may 
00940              * not uniquely identify the symbol. The only case were this occurs
00941              * is with COMMON symbols -- their offset is their memory alignment
00942              * and their Region is undefined. In this case, always create a 
00943              * new variable.
00944              */
00945             if( obj_RelocatableFile == getObjectType() &&
00946                 ( var->getRegion() != sym->getRegion() ||
00947                   NULL == sym->getRegion() ) )
00948             {
00949                 var = new Variable(sym);
00950                 everyVariable.push_back(var);
00951             }else{
00952                 var->addSymbol(sym);
00953             }
00954         }
00955         sym->setVariable(var);
00956         break;
00957     }
00958     default: {
00959         break;
00960     }
00961     }
00962     return true;
00963 }
00964 
00965 // A hacky override for specially treating symbols that appear
00966 // to be functions or variables but aren't.
00967 //
00968 // Example: IA-32/AMD-64 libc (and others compiled with libc headers)
00969 // uses outlined locking primitives. These are named _L_lock_<num>
00970 // and _L_unlock_<num> and labelled as functions. We explicitly do
00971 // not include them in function scope.
00972 bool Symtab::doNotAggregate(Symbol *&sym) {
00973   if (sym->getMangledName().compare(0, strlen("_L_lock_"), "_L_lock_") == 0) {
00974     return true;
00975   }
00976   if (sym->getMangledName().compare(0, strlen("_L_unlock_"), "_L_unlock_") == 0) {
00977     return true;
00978   }
00979 
00980 #if 0
00981   // Disabling as a test; this means we find _zero_ Function objects. 
00982   // PPC64 Linux symbols in the .opd section appear to be functions,
00983   // but are not.
00984   if (sym->getRegion() && sym->getRegion()->getRegionName() == ".opd") {
00985       return true;
00986   }
00987 #endif
00988   return false;
00989 }
00990 
00991 /* Add the new name to the appropriate symbol index */
00992 
00993 bool Symtab::updateIndices(Symbol *sym, std::string newName, NameType nameType) {
00994     if (nameType & mangledName) {
00995         // Add this symbol under the given name (as mangled)
00996         symsByMangledName[newName].push_back(sym);
00997     }
00998     if (nameType & prettyName) {
00999         // Add this symbol under the given name (as pretty)
01000         symsByPrettyName[newName].push_back(sym);
01001     }
01002     if (nameType & typedName) {
01003         // Add this symbol under the given name (as typed)
01004         symsByTypedName[newName].push_back(sym);
01005     }
01006     return true;
01007 }
01008 
01009 #if 0
01010 /* checkPPC64DescriptorSymbols() is no longer needed.  3-word descriptor
01011  * symbols are properly taken care of during symbol parsing.  See
01012  * parse_symbols() in Object-elf.C for details.
01013  */
01014 
01015 #if defined(ppc64_linux)
01016 /* Special case for ppc64 ELF binaries. Sometimes a function has a 3-byte descriptor symbol
01017  * along with it in the symbol table and "." preceding its original pretty name for the correct
01018  * function symbol. This checks to see if we have a corresponding 3-byte descriptor symbol existing
01019  * and if it does we remove the preceding "." from the name of the symbol
01020  */
01021 
01022 void Symtab::checkPPC64DescriptorSymbols(Object *linkedFile)
01023 {
01024    // find the real functions -- those with the correct type in the symbol table
01025    for(SymbolIter symIter(*linkedFile); symIter;symIter++)
01026    {
01027       Symbol *lookUp = symIter.currval();
01028       const char *np = lookUp->getMangledName().c_str();
01029       if(!np)
01030          continue;
01031 
01032       if(np[0] == '.' && (lookUp->getType() == Symbol::ST_FUNCTION))
01033       {
01034          std::vector<Symbol *>syms;
01035          std::string newName = np+1;
01036          if(linkedFile->get_symbols(newName, syms) && (syms[0]->getSize() == 24 || syms[0]->getSize() == 0))
01037          {
01038             //Remove the "." from the name
01039             lookUp->mangledNames[0] = newName;
01040 
01041             //Change the type of the descriptor symbol
01042             syms[0]->type_ = Symbol::ST_NOTYPE;
01043          }
01044       }
01045    }
01046 
01047 }
01048 
01049 #endif
01050 #endif
01051 
01052 //  setModuleLanguages is only called after modules have been defined.
01053 //  it attempts to set each module's language, information which is needed
01054 //  before names can be demangled.
01055 void Symtab::setModuleLanguages(dyn_hash_map<std::string, supportedLanguages> *mod_langs)
01056 {
01057    if (!mod_langs->size())
01058       return;  // cannot do anything here
01059    //  this case will arise on non-stabs platforms until language parsing can be introduced at this level
01060    std::vector<Module *> *modlist;
01061    Module *currmod = NULL;
01062    modlist = &_mods;
01063    //int dump = 0;
01064 
01065    for (unsigned int i = 0;  i < modlist->size(); ++i)
01066    {
01067       currmod = (*modlist)[i];
01068       supportedLanguages currLang;
01069       if (currmod->isShared()) {
01070          continue;  // need to find some way to get shared object languages?
01071       }
01072 
01073       const std::string fn = currmod->fileName();
01074       if (mod_langs->find(currmod->fileName()) != mod_langs->end())
01075       {
01076          currLang = (*mod_langs)[fn];
01077       }
01078       else if (fn.rfind(".s") != std::string::npos ||
01079             fn.rfind(".asm") != std::string::npos)
01080       {
01081          currLang = lang_Assembly;
01082       }
01083       else if (fn.rfind(".c") != std::string::npos)
01084       {
01085          currLang = lang_C;
01086       }
01087       else if (fn.rfind(".cpp") != std::string::npos ||
01088             fn.rfind(".cc") != std::string::npos ||
01089             fn.rfind(".C") != std::string::npos)
01090       {
01091          currLang = lang_CPlusPlus;
01092       }
01093       else
01094       {
01095          continue;
01096       }
01097       currmod->setLanguage(currLang);
01098    }
01099 }
01100 
01101 void Symtab::createDefaultModule() {
01102     Module *mod = NULL;
01103     if (getObjectType() == obj_SharedLib) {
01104         mod = new Module(lang_Unknown, 
01105                          imageOffset_,
01106                          name(),
01107                          this);
01108     }
01109     else {
01110         mod = new Module(lang_Unknown, 
01111                          imageOffset_,
01112 #if defined(os_vxworks)
01113                          // VxWorks' kernel objects should
01114                          // have their own module.
01115                          name(),
01116 #else
01117                          "DEFAULT_MODULE",
01118 #endif
01119                          this);
01120     }
01121     modsByFileName[mod->fileName()] = mod;
01122     modsByFullName[mod->fullName()] = mod;
01123     _mods.push_back(mod);
01124 }
01125 
01126 
01127 
01128 Module *Symtab::getOrCreateModule(const std::string &modName, 
01129                                   const Offset modAddr)
01130 {
01131    std::string nameToUse;
01132    if (modName.length() > 0)
01133       nameToUse = modName;
01134    else
01135       nameToUse = "DEFAULT_MODULE";
01136 
01137    Module *fm = NULL;
01138    if (findModuleByName(fm, nameToUse)) 
01139    {
01140       return fm;
01141    }
01142 
01143     const char *str = nameToUse.c_str();
01144     int len = nameToUse.length();
01145     assert(len>0);
01146 
01147     // TODO ignore directory definitions for now
01148     if (str[len-1] == '/') 
01149         return NULL;
01150 
01151     return (newModule(nameToUse, modAddr, lang_Unknown));
01152 }
01153  
01154 Module *Symtab::newModule(const std::string &name, const Offset addr, supportedLanguages lang)
01155 {
01156     Module *ret = NULL;
01157     // modules can be defined several times in C++ due to templates and
01158     //   in-line member functions.
01159 
01160     if (findModuleByName(ret, name)) 
01161     {
01162         return(ret);
01163     }
01164 
01165     //parsing_printf("=== image, creating new pdmodule %s, addr 0x%x\n",
01166     //              name.c_str(), addr);
01167     
01168     std::string fileNm, fullNm;
01169     fullNm = name;
01170     fileNm = extract_pathname_tail(name);
01171 
01172     // /* DEBUG */ fprintf( stderr, "%s[%d]: In %p: Creating new pdmodule '%s'/'%s'\n", FILE__, __LINE__, this, fileNm.c_str(), fullNm.c_str() );
01173     create_printf("%s[%d]: In %p: Creating new module '%s'/'%s'\n", FILE__, __LINE__, this, fileNm.c_str(), fullNm.c_str());
01174 
01175     ret = new Module(lang, addr, fullNm, this);
01176     assert(ret);
01177 
01178     /*
01179      * FIXME
01180      *
01181      * There are cases where the fileName can be the same, but the full name is
01182      * different and the modules are actually different. This is an inherent
01183      * problem with how modules are processed.
01184      */
01185     if (modsByFileName.end() != modsByFileName.find(ret->fileName()))
01186     {
01187        create_printf("%s[%d]:  WARN:  LEAK?  already have module with name %s\n", 
01188              FILE__, __LINE__, ret->fileName().c_str());
01189     }
01190 
01191     if (modsByFullName.end() != modsByFullName.find(ret->fullName()))
01192     {
01193        create_printf("%s[%d]:  WARN:  LEAK?  already have module with name %s\n", 
01194                      FILE__, __LINE__, ret->fullName().c_str());
01195     }
01196 
01197     modsByFileName[ret->fileName()] = ret;
01198     modsByFullName[ret->fullName()] = ret;
01199     _mods.push_back(ret);
01200     
01201     return (ret);
01202 }
01203 
01204 Symtab::Symtab(std::string filename, bool defensive_bin, bool &err) :
01205    member_offset_(0),
01206    is_a_out(false), 
01207    main_call_addr_(0),
01208    nativeCompiler(false), 
01209    isLineInfoValid_(false), 
01210    isTypeInfoValid_(false),
01211    isDefensiveBinary_(defensive_bin),
01212    obj_private(NULL),
01213    _ref_cnt(1)
01214 {
01215     init_debug_symtabAPI();
01216    // Initialize error parameter
01217    err = false;
01218    
01219    create_printf("%s[%d]: created symtab for %s\n", FILE__, __LINE__, filename.c_str());
01220 
01221 #if defined (os_windows)
01222    extern void fixup_filename(std::string &);
01223    fixup_filename(filename);
01224 #endif
01225 
01226    //  createMappedFile handles reference counting
01227    mf = MappedFile::createMappedFile(filename);
01228    if (!mf) {
01229       create_printf("%s[%d]: WARNING: creating symtab for %s, " 
01230                     "createMappedFile() failed\n", FILE__, __LINE__, 
01231                     filename.c_str());
01232       err = true;
01233       return;
01234    }
01235 
01236    obj_private = new Object(mf, defensive_bin, 
01237                             symtab_log_perror, true);
01238    if (obj_private->hasError()) {
01239      err = true;
01240      return;
01241    }
01242 
01243    if (!extractInfo(obj_private))
01244    {
01245       create_printf("%s[%d]: WARNING: creating symtab for %s, extractInfo() " 
01246                     "failed\n", FILE__, __LINE__, filename.c_str());
01247       err = true;
01248    }
01249 
01250    member_name_ = mf->filename();
01251 
01252    defaultNamespacePrefix = "";
01253 }
01254 
01255 Symtab::Symtab(unsigned char *mem_image, size_t image_size, 
01256                const std::string &name, bool defensive_bin, bool &err) :
01257    member_offset_(0),
01258    is_a_out(false), 
01259    main_call_addr_(0),
01260    nativeCompiler(false),
01261    isLineInfoValid_(false),
01262    isTypeInfoValid_(false),
01263    isDefensiveBinary_(defensive_bin),
01264    obj_private(NULL),
01265    _ref_cnt(1)
01266 {
01267    // Initialize error parameter
01268    err = false;
01269   
01270    create_printf("%s[%d]: created symtab for memory image at addr %u\n", 
01271                  FILE__, __LINE__, mem_image);
01272 
01273    //  createMappedFile handles reference counting
01274    mf = MappedFile::createMappedFile(mem_image, image_size, name);
01275    if (!mf) {
01276       create_printf("%s[%d]: WARNING: creating symtab for memory image at " 
01277                     "addr %u, createMappedFile() failed\n", FILE__, __LINE__, 
01278                     mem_image);
01279       err = true;
01280       return;
01281    }
01282 
01283    obj_private = new Object(mf, defensive_bin, 
01284                             symtab_log_perror, true);
01285    if (obj_private->hasError()) {
01286      err = true;
01287      return;
01288    }
01289 
01290    if (!extractInfo(obj_private))
01291    {
01292       create_printf("%s[%d]: WARNING: creating symtab for memory image at addr" 
01293                     "%u, extractInfo() failed\n", FILE__, __LINE__, mem_image);
01294       err = true;
01295    }
01296 
01297    member_name_ = mf->filename();
01298 
01299    defaultNamespacePrefix = "";
01300 }
01301 
01302 // Symtab constructor for archive members
01303 #if defined(os_aix)
01304 Symtab::Symtab(std::string filename, std::string member_name, Offset offset, 
01305                bool &err, void *base) :
01306    member_name_(member_name), 
01307    member_offset_(offset),
01308    is_a_out(false),
01309    main_call_addr_(0), 
01310    nativeCompiler(false), 
01311    isLineInfoValid_(false),
01312    isTypeInfoValid_(false), 
01313    obj_private(NULL),
01314    _ref_cnt(1)
01315 {
01316    mf = MappedFile::createMappedFile(filename);
01317    assert(mf);
01318    obj_private = new Object(mf, member_name, offset, symtab_log_perror, base);
01319    if (obj_private->hasError()) {
01320      err = true;
01321      return;
01322    }
01323    err = !extractInfo(obj_private);
01324    defaultNamespacePrefix = "";
01325 
01326    create_printf("%s[%d]: created symtab for %s(%s)\n", FILE__, __LINE__, filename.c_str(),
01327            member_name.c_str());
01328 }
01329 #else
01330 Symtab::Symtab(std::string, std::string, Offset, bool &, void *)
01331 {
01332     assert(0);
01333 }
01334 #endif
01335 
01336 #if defined(os_aix) // is this ever used on AIX? 
01337 Symtab::Symtab(char *mem_image, size_t image_size, std::string member_name,
01338                        Offset offset, bool &err, void *base) :
01339    member_name_(member_name), 
01340    member_offset_(offset),
01341    is_a_out(false), 
01342    main_call_addr_(0),
01343    nativeCompiler(false), 
01344    isLineInfoValid_(false), 
01345    isTypeInfoValid_(false),
01346    _ref_cnt(1)
01347 {
01348    mf = MappedFile::createMappedFile(mem_image, image_size);
01349    assert(mf);
01350    obj_private = new Object(mf, mf, member_name, offset, symtab_log_perror, base);
01351    if (obj_private->hasError()) {
01352      err = true;
01353      return;
01354    }
01355    err = !extractInfo(obj_private);
01356    defaultNamespacePrefix = "";
01357 }
01358 #else 
01359 Symtab::Symtab(char *, size_t, std::string , Offset, bool &, void *)
01360 {
01361     assert(0);
01362 }
01363 #endif
01364 
01365 bool sort_reg_by_addr(const Region* a, const Region* b)
01366 {
01367   if (a->getMemOffset() == b->getMemOffset())
01368     return a->getMemSize() < b->getMemSize();
01369   return a->getMemOffset() < b->getMemOffset();
01370 }
01371 
01372 extern void print_symbols( std::vector< Symbol *>& allsymbols );
01373 extern void print_symbol_map( dyn_hash_map< std::string, std::vector< Symbol *> > *symbols);
01374 
01375 bool Symtab::extractInfo(Object *linkedFile)
01376 {
01377 #if defined(TIMED_PARSE)
01378     struct timeval starttime;
01379     gettimeofday(&starttime, NULL);
01380 #endif
01381 
01382     /* FIXME 
01383      *
01384      * Some ELF .o's don't have contiguous code and data Regions so these data
01385      * members are imprecise. These members should probably be deprecated in
01386      * favor of the getCodeRegions and getDataRegions functions.
01387      */
01388 
01389     imageOffset_ = linkedFile->code_off();
01390     dataOffset_ = linkedFile->data_off();
01391 
01392     imageLen_ = linkedFile->code_len();
01393     dataLen_ = linkedFile->data_len();
01394     
01395     if (0 == imageLen_ || 0 == linkedFile->code_ptr()) 
01396     {
01397         // for AIX, code_ptr()==NULL is normal behavior
01398 #if !defined(os_aix)
01399        if (0 == linkedFile->code_ptr()) {
01400           //fprintf(stderr, "[%s][%d]WARNING: null code pointer in Symtab for"
01401           //" file %s, possibly due to a missing .text section.\n",
01402           //__FILE__,__LINE__, file().c_str());
01403           linkedFile->code_ptr_ = (char *) linkedFile->code_off();
01404        }
01405        else 
01406 #endif
01407        {
01408            if( object_type_ != obj_RelocatableFile ||
01409                linkedFile->code_ptr() == 0)
01410            {
01411                 serr = Obj_Parsing;
01412                 return false;
01413            }
01414        }
01415    }
01416     
01417   //  if (!imageLen_ || !linkedFile->code_ptr()) {
01418   //      serr = Obj_Parsing; 
01419   //      return false; 
01420    // }
01421 
01422     no_of_sections = linkedFile->no_of_sections();
01423     newSectionInsertPoint = no_of_sections;
01424     no_of_symbols = linkedFile->no_of_symbols();
01425     
01426     isStaticBinary_ = linkedFile->isStaticBinary();
01427 
01428     hasRel_ = false;
01429     hasRela_ = false;
01430     hasReldyn_ = false;
01431     hasReladyn_ = false;
01432     hasRelplt_ = false;
01433     hasRelaplt_ = false;
01434     regions_ = linkedFile->getAllRegions();
01435 
01436     for (unsigned index=0;index<regions_.size();index++)
01437       {
01438       regions_[index]->setSymtab(this);
01439 
01440         if ( regions_[index]->isLoadable() ) 
01441         {
01442            if (     (regions_[index]->getRegionPermissions() == Region::RP_RX) 
01443                  || (isDefensiveBinary_ && 
01444                      regions_[index]->getRegionPermissions() == Region::RP_RW)
01445                  || (regions_[index]->getRegionPermissions() == Region::RP_RWX)) 
01446            {
01447               codeRegions_.push_back(regions_[index]);
01448            }
01449            else 
01450            {
01451               dataRegions_.push_back(regions_[index]);
01452            }
01453         }
01454 
01455         regionsByEntryAddr[regions_[index]->getMemOffset()] = regions_[index];
01456 
01457         if (regions_[index]->getRegionType() == Region::RT_REL) 
01458         {
01459             hasRel_ = true;
01460         }
01461 
01462         if (regions_[index]->getRegionType() == Region::RT_RELA) 
01463         {
01464             hasRela_ = true;
01465         }
01466 
01467 #if defined(os_linux) || defined(os_freebsd)
01468         hasReldyn_ = linkedFile->hasReldyn();
01469     hasReladyn_ = linkedFile->hasReladyn();
01470         hasRelplt_ = linkedFile->hasRelplt();
01471         hasRelaplt_ = linkedFile->hasRelaplt();
01472 #endif  
01473 
01474     }
01475     // sort regions_ & codeRegions_ vectors
01476 
01477     std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
01478     std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
01479     std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
01480 
01481     /* insert error check here. check if parsed */
01482     address_width_ = linkedFile->getAddressWidth();
01483     is_a_out = linkedFile->is_aout();
01484     code_ptr_ = linkedFile->code_ptr();
01485     data_ptr_ = linkedFile->data_ptr();
01486 
01487     if (linkedFile->interpreter_name())
01488        interpreter_name_ = std::string(linkedFile->interpreter_name());
01489 
01490     entry_address_ = linkedFile->getEntryAddress();
01491     base_address_ = linkedFile->getBaseAddress();
01492     load_address_ = linkedFile->getLoadAddress();
01493     object_type_  = linkedFile->objType();
01494     is_eel_ = linkedFile->isEEL();
01495     linkedFile->getSegments(segments_);
01496 
01497 #if !defined(os_aix) && !defined(os_windows)
01498     linkedFile->getDependencies(deps_);
01499 #endif
01500 
01501 #if defined (os_aix)
01502     //  These should go away
01503     linkedFile->get_stab_info(stabstr_, nstabs_, stabs_, stringpool_);
01504     linkedFile->get_line_info(nlines_, lines_, fdptr_);
01505 #endif
01506 
01507 #if defined(os_aix) || defined(os_linux) || defined(os_freebsd)
01508     // make sure we're using the right demangler
01509     
01510     nativeCompiler = parseCompilerType(linkedFile);
01511     //parsing_printf("isNativeCompiler: %d\n", nativeCompiler);
01512 #endif
01513     
01514     // define all of the functions
01515     //statusLine("winnowing functions");
01516 
01517     // a vector to hold all created symbols until they are properly classified
01518     std::vector<Symbol *> raw_syms;
01519 
01520 #ifdef BINEDIT_DEBUG
01521     printf("== from linkedFile...\n");
01522     print_symbol_map(linkedFile->getAllSymbols());
01523 #endif
01524 
01525     if (!extractSymbolsFromFile(linkedFile, raw_syms)) 
01526     {
01527         serr = Syms_To_Functions;
01528         return false;
01529     }
01530 
01531     // don't sort the symbols--preserve the original ordering
01532     //sort(raw_syms.begin(),raw_syms.end(),symbol_compare);
01533 
01534     createDefaultModule();
01535 
01536     if (!fixSymModules(raw_syms)) 
01537     {
01538         serr = Syms_To_Functions;
01539         return false;
01540     }
01541     Object *obj = getObject();
01542     if (!obj)
01543     {
01544 #if !defined(os_vxworks)
01545         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
01546 #endif
01547         return false;
01548     }
01549     obj->clearSymsToMods();
01550 
01551     // wait until all modules are defined before applying languages to
01552     // them we want to do it this way so that module information comes
01553     // from the function symbols, first and foremost, to avoid any
01554     // internal module-function mismatching.
01555             
01556     // get Information on the language each modules is written in
01557     // (prior to making modules)
01558 
01559     dyn_hash_map<std::string, supportedLanguages> mod_langs;
01560     linkedFile->getModuleLanguageInfo(&mod_langs);
01561     setModuleLanguages(&mod_langs);
01562     
01563     // Be sure that module languages are set before demangling, or
01564     // we won't get very far.
01565 
01566     if (!demangleSymbols(raw_syms)) 
01567     {
01568         serr = Syms_To_Functions;
01569         return false;
01570     }
01571     
01572     if (!demangleSymbols(undefDynSyms)) {
01573        serr = Syms_To_Functions;
01574        return false;
01575     }
01576 
01577     if (!createIndices(raw_syms, false)) 
01578     {
01579         serr = Syms_To_Functions;
01580         return false;
01581     }
01582 
01583     if (!createIndices(undefDynSyms, true)) 
01584     {
01585         serr = Syms_To_Functions;
01586         return false;
01587     }
01588 
01589     if (!createAggregates()) 
01590     {
01591         serr = Syms_To_Functions;
01592         return false;
01593     }
01594     
01595     // Once languages are assigned, we can build demangled names (in
01596     // the wider sense of demangling which includes stripping _'s from
01597     // fortran names -- this is why language information must be
01598     // determined before this step).
01599     
01600     // Also identifies aliases (multiple names with equal addresses)
01601     
01602     //addSymtabVariables();
01603     linkedFile->getAllExceptions(excpBlocks);
01604 
01605     vector<relocationEntry >fbt;
01606     linkedFile->get_func_binding_table(fbt);
01607     for(unsigned i=0; i<fbt.size();i++)
01608         relocation_table_.push_back(fbt[i]);
01609     return true;
01610 }
01611 
01612 Symtab::Symtab(const Symtab& obj) :
01613    LookupInterface(),
01614    Serializable(),
01615    AnnotatableSparse(),
01616    _ref_cnt(1)
01617 {
01618     create_printf("%s[%d]: Creating symtab 0x%p from symtab 0x%p\n", FILE__, __LINE__, this, &obj);
01619   
01620     member_name_ = obj.member_name_;
01621     member_offset_ = obj.member_offset_;
01622     imageOffset_ = obj.imageOffset_;
01623     imageLen_ = obj.imageLen_;
01624     dataOffset_ = obj.dataOffset_;
01625     dataLen_ = obj.dataLen_;
01626     isDefensiveBinary_ = obj.isDefensiveBinary_;
01627 
01628    isLineInfoValid_ = obj.isLineInfoValid_;
01629    isTypeInfoValid_ = obj.isTypeInfoValid_;
01630 
01631    is_a_out = obj.is_a_out;
01632    main_call_addr_ = obj.main_call_addr_; // address of call to main()
01633 
01634    nativeCompiler = obj.nativeCompiler;
01635    defaultNamespacePrefix = obj.defaultNamespacePrefix;
01636 
01637    //sections
01638    no_of_sections = obj.no_of_sections;
01639    unsigned i;
01640 
01641    for (i=0;i<obj.regions_.size();i++) {
01642      regions_.push_back(new Region(*(obj.regions_[i])));
01643      regions_.back()->setSymtab(this);
01644    }
01645 
01646    for (i=0;i<regions_.size();i++)
01647       regionsByEntryAddr[regions_[i]->getMemOffset()] = regions_[i];
01648 
01649    // TODO FIXME: copying symbols/Functions/Variables
01650 
01651    for (i=0;i<obj._mods.size();i++)
01652    {
01653       Module *m = new Module(*(obj._mods[i]));
01654       _mods.push_back(m);
01655       modsByFileName[m->fileName()] = m;
01656       modsByFullName[m->fullName()] = m;
01657       fprintf(stderr, "%s[%d]:  copy ctor creating new module %s\n", 
01658             FILE__, __LINE__, m->fileName().c_str());
01659    }
01660 
01661    for (i=0; i<relocation_table_.size();i++) 
01662    {
01663       relocation_table_.push_back(relocationEntry(obj.relocation_table_[i]));
01664    }
01665 
01666    for (i=0;i<excpBlocks.size();i++)
01667    {
01668       excpBlocks.push_back(new ExceptionBlock(*(obj.excpBlocks[i])));
01669    }
01670 
01671    deps_ = obj.deps_;
01672 }
01673 
01674 // Address must be in code or data range since some code may end up
01675 // in the data segment
01676 bool Symtab::isValidOffset(const Offset where) const
01677 {
01678    return isCode(where) || isData(where);
01679 }
01680 
01681 /* Performs a binary search on the codeRegions_ vector, which must
01682  * be kept in sorted order
01683  */
01684 bool Symtab::isCode(const Offset where)  const
01685 {
01686 #if defined(os_vxworks)
01687     // All memory is valid in the kernel.  Kinda.
01688     //return true;
01689 #endif
01690 
01691    if (!codeRegions_.size()) 
01692    {
01693       fprintf(stderr, "%s[%d] No code regions in %s \n",
01694             __FILE__, __LINE__, mf->filename().c_str());
01695       return false;
01696    }
01697 
01698    // search for "where" in codeRegions_ (code regions must not overlap)
01699    int first = 0; 
01700    int last = codeRegions_.size() - 1;
01701 
01702    while (last >= first) 
01703    {
01704       Region *curreg = codeRegions_[(first + last) / 2];
01705       if (where >= curreg->getMemOffset()
01706             && where < (curreg->getMemOffset()
01707                + curreg->getMemSize())) 
01708       {
01709          if (curreg->getRegionType() == Region::RT_BSS)
01710             return false;
01711          return true;
01712       }
01713       else if (where < curreg->getMemOffset()) 
01714       {
01715          last = ((first + last) / 2) - 1;
01716       }
01717       else if (where >= (curreg->getMemOffset() + curreg->getMemSize()))
01718       {
01719          first = ((first + last) / 2) + 1;
01720       }
01721       else 
01722       {  // "where" is in the range: 
01723          // [memOffset + diskSize , memOffset + memSize)
01724          // meaning that it's in an uninitialized data region 
01725          return false;
01726       }
01727    }
01728 
01729    return false;
01730 }
01731 
01732 /* Performs a binary search on the dataRegions_ vector, which must
01733  * be kept in sorted order */
01734 bool Symtab::isData(const Offset where)  const
01735 {
01736    if (!dataRegions_.size()) 
01737    {
01738       fprintf(stderr, "%s[%d] No data regions in %s \n",
01739             __FILE__,__LINE__,mf->filename().c_str());
01740       return false;
01741    }
01742 
01743    int first = 0; 
01744    int last = dataRegions_.size() - 1;
01745 
01746    while (last >= first) 
01747    {
01748       Region *curreg = dataRegions_[(first + last) / 2];
01749 
01750       if (     (where >= curreg->getMemOffset())
01751             && (where < (curreg->getMemOffset() + curreg->getMemSize())))
01752       {
01753          return true;
01754       }
01755       else if (where < curreg->getMemOffset()) 
01756       {
01757          last = ((first + last) / 2) - 1;
01758       }
01759       else 
01760       {
01761          first = ((first + last) / 2) + 1;
01762       }
01763    }
01764 
01765    return false;
01766 }
01767 
01768 SYMTAB_EXPORT bool Symtab::getFuncBindingTable(std::vector<relocationEntry> &fbt) const
01769 {
01770    fbt = relocation_table_;
01771    return true;
01772 }
01773 
01774 SYMTAB_EXPORT bool Symtab::updateFuncBindingTable(Offset stub_addr, Offset plt_addr)
01775 {
01776     int stub_idx = -1, plt_idx = -1;
01777 
01778     for (unsigned i = 0; i < relocation_table_.size(); ++i) {
01779         if (stub_addr == relocation_table_[i].target_addr())
01780             stub_idx = i;
01781         if (plt_addr  == relocation_table_[i].target_addr())
01782             plt_idx = i;
01783         if (stub_idx >= 0 && plt_idx >= 0)
01784             break;
01785     }
01786     if (stub_idx >= 0 && plt_idx >= 0) {
01787         relocation_table_[stub_idx] = relocation_table_[plt_idx];
01788         relocation_table_[stub_idx].setTargetAddr(stub_addr);
01789         return true;
01790     }
01791     return false;
01792 }
01793 
01794 SYMTAB_EXPORT std::vector<std::string> &Symtab::getDependencies(){
01795     return deps_;
01796 }
01797 
01798 SYMTAB_EXPORT Archive *Symtab::getParentArchive() const {
01799     return parentArchive_;
01800 }
01801 
01802 Symtab::~Symtab()
01803 {
01804    // Doesn't do anything yet, moved here so we don't mess with symtab.h
01805    // Only called if we fail to create a process.
01806    // Or delete the a.out...
01807 
01808 #if 1 
01809 
01810    for (unsigned i = 0; i < regions_.size(); i++) 
01811    {
01812       delete regions_[i];
01813    }
01814 
01815    regions_.clear();
01816    codeRegions_.clear();
01817    dataRegions_.clear();
01818    regionsByEntryAddr.clear();
01819 
01820    std::vector<Region *> *user_regions = NULL;
01821    getAnnotation(user_regions, UserRegionsAnno);
01822 
01823    if (user_regions)
01824    {
01825       for (unsigned i = 0; i < user_regions->size(); ++i) 
01826          delete (*user_regions)[i];
01827       user_regions->clear();
01828    }
01829 
01830    // Symbols are copied from linkedFile, and NOT deleted
01831    everyDefinedSymbol.clear();
01832    undefDynSyms.clear();
01833    undefDynSymsByMangledName.clear();
01834    undefDynSymsByPrettyName.clear();
01835    undefDynSymsByTypedName.clear();
01836 
01837    // TODO make annotation
01838    symsByOffset.clear();
01839    symsByMangledName.clear();
01840    symsByPrettyName.clear();
01841    symsByTypedName.clear();
01842 
01843    for (unsigned i = 0; i < everyFunction.size(); i++) 
01844    {
01845       delete everyFunction[i];
01846    }
01847 
01848    everyFunction.clear();
01849    funcsByOffset.clear();
01850 
01851    for (unsigned i = 0; i < everyVariable.size(); i++) 
01852    {
01853       delete everyVariable[i];
01854    }
01855 
01856    everyVariable.clear();
01857    varsByOffset.clear();
01858 
01859    for (unsigned i = 0; i < _mods.size(); i++) 
01860    {
01861       delete _mods[i];
01862    }
01863    _mods.clear();
01864    modsByFileName.clear();
01865    modsByFullName.clear();
01866 
01867    for (unsigned i=0;i<excpBlocks.size();i++)
01868       delete excpBlocks[i];
01869 
01870    create_printf("%s[%d]: Symtab::~Symtab removing %p from allSymtabs\n", 
01871          FILE__, __LINE__, this);
01872 
01873    deps_.clear();
01874 
01875    for (unsigned i = 0; i < allSymtabs.size(); i++) 
01876    {
01877       if (allSymtabs[i] == this)
01878          allSymtabs.erase(allSymtabs.begin()+i);
01879    }
01880 
01881    // Make sure to free the underlying Object as it doesn't have a factory
01882    // open method
01883    if( obj_private ) delete obj_private;
01884 
01885    //fprintf(stderr, "%s[%d]:  symtab DTOR, mf = %p: %s\n", FILE__, __LINE__, mf, mf->filename().c_str());
01886    if (mf) MappedFile::closeMappedFile(mf);
01887 #endif
01888 }   
01889 
01890 #if !defined(SERIALIZATION_DISABLED)
01891 bool Symtab::exportXML(string file)
01892 {
01893 #if defined (cap_serialization)
01894    try 
01895    {
01896        SerContext<Symtab> *scs = new SerContext<Symtab>(this, file);
01897        serialize(file, scs, ser_xml);
01898 #if 0
01899        SerContext<Symtab> *scs = new SerContext<Symtab>(this);
01900        SerializerXML *ser = new SerializerXML(scs, "XMLTranslator", file, sd_serialize, true);
01901        serialize(ser, "Symtab");
01902 #endif
01903 #if 0
01904       SerializerXML sb("XMLTranslator", file, sd_serialize, true);
01905       serialize(&sb, "Symtab");
01906 #endif
01907    } 
01908    catch (const SerializerError &err) 
01909    {
01910       fprintf(stderr, "%s[%d]: error serializing xml: %s\n", FILE__, __LINE__, err.what());
01911       return false;
01912    }
01913 
01914    return false;
01915 #else
01916    fprintf(stderr, "%s[%d]:  WARNING:  cannot produce %s, serialization not available\n", FILE__, __LINE__, file.c_str());
01917    return false;
01918 #endif
01919 }
01920 
01921 bool Symtab::exportBin(string file)
01922 {
01923    try
01924    {
01925        SerContext<Symtab> *scs = new SerContext<Symtab>(this, file);
01926        serialize(file, scs, ser_bin);
01927        //fprintf(stderr, "%s[%d]:  did serialize\n", FILE__, __LINE__);
01928        return true;
01929    }
01930 
01931    catch (const SerializerError &err)
01932    {
01933       if (err.code() == SerializerError::ser_err_disabled) 
01934       {
01935          fprintf(stderr, "%s[%d]:  WARN:  serialization is disabled for file %s\n",
01936                FILE__, __LINE__, file.c_str());
01937          return false;
01938       }
01939 
01940       fprintf(stderr, "%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
01941             err.what(), err.file().c_str(), err.line());
01942    }
01943 
01944    fprintf(stderr, "%s[%d]:  error doing binary serialization\n", __FILE__, __LINE__);
01945    return false;
01946 }
01947 
01948 Symtab *Symtab::importBin(std::string file)
01949 {
01950 #if defined (cap_serialization)
01951    MappedFile *mf= MappedFile::createMappedFile(file);
01952    if (!mf) 
01953    {
01954       fprintf(stderr, "%s[%d]:  failed to map file %s\n", FILE__, __LINE__, file.c_str());
01955       return NULL;
01956    }
01957 
01958    Symtab *st = new Symtab(mf);
01959 
01960    try
01961    {
01962        SerContext<Symtab> *scs = new SerContext<Symtab>(st, file);
01963        if (!st->deserialize(file, scs))
01964        {
01965            delete st;
01966            return NULL;
01967        }
01968 
01969        return st;
01970    }
01971 
01972    catch (const SerializerError &err)
01973    {
01974       if (err.code() == SerializerError::ser_err_disabled) 
01975       {
01976          serialize_printf("%s[%d]:  WARN:  serialization is disabled for file %s\n",
01977                FILE__, __LINE__, file.c_str());
01978          fprintf(stderr, "%s[%d]:  WARN:  serialization is disabled for file %s\n",
01979                FILE__, __LINE__, file.c_str());
01980          return NULL;
01981       }
01982 
01983       serialize_printf("%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
01984             err.what(), err.file().c_str(), err.line());
01985       fprintf(stderr, "%s[%d]: %s\n\tfrom: %s[%d]\n", FILE__, __LINE__,
01986             err.what(), err.file().c_str(), err.line());
01987    }
01988 
01989 
01990    serialize_printf("%s[%d]:  error doing binary deserialization\n", __FILE__, __LINE__);
01991    delete st;
01992    return NULL;
01993 #else
01994    serialize_printf("%s[%d]:  WARNING:  cannot produce %s, serialization not available\n", FILE__, __LINE__, file.c_str());
01995    return NULL;
01996 #endif
01997 }
01998 
01999 #else
02000 bool Symtab::exportXML(string)
02001 {
02002    return false;
02003 }
02004 
02005 bool Symtab::exportBin(string) 
02006 {
02007    return false;
02008 }
02009 
02010 Symtab *Symtab::importBin(std::string)
02011 {
02012    return NULL;
02013 }
02014 #endif
02015 
02016 bool Symtab::openFile(Symtab *&obj, void *mem_image, size_t size, 
02017                       std::string name, def_t def_bin)
02018 {
02019    bool err = false;
02020 #if defined(TIMED_PARSE)
02021    struct timeval starttime;
02022    gettimeofday(&starttime, NULL);
02023 #endif
02024 
02025    obj = new Symtab((unsigned char *) mem_image, size, name, (def_bin == Defensive), err);
02026 
02027 #if defined(TIMED_PARSE)
02028     struct timeval endtime;
02029     gettimeofday(&endtime, NULL);
02030     unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
02031     unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
02032     unsigned long difftime = lendtime - lstarttime;
02033     double dursecs = difftime/(1000 );
02034     cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
02035 #endif
02036     if(!err)
02037     {
02038        allSymtabs.push_back(obj);
02039     }
02040     else
02041     {
02042         delete obj;
02043        obj = NULL;
02044     }
02045     // returns true on success (not an error)
02046     return !err;
02047 }
02048 
02049 bool Symtab::closeSymtab(Symtab *st)
02050 {
02051     bool found = false;
02052     if (!st) return false;
02053 
02054     --(st->_ref_cnt);
02055 
02056     std::vector<Symtab *>::reverse_iterator iter;
02057     for (iter = allSymtabs.rbegin(); iter != allSymtabs.rend() ; iter++)
02058     {
02059         if (*iter == st)
02060         {
02061             found = true;
02062             if(0 == st->_ref_cnt) {
02063                 allSymtabs.erase(iter.base() -1);
02064                 break;
02065             }
02066         }
02067     }
02068     if(0 == st->_ref_cnt)
02069         delete(st);
02070     return found;
02071 }
02072 
02073 Symtab *Symtab::findOpenSymtab(std::string filename)
02074 {
02075    unsigned numSymtabs = allSymtabs.size();
02076     for (unsigned u=0; u<numSymtabs; u++) 
02077     {
02078         assert(allSymtabs[u]);
02079         if (filename == allSymtabs[u]->file() && 
02080           allSymtabs[u]->mf->canBeShared()) 
02081         {
02082             allSymtabs[u]->_ref_cnt++;
02083             // return it
02084             return allSymtabs[u];
02085         }
02086     }   
02087     return NULL;
02088 }
02089 
02090 bool Symtab::openFile(Symtab *&obj, std::string filename, def_t def_binary)
02091 {
02092    bool err = false;
02093 #if defined(TIMED_PARSE)
02094    struct timeval starttime;
02095    gettimeofday(&starttime, NULL);
02096 #endif
02097 
02098    // AIX: it's possible that we're reparsing a file with better information
02099    // about it. If so, yank the old one out of the allSymtabs std::vector -- replace
02100    // it, basically.
02101    if ( filename.find("/proc") == std::string::npos)
02102    {
02103        obj = findOpenSymtab(filename);
02104        if (obj)
02105        {
02106            //fprintf(stderr, "%s[%d]:  have existing symtab obj for %s\n", FILE__, __LINE__, filename.c_str());
02107            return true;
02108    }
02109    }
02110 
02111 
02112 #if defined (cap_serialization)
02113 #if 0
02114    obj = importBin(filename);
02115 
02116    if (NULL == obj) 
02117    {
02118        if (deserializeEnforced<Symtab>(filename))
02119       {
02120               serialize_printf("%s[%d]: aborting new symtab, expected deserialize failed\n",
02121                       FILE__, __LINE__);
02122               fprintf(stderr, "%s[%d]: aborting new symtab, expected deserialize failed\n",
02123                       FILE__, __LINE__);
02124               return false;
02125       }
02126        //fprintf(stderr, "%s[%d]:  deserialize failed, but not enforced for %s\n", FILE__, __LINE__, filename.c_str());
02127    }
02128    else 
02129    {
02130       //fprintf(stderr, "%s[%d]:  deserialize success\n", FILE__, __LINE__);
02131       return true;
02132    }
02133 #endif
02134 #endif
02135 
02136    obj = new Symtab(filename, (def_binary == Defensive), err);
02137 
02138 #if defined(TIMED_PARSE)
02139    struct timeval endtime;
02140    gettimeofday(&endtime, NULL);
02141    unsigned long lstarttime = starttime.tv_sec * 1000 * 1000 + starttime.tv_usec;
02142    unsigned long lendtime = endtime.tv_sec * 1000 * 1000 + endtime.tv_usec;
02143    unsigned long difftime = lendtime - lstarttime;
02144    double dursecs = difftime/(1000 );
02145    cout << __FILE__ << ":" << __LINE__ <<": openFile "<< filename<< " took "<<dursecs <<" msecs" << endl;
02146 #endif
02147 
02148    if (!err)
02149    {
02150       if (filename.find("/proc") == std::string::npos)
02151          allSymtabs.push_back(obj);
02152 
02153 
02154 #if defined (cap_serialization)
02155 #if 0
02156       serialize_printf("%s[%d]:  doing bin-serialize for %s\n", 
02157             FILE__, __LINE__, filename.c_str());
02158 
02159       if (!obj->exportBin(filename))
02160       {
02161          serialize_printf("%s[%d]:  failed to export symtab\n", FILE__, __LINE__);
02162       }
02163       else
02164          serialize_printf("%s[%d]:  did bin-serialize for %s\n", 
02165                           FILE__, __LINE__, filename.c_str());
02166 #endif
02167 #endif
02168 
02169     }
02170     else
02171     {
02172        create_printf("%s[%d]: WARNING: failed to open symtab for %s\n", 
02173              FILE__, __LINE__, filename.c_str());
02174        delete obj;
02175        obj = NULL;
02176     }
02177 
02178    // returns true on success (not an error)
02179    return !err;
02180 }
02181 
02182 bool Symtab::addRegion(Offset vaddr, void *data, unsigned int dataSize, std::string name, 
02183         Region::RegionType rType_, bool loadable, unsigned long memAlign, bool tls)
02184 {
02185    Region *sec;
02186    unsigned i;
02187    if (loadable)
02188    {
02189       sec = new Region(newSectionInsertPoint, name, vaddr, dataSize, vaddr, 
02190             dataSize, (char *)data, Region::RP_R, rType_, true, tls, memAlign);
02191       sec->setSymtab(this);
02192 
02193       regions_.insert(regions_.begin()+newSectionInsertPoint, sec);
02194 
02195       for (i = newSectionInsertPoint+1; i < regions_.size(); i++)
02196       {
02197          regions_[i]->setRegionNumber(regions_[i]->getRegionNumber() + 1);
02198       }
02199 
02200       if (    (sec->getRegionType() == Region::RT_TEXT) 
02201             || (sec->getRegionType() == Region::RT_TEXTDATA))
02202       {
02203          codeRegions_.push_back(sec);
02204          std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
02205       }
02206 
02207       if (    (sec->getRegionType() == Region::RT_DATA) 
02208             || (sec->getRegionType() == Region::RT_TEXTDATA))
02209       {
02210          dataRegions_.push_back(sec);
02211          std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
02212       }
02213    }
02214    else
02215    {
02216       sec = new Region(regions_.size()+1, name, vaddr, dataSize, 0, 0, 
02217             (char *)data, Region::RP_R, rType_, loadable, tls, memAlign);
02218       sec->setSymtab(this);
02219       regions_.push_back(sec);
02220    }
02221 
02222    addUserRegion(sec);
02223    std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
02224    return true;
02225 }
02226 
02227 bool Symtab::addUserRegion(Region *reg)
02228 {
02229    std::vector<Region *> *user_regions = NULL;
02230 
02231    if (!getAnnotation(user_regions, UserRegionsAnno))
02232    {
02233       user_regions = new std::vector<Region *>();
02234       if (!addAnnotation(user_regions, UserRegionsAnno))
02235       {
02236          fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
02237          return false;
02238       }
02239    }
02240 
02241    if (!user_regions)
02242    {
02243       fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
02244       return false;
02245    }
02246 
02247    user_regions->push_back(reg);
02248 
02249    return true;
02250 }
02251 
02252 bool Symtab::addUserType(Type *t)
02253 {
02254    std::vector<Type *> *user_types = NULL;
02255 
02256    //  need to change this to something based on AnnotationContainer
02257    //  for it to work with serialization
02258    if (!getAnnotation(user_types, UserTypesAnno))
02259    {
02260       user_types = new std::vector<Type *>();
02261       if (!addAnnotation(user_types, UserTypesAnno))
02262       {
02263          fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
02264          return false;
02265       }
02266    }
02267    if (!user_types)
02268    {
02269       fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
02270       return false;
02271    }
02272 
02273    user_types->push_back(t);
02274 
02275    return true;
02276 }
02277 
02278 bool Symtab::addRegion(Region *sec)
02279 {
02280   regions_.push_back(sec);
02281   sec->setSymtab(this);
02282   std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
02283   addUserRegion(sec);
02284    return true;
02285 }
02286 
02287 void Symtab::parseLineInformation()
02288 {
02289    dyn_hash_map<std::string, LineInformation> *lineInfo = new dyn_hash_map <std::string, LineInformation>;
02290 
02291 
02292    Object *linkedFile = getObject();
02293     if (!linkedFile)
02294     {
02295 #if !defined(os_vxworks)
02296         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
02297 #endif
02298         return;
02299     }
02300    linkedFile->parseFileLineInfo(this, *lineInfo);
02301 
02302    isLineInfoValid_ = true; 
02303    dyn_hash_map <std::string, LineInformation>::iterator iter;
02304 
02305    for (iter = lineInfo->begin(); iter!=lineInfo->end(); iter++)
02306    {
02307       Module *mod = NULL;
02308       bool result = findModuleByName(mod, iter->first);
02309       if (!result) {
02310          mod = getDefaultModule();
02311       }
02312 
02313          LineInformation *lineInformation = mod->getLineInformation();
02314          if (!lineInformation) 
02315          {
02316             mod->setLineInfo(&(iter->second));
02317          } 
02318          else 
02319          {
02320             lineInformation->addLineInfo(&(iter->second));
02321             mod->setLineInfo(lineInformation);
02322          }
02323       }
02324 }
02325 
02326 SYMTAB_EXPORT bool Symtab::getAddressRanges(std::vector<pair<Offset, Offset> >&ranges,
02327       std::string lineSource, unsigned int lineNo)
02328 {
02329    unsigned int originalSize = ranges.size();
02330 
02331    /* Iteratate over the modules, looking for ranges in each. */
02332 
02333    for ( unsigned int i = 0; i < _mods.size(); i++ ) 
02334    {
02335       LineInformation *lineInformation = _mods[i]->getLineInformation();
02336 
02337       if (lineInformation)
02338          lineInformation->getAddressRanges( lineSource.c_str(), lineNo, ranges );
02339 
02340    } /* end iteration over modules */
02341 
02342    if ( ranges.size() != originalSize )
02343       return true;
02344 
02345    fprintf(stderr, "%s[%d]:  failing to getAdressRanges for %s[%d]\n", FILE__, __LINE__, lineSource.c_str(), lineNo);
02346    return false;
02347 }
02348 
02349 SYMTAB_EXPORT bool Symtab::getSourceLines(std::vector<Statement *> &lines, Offset addressInRange)
02350 {
02351    unsigned int originalSize = lines.size();
02352 
02353    /* Iteratate over the modules, looking for ranges in each. */
02354    for ( unsigned int i = 0; i < _mods.size(); i++ ) 
02355    {
02356       LineInformation *lineInformation = _mods[i]->getLineInformation();
02357 
02358       if (lineInformation)
02359          lineInformation->getSourceLines( addressInRange, lines );
02360 
02361    } /* end iteration over modules */
02362 
02363    if ( lines.size() != originalSize )
02364       return true;
02365 
02366    return false;
02367 
02368 }
02369 
02370 SYMTAB_EXPORT bool Symtab::getSourceLines(std::vector<LineNoTuple> &lines, Offset addressInRange)
02371 {
02372    unsigned int originalSize = lines.size();
02373    
02374    /* Iteratate over the modules, looking for ranges in each. */
02375    for ( unsigned int i = 0; i < _mods.size(); i++ ) 
02376    {
02377       LineInformation *lineInformation = _mods[i]->getLineInformation();
02378       
02379       if (lineInformation)
02380          lineInformation->getSourceLines( addressInRange, lines );
02381       
02382    } /* end iteration over modules */
02383    
02384    if ( lines.size() != originalSize )
02385       return true;
02386    
02387    return false;
02388 }
02389 
02390 SYMTAB_EXPORT bool Symtab::addLine(std::string lineSource, unsigned int lineNo,
02391       unsigned int lineOffset, Offset lowInclAddr,
02392       Offset highExclAddr)
02393 {
02394    Module *mod;
02395 
02396    if (!findModuleByName(mod, lineSource))
02397    {
02398       std::string fileNm = extract_pathname_tail(lineSource);
02399 
02400       if (!findModuleByName(mod, fileNm))
02401       {
02402          if (!findModuleByName(mod, mf->pathname()))
02403             return false;
02404       }    
02405    }
02406 
02407    LineInformation *lineInfo = mod->getLineInformation();
02408 
02409    if (!lineInfo)
02410       return false;
02411 
02412    return (lineInfo->addLine(lineSource.c_str(), lineNo, lineOffset, 
02413             lowInclAddr, highExclAddr));
02414 }
02415 
02416 SYMTAB_EXPORT bool Symtab::addAddressRange( Offset lowInclusiveAddr, Offset highExclusiveAddr,
02417       std::string lineSource, unsigned int lineNo,
02418       unsigned int lineOffset)
02419 {
02420    Module *mod;
02421 
02422    if (!findModuleByName(mod, lineSource))
02423    {
02424       std::string fileNm = extract_pathname_tail(lineSource);
02425 
02426       if (!findModuleByName(mod, fileNm))
02427          return false;
02428    }
02429 
02430    LineInformation *lineInfo = mod->getLineInformation();
02431 
02432    if (!lineInfo)
02433       return false;
02434 
02435    return (lineInfo->addAddressRange(lowInclusiveAddr, highExclusiveAddr, 
02436             lineSource.c_str(), lineNo, lineOffset));
02437 }
02438 
02439 void Symtab::setTruncateLinePaths(bool value)
02440 {
02441    getObject()->setTruncateLinePaths(value);
02442 }
02443 
02444 bool Symtab::getTruncateLinePaths()
02445 {
02446    return getObject()->getTruncateLinePaths();
02447 }
02448 
02449 void Symtab::parseTypes()
02450 {
02451    Object *linkedFile = getObject();
02452     if (!linkedFile)
02453     {
02454 #if !defined(os_vxworks)
02455         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
02456 #endif
02457         return;
02458     }
02459    linkedFile->parseTypeInfo(this);
02460    isTypeInfoValid_ = true;
02461 
02462    for (unsigned int i = 0; i < _mods.size(); ++i)
02463    {
02464        typeCollection *tc = typeCollection::getModTypeCollection(_mods[i]);
02465 
02466        if (!_mods[i]->addAnnotation(tc, ModuleTypeInfoAnno))
02467        {
02468            fprintf(stderr, "%s[%d]:  failed to addAnnotation here\n", FILE__, __LINE__);
02469        }
02470    }
02471 
02472    //  optionally we might want to clear the static data struct in typeCollection
02473    //  here....  the parsing is over, and we have added all typeCollections as
02474    //  annotations proper.
02475 
02476    typeCollection::fileToTypesMap.clear();
02477 
02478 }
02479 
02480 bool Symtab::addType(Type *type)
02481 {
02482   bool result = addUserType(type);
02483   if (!result)
02484     return false;
02485 
02486   return true;
02487 }
02488 
02489 SYMTAB_EXPORT vector<Type *> *Symtab::getAllstdTypes()
02490 {
02491    return stdTypes()->getAllTypes();    
02492 }
02493 
02494 SYMTAB_EXPORT vector<Type *> *Symtab::getAllbuiltInTypes()
02495 {
02496    return builtInTypes()->getAllBuiltInTypes();
02497 }
02498 
02499 SYMTAB_EXPORT bool Symtab::findType(Type *&type, std::string name)
02500 {
02501    parseTypesNow();
02502 
02503    if (!_mods.size())
02504       return false;
02505 
02506    for (unsigned int i = 0; i < _mods.size(); ++i)
02507    {
02508        typeCollection *tc = _mods[i]->getModuleTypes();
02509        if (!tc) continue;
02510        type = tc->findType(name);
02511        if (type) return true;
02512    }
02513 
02514    if (type == NULL)
02515       return false;
02516 
02517    return true; 
02518 }
02519 
02520 SYMTAB_EXPORT Type *Symtab::findType(unsigned type_id)
02521 {
02522     Type *t = NULL;
02523    parseTypesNow();
02524 
02525    if (!_mods.size())
02526    {
02527        //fprintf(stderr, "%s[%d]:  findType failing due to lack of modules\n", FILE__, __LINE__);
02528       return NULL;
02529    }
02530 
02531    for (unsigned int i = 0; i < _mods.size(); ++i)
02532    {
02533        typeCollection *tc = _mods[i]->getModuleTypes();
02534        if (!tc) continue;
02535        t = tc->findType(type_id);
02536        if (t)  break;
02537    }
02538 
02539    if (t == NULL)
02540    {
02541        if (builtInTypes())
02542        {
02543            t = builtInTypes()->findBuiltInType(type_id);
02544            if (t) return t;
02545        }
02546        else
02547        {
02548            //fprintf(stderr, "%s[%d]:  no built in types!\n", FILE__, __LINE__);
02549        }
02550 
02551        if (stdTypes())
02552        {
02553            t = stdTypes()->findType(type_id);
02554            if (t) return t;
02555        }
02556        else
02557        {
02558            //fprintf(stderr, "%s[%d]:  no std types!\n", FILE__, __LINE__);
02559        }
02560 
02561        return NULL;
02562    }
02563 
02564    return t;    
02565 }
02566 
02567 SYMTAB_EXPORT bool Symtab::findVariableType(Type *&type, std::string name)
02568 {
02569    parseTypesNow();
02570 
02571    if (!_mods.size())
02572       return false;
02573 
02574 
02575    for (unsigned int i = 0; i < _mods.size(); ++i)
02576    {
02577        typeCollection *tc = _mods[i]->getModuleTypes();
02578        if (!tc) continue;
02579        type = tc->findVariableType(name);
02580        if (type) break;
02581    }
02582 
02583    if (type == NULL)
02584       return false;
02585 
02586    return true; 
02587 }
02588 
02589 SYMTAB_EXPORT bool Symtab::findLocalVariable(std::vector<localVar *>&vars, std::string name)
02590 {
02591    parseTypesNow();
02592    unsigned origSize = vars.size();
02593 
02594    for (unsigned i = 0; i < everyFunction.size(); i++)
02595    {
02596       everyFunction[i]->findLocalVariable(vars, name);
02597    }
02598 
02599    if (vars.size()>origSize)
02600       return true;
02601 
02602    return false;    
02603 }
02604 
02605 SYMTAB_EXPORT bool Symtab::hasRel() const
02606 {
02607    return hasRel_;
02608 }
02609 
02610 SYMTAB_EXPORT bool Symtab::hasRela() const
02611 {
02612    return hasRela_;
02613 }
02614 
02615 SYMTAB_EXPORT bool Symtab::hasReldyn() const
02616 {
02617    return hasReldyn_;
02618 }
02619 
02620 SYMTAB_EXPORT bool Symtab::hasReladyn() const
02621 {
02622    return hasReladyn_;
02623 }
02624 
02625 SYMTAB_EXPORT bool Symtab::hasRelplt() const
02626 {
02627    return hasRelplt_;
02628 }
02629 
02630 SYMTAB_EXPORT bool Symtab::hasRelaplt() const
02631 {
02632    return hasRelaplt_;
02633 }
02634 
02635 SYMTAB_EXPORT bool Symtab::isStaticBinary() const
02636 {
02637    return isStaticBinary_;
02638 }
02639 
02640 bool Symtab::setDefaultNamespacePrefix(string &str)
02641 {
02642    defaultNamespacePrefix = str;
02643    return true;
02644 }
02645 
02646 SYMTAB_EXPORT bool Symtab::emitSymbols(Object *linkedFile,std::string filename, unsigned flag)
02647 {
02648     // Start with all the defined symbols
02649     std::vector<Symbol *> allSyms;
02650     allSyms.insert(allSyms.end(), everyDefinedSymbol.begin(), everyDefinedSymbol.end());
02651 
02652     // Add the undefined dynamic symbols
02653     map<string, std::vector<Symbol *> >::iterator iter;
02654     std::vector<Symbol *>::iterator siter;
02655 
02656     allSyms.insert(allSyms.end(), undefDynSyms.begin(), undefDynSyms.end());
02657 
02658     // Write the new file
02659     return linkedFile->emitDriver(this, filename, allSyms, flag);
02660 }
02661 
02662 SYMTAB_EXPORT bool Symtab::emit(std::string filename, unsigned flag)
02663 {
02664     Object *obj = getObject();
02665     if (!obj)
02666     {
02667 #if !defined(os_vxworks)
02668         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
02669 #endif
02670         return false;
02671     }
02672    obj->mf->setSharing(false);
02673    return emitSymbols(obj, filename, flag);
02674 }
02675 
02676 SYMTAB_EXPORT void Symtab::addDynLibSubstitution(std::string oldName, std::string newName)
02677 {
02678    dynLibSubs[oldName] = newName;
02679 }
02680 
02681 SYMTAB_EXPORT std::string Symtab::getDynLibSubstitution(std::string name)
02682 {
02683 #ifdef BINEDIT_DEBUG
02684    map<std::string, std::string>::iterator iter = dynLibSubs.begin();
02685 
02686    printf ("substitutions for %s:\n", mf->filename().c_str());
02687 
02688    while (iter != dynLibSubs.end()) 
02689    {
02690       printf("  \"%s\" => \"%s\"\n", iter->first.c_str(), iter->second.c_str());
02691       iter++;
02692    }
02693 #endif
02694 
02695    map<std::string, std::string>::iterator loc = dynLibSubs.find(name);
02696 
02697    if (loc == dynLibSubs.end())
02698       return name;
02699    else
02700       return loc->second;
02701 }
02702 
02703 SYMTAB_EXPORT bool Symtab::getSegments(vector<Segment> &segs) const
02704 {
02705    segs = segments_;
02706 
02707    if (!segments_.size()) 
02708       return false;
02709 
02710    return true;
02711 }
02712 
02713 SYMTAB_EXPORT bool Symtab::getMappedRegions(std::vector<Region *> &mappedRegs) const
02714 {
02715    unsigned origSize = mappedRegs.size();
02716 
02717    for (unsigned i = 0; i < regions_.size(); i++)
02718    {
02719       if (regions_[i]->isLoadable())
02720          mappedRegs.push_back(regions_[i]);
02721    }
02722 
02723    if (mappedRegs.size() > origSize)
02724       return true;
02725 
02726    return false;
02727 }
02728 
02729 SYMTAB_EXPORT bool Symtab::fixup_RegionAddr(const char* name, Offset memOffset, long memSize)
02730 {
02731     Region *sec;
02732 
02733     if (!findRegion(sec, name)) {
02734         return false;
02735     }
02736 
02737     vector<relocationEntry> relocs;
02738     Object *obj = getObject();
02739 
02740     // Fix relocation table with correct memory address
02741     if (obj) {
02742         obj->get_func_binding_table(relocs);
02743         /* DEBUG
02744         fprintf(stderr, "There are %d relocs in this symtab.\n",
02745                 relocs.size()); // */
02746 
02747         for (unsigned i=0; i < relocs.size(); i++) {
02748             Offset value = relocs[i].rel_addr();
02749             relocs[i].setRelAddr(memOffset + value);
02750             /* DEBUG
02751             fprintf(stderr, "Fixing reloc from 0x%x to 0x%x\n",
02752                     value, memOffset + value); // */
02753         }
02754     }
02755     relocation_table_ = relocs;
02756 
02757     vector<relocationEntry> &relref = sec->getRelocations();
02758     for (unsigned i=0; i < relref.size(); i++) {
02759         Offset value = relref[i].rel_addr();
02760         relref[i].setRelAddr(memOffset + value);
02761         /* DEBUG
02762         fprintf(stderr, "Fixing region reloc from 0x%x to 0x%x\n",
02763                 value, memOffset + value); // */
02764     }
02765 
02766 #if defined(_MSC_VER)
02767     regionsByEntryAddr.erase(sec->getMemOffset());
02768 #endif
02769 
02770     /* DEBUG
02771     fprintf(stderr, "Fixing region %s from 0x%x [0x%x] to 0x%x [0x%x]\n",
02772             name, sec->getMemOffset(), sec->getMemSize(), memOffset,
02773             memSize); // */
02774     sec->setMemOffset(memOffset);
02775     sec->setMemSize(memSize);
02776 
02777 #if defined(_MSC_VER)
02778     regionsByEntryAddr[sec->getMemOffset()] = sec;
02779 #endif
02780 
02781     std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
02782     std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
02783     std::sort(regions_.begin(), regions_.end(), sort_reg_by_addr);
02784     return true;
02785 }
02786 
02787 SYMTAB_EXPORT bool Symtab::fixup_SymbolAddr(const char* name, Offset newOffset)
02788 {
02789     // Find the symbol.
02790     if (symsByMangledName.count(name) == 0) return false;
02791     // /* DEBUG
02792     if (symsByMangledName[name].size() != 1)
02793         fprintf(stderr, "*** Found %zu symbols with name %s.  Expecting 1.\n",
02794                 symsByMangledName[name].size(), name); // */
02795     Symbol *sym = symsByMangledName[name][0];
02796 
02797     // Update symbol.
02798     Offset oldOffset = sym->getOffset();
02799     sym->setOffset(newOffset);
02800 
02801     /* DEBUG
02802     fprintf(stderr, "Fixing symbol %s from 0x%x to 0x%x\n",
02803             name, oldOffset, newOffset); // */
02804 
02805     // Update hashes.
02806     if (symsByOffset.count(oldOffset)) {
02807         std::vector<Symbol *>::iterator iter = symsByOffset[oldOffset].begin();
02808         while (iter != symsByOffset[oldOffset].end()) {
02809             if (*iter == sym) {
02810                 symsByOffset[oldOffset].erase(iter);
02811                 iter = symsByOffset[oldOffset].begin();
02812 
02813             } else iter++;
02814         }
02815     }
02816     if (!findSymbolByOffset(newOffset))
02817         symsByOffset[newOffset].push_back(sym);
02818 
02819     // Update aggregates.
02820     if (!doNotAggregate(sym)) {
02821       addSymbolToAggregates(sym);
02822     }
02823 
02824     return true;
02825 }
02826 
02827 SYMTAB_EXPORT bool Symtab::updateRegion(const char* name, void *buffer, unsigned size)
02828 {
02829    Region *sec;
02830 
02831    if (!findRegion(sec, name))
02832       return false;
02833 
02834    sec->setPtrToRawData(buffer, size);
02835 
02836    return true;
02837 }
02838 
02839 SYMTAB_EXPORT bool Symtab::updateCode(void *buffer, unsigned size)
02840 {
02841   return updateRegion(".text", buffer, size);
02842 }
02843 
02844 SYMTAB_EXPORT bool Symtab::updateData(void *buffer, unsigned size)
02845 {
02846   return updateRegion(".data", buffer, size);
02847 }
02848 
02849 SYMTAB_EXPORT Offset Symtab::getFreeOffset(unsigned size) 
02850 {
02851    // Look through sections until we find a gap with
02852    // sufficient space.
02853    Offset highWaterMark = 0;
02854    Offset secoffset = 0;
02855    Offset prevSecoffset = 0;
02856    Object *linkedFile = getObject();
02857    if (!linkedFile)
02858      {
02859 #if !defined(os_vxworks)
02860        fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
02861 #endif
02862        return 0;
02863      }
02864    
02865    for (unsigned i = 0; i < regions_.size(); i++) 
02866    {
02867       Offset end = regions_[i]->getMemOffset() + regions_[i]->getMemSize();
02868       if (regions_[i]->getMemOffset() == 0) 
02869          continue;
02870 
02871       prevSecoffset = secoffset;
02872 
02873       unsigned region_offset = (unsigned)((char *)(regions_[i]->getPtrToRawData())
02874                                           - linkedFile->mem_image());
02875 
02876       if (region_offset < (unsigned)prevSecoffset)
02877       {
02878          secoffset += regions_[i]->getMemSize();
02879       }
02880       else 
02881       {
02882          secoffset = (char *)(regions_[i]->getPtrToRawData()) - linkedFile->mem_image();
02883          secoffset += regions_[i]->getMemSize();
02884       }
02885 
02886       /*fprintf(stderr, "%d: secAddr 0x%lx, size %d, end 0x%lx, looking for %d\n",
02887         i, regions_[i]->getRegionAddr(), regions_[i]->getRegionSize(),
02888         end,size);*/
02889 
02890       if (end > highWaterMark) 
02891       {
02892          //fprintf(stderr, "Increasing highWaterMark...\n");
02893          newSectionInsertPoint = i+1;
02894          highWaterMark = end;
02895       }
02896 
02897       if (     (i < (regions_.size()-2)) 
02898                && ((end + size) < regions_[i+1]->getMemOffset())) 
02899       {
02900          /*      fprintf(stderr, "Found a hole between sections %d and %d\n",
02901                  i, i+1);
02902                  fprintf(stderr, "End at 0x%lx, next one at 0x%lx\n",
02903                  end, regions_[i+1]->getRegionAddr());
02904          */   
02905          newSectionInsertPoint = i+1;
02906          highWaterMark = end;
02907          break;
02908       }
02909    }
02910 
02911    //   return highWaterMark;
02912 #if defined (os_windows)
02913     Object *obj = getObject();
02914     if (!obj)
02915     {
02916         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
02917         return 0;
02918     }
02919     unsigned pgSize = obj->getSecAlign();
02920     //printf("pgSize:0x%x\n", pgSize);
02921     Offset newaddr = highWaterMark  - (highWaterMark & (pgSize-1));
02922     while(newaddr < highWaterMark)
02923       newaddr += pgSize;
02924     //printf("getfreeoffset:%lu\n", newaddr);
02925     return newaddr;
02926 
02927 #else
02928     unsigned pgSize = P_getpagesize();
02929 
02930 #if defined(os_linux)
02931         // Bluegene compute nodes have a 1MB alignment restructions on PT_LOAD section
02932     Object *obj = getObject();
02933     if (!obj)
02934     {
02935         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
02936         return 0;
02937     }
02938     bool isBlueGeneQ = obj->isBlueGeneQ();
02939     bool isBlueGeneP = obj->isBlueGeneP();
02940     bool hasNoteSection = obj->hasNoteSection();
02941     bool isStaticBinary = obj->isStaticBinary();
02942     /* In BlueGeneQ static binary, we extend the existing LOAD section to add Dyninst code and data
02943         In BlueGeneQ dynamic binary, we add a new LOAD section
02944        In BlueGeneP, we replace NOTE section with new LOAD section, else we extend existing LOAD section
02945         If we add a new LOAD section in BlueGene, it needs to be aligned to 1MB
02946     */
02947     if ((isBlueGeneQ && !isStaticBinary) || (isBlueGeneP && hasNoteSection)) {
02948         pgSize = 0x100000; 
02949     } else if( isBlueGeneQ && isStaticBinary ) {
02950     /* UGLY:: The maximum offset from TOC pointer is 0x7fff (15 bits + 1 sign bit).
02951        For static binaries, the TOC pointer must be able to reach the new load segment.
02952         If we align by page size (1MB), the TOC pointer will not be able to reach the new segment.
02953         Since we do not create a new PT_LOAD segment, but rather extend the existing PT_LOAD segment,
02954         we do not need to align by page size. 
02955         Note1: 64 bytes is just random number I choose. 
02956         Note2: We need to do this only for memory offset and not disk offset as TOC pointer
02957         uses only memory offset */
02958         pgSize = 64;
02959     }   
02960 
02961         
02962 #endif  
02963     Offset newaddr = highWaterMark  - (highWaterMark & (pgSize-1));
02964     if(newaddr < highWaterMark)
02965         newaddr += pgSize;
02966    return newaddr;
02967 #endif  
02968 }
02969 
02970 SYMTAB_EXPORT ObjectType Symtab::getObjectType() const 
02971 {
02972    return object_type_;
02973 }
02974 
02975 SYMTAB_EXPORT Dyninst::Architecture Symtab::getArchitecture()
02976 {
02977    return getObject()->getArch();
02978 }
02979 
02980 SYMTAB_EXPORT char *Symtab::mem_image() const 
02981 {
02982    return (char *)mf->base_addr();
02983 }
02984 
02985 SYMTAB_EXPORT std::string Symtab::file() const 
02986 {
02987    assert(mf);
02988    return mf->pathname();
02989 }
02990 
02991 SYMTAB_EXPORT std::string Symtab::name() const 
02992 {
02993    return mf->filename();
02994 }
02995 
02996 SYMTAB_EXPORT std::string Symtab::memberName() const 
02997 {
02998     return member_name_;
02999 }
03000 
03001 SYMTAB_EXPORT unsigned Symtab::getNumberofRegions() const 
03002 {
03003    return no_of_sections; 
03004 }
03005 
03006 SYMTAB_EXPORT unsigned Symtab::getNumberofSymbols() const 
03007 {
03008    return no_of_symbols; 
03009 }
03010 
03011 bool Symtab::setup_module_up_ptrs(SerializerBase *, Symtab *st)
03012 {
03013    std::vector<Module *> &mods = st->_mods;
03014 
03015    for (unsigned int i = 0; i < mods.size(); ++i) 
03016    {
03017       Module *m = mods[i];
03018       m->exec_ = st;
03019    }
03020 
03021    return true;
03022 }
03023 
03024 bool Symtab::fixup_relocation_symbols(SerializerBase *, Symtab *st)
03025 {
03026    std::vector<Module *> &mods = st->_mods;
03027 
03028    for (unsigned int i = 0; i < mods.size(); ++i) 
03029    {
03030       Module *m = mods[i];
03031       m->exec_ = st;
03032    }
03033 
03034    return true;
03035 }
03036 
03037 void Symtab::rebuild_symbol_hashes(SerializerBase *sb)
03038 {
03039     if (!is_input(sb))
03040         return;
03041 
03042     for (unsigned long i = 0; i < everyDefinedSymbol.size(); ++i)
03043     {
03044         Symbol *s = everyDefinedSymbol[i];
03045         assert(s);
03046         const std::string &pn = s->getPrettyName();
03047         const std::string &mn = s->getMangledName();
03048         const std::string tn = s->getTypedName();
03049 
03050         symsByPrettyName[pn].push_back(s);
03051         symsByMangledName[mn].push_back(s);
03052         symsByTypedName[tn].push_back(s);
03053         symsByOffset[s->getOffset()].push_back(s);
03054     }
03055 }
03056 
03057 void Symtab::rebuild_funcvar_hashes(SerializerBase *sb)
03058 {
03059     if (!is_input(sb))
03060         return;
03061     for (unsigned int i = 0; i < everyFunction.size(); ++i)
03062     {
03063         Function *f = everyFunction[i];
03064         funcsByOffset[f->getOffset()] = f;
03065     }
03066     for (unsigned int i = 0; i < everyVariable.size(); ++i)
03067     {
03068         Variable *v = everyVariable[i];
03069         varsByOffset[v->getOffset()] = v;
03070     }
03071 }
03072 void Symtab::rebuild_module_hashes(SerializerBase *sb)
03073 {
03074     if (!is_input(sb))
03075         return;
03076     for (unsigned int i = 0; i < _mods.size(); ++i)
03077     {
03078         Module *m = _mods[i];
03079         modsByFileName[m->fileName()] = m;
03080         modsByFullName[m->fullName()] = m;
03081     }
03082 }
03083 void Symtab::rebuild_region_indexes(SerializerBase *sb) THROW_SPEC (SerializerError)
03084 {
03085     if (!is_input(sb))
03086         return;
03087 
03088     for (unsigned int i = 0; i < regions_.size(); ++i)
03089     {
03090         Region *r = regions_[i];
03091 
03092         if ( r->isLoadable() )
03093         {
03094             if ((r->getRegionPermissions() == Region::RP_RX)
03095                     || (r->getRegionPermissions() == Region::RP_RWX))
03096                 codeRegions_.push_back(r);
03097             else
03098                 dataRegions_.push_back(r);
03099         }
03100 
03101         //  entry addr might require some special attn on windows, since it
03102         //  is not the disk offset but the actual mem addr, which is going to be
03103         //  different after deserialize.  Probably have to look it up again.
03104         regionsByEntryAddr[r->getMemOffset()] = r;
03105     }
03106 
03107     std::sort(codeRegions_.begin(), codeRegions_.end(), sort_reg_by_addr);
03108     std::sort(dataRegions_.begin(), dataRegions_.end(), sort_reg_by_addr);
03109 }
03110 
03111 #if !defined(SERIALIZATION_DISABLED)
03112 Serializable *Symtab::serialize_impl(SerializerBase *sb, 
03113         const char *tag) THROW_SPEC (SerializerError)
03114 {
03115     serialize_printf("%s[%d]:  welcome to Symtab::serialize_impl\n", 
03116             FILE__, __LINE__);
03117     if (is_input(sb))
03118     {
03119         //  don't bother with serializing standard and builtin types.
03120         /* XXX Change to use safe static allocation and initialization
03121                of standard and builtin types changes serialization behavior:
03122                these types are initialized on first access to the types
03123                structures (no explicit initialization). I think this code
03124                is dead anyway, though, so it probably doesn't matter.
03125         */
03126         //setupTypes();
03127     }
03128 
03129     ifxml_start_element(sb, tag);
03130     gtranslate(sb, imageOffset_, "imageOffset");
03131     gtranslate(sb, imageLen_, "imageLen");
03132     gtranslate(sb, dataOffset_, "dataOff");
03133     gtranslate(sb, dataLen_, "dataLen");
03134     gtranslate(sb, is_a_out, "isExec");
03135     gtranslate(sb, _mods, "Modules", "Module");
03136     rebuild_module_hashes(sb);
03137     if (is_input(sb))
03138     {
03139         //  problem:  if isTypeInfoValid_ is not true, we can trigger type parsing
03140         //  for an object class that does not exist.  Need to introduce logic to 
03141         //  recreate the object in this case
03142         isTypeInfoValid_ = true;
03143         isLineInfoValid_ = true; //  NOTE:  set this to true after deserializing at least one lineInformaton object
03144     }
03145     gtranslate(sb, regions_, "Regions", "Region");
03146     rebuild_region_indexes(sb);
03147     gtranslate(sb, everyDefinedSymbol, "EveryDefinedSymbol", "Symbol");
03148     rebuild_symbol_hashes(sb);
03149     gtranslate(sb, relocation_table_, "RelocationTable", "RelocationTableEntry");
03150     gtranslate(sb, everyFunction, "EveryFunction", "Function");
03151     gtranslate(sb, everyVariable, "EveryVariable", "Variable");
03152     rebuild_funcvar_hashes(sb);
03153 
03154     //gtranslate(sb, everyUniqueVariable, "EveryUniqueVariable", "UniqueVariable");
03155     //gtranslate(sb, modSyms, "ModuleSymbols", "ModuleSymbol");
03156 
03157     gtranslate(sb, excpBlocks, "ExceptionBlocks", "ExceptionBlock");
03158     ifxml_end_element(sb, tag);
03159 
03160     sb->magic_check(FILE__, __LINE__);
03161 #if 0
03162     ifinput(Symtab::setup_module_up_ptrs, sb, this);
03163     ifinput(fixup_relocation_symbols, sb, this);
03164 #endif
03165 
03166     if (is_input(sb))
03167     {
03168         dyn_hash_map<Address, Symbol *> *map_p = NULL;
03169         if (getAnnotation(map_p, IdToSymAnno) && (NULL != map_p))
03170         {
03171             if (!removeAnnotation(IdToSymAnno))
03172             {
03173                 fprintf(stderr, "%s[%d]:  failed to remove id-to-sym map\n", 
03174                         FILE__, __LINE__);
03175             }
03176             delete map_p;
03177         }
03178     }
03179     serialize_printf("%s[%d]:  leaving Symtab::serialize_impl\n", FILE__, __LINE__);
03180     return NULL;
03181 }
03182 #else
03183 Serializable *Symtab::serialize_impl(SerializerBase *, const char *) THROW_SPEC (SerializerError)
03184 {
03185    return NULL;
03186 }
03187 #endif
03188 
03189 SYMTAB_EXPORT LookupInterface::LookupInterface() 
03190 {
03191 }
03192 
03193 SYMTAB_EXPORT LookupInterface::~LookupInterface()
03194 {
03195 }
03196 
03197 
03198 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset tStart, 
03199       unsigned tSize, 
03200       Offset cStart) 
03201 : tryStart_(tStart), trySize_(tSize), catchStart_(cStart), hasTry_(true) 
03202 {
03203 }
03204 
03205    SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(Offset cStart) 
03206 : tryStart_(0), trySize_(0), catchStart_(cStart), hasTry_(false) 
03207 {
03208 }
03209 
03210 SYMTAB_EXPORT ExceptionBlock::ExceptionBlock(const ExceptionBlock &eb) :
03211    Serializable(),
03212    tryStart_(eb.tryStart_), trySize_(eb.trySize_), 
03213    catchStart_(eb.catchStart_), hasTry_(eb.hasTry_) 
03214 {
03215 }
03216 SYMTAB_EXPORT bool ExceptionBlock::hasTry() const
03217 { 
03218    return hasTry_; 
03219 }
03220 
03221 SYMTAB_EXPORT Offset ExceptionBlock::tryStart() const
03222 { 
03223    return tryStart_; 
03224 }
03225 
03226 SYMTAB_EXPORT Offset ExceptionBlock::tryEnd() const
03227 { 
03228    return tryStart_ + trySize_; 
03229 }
03230 
03231 SYMTAB_EXPORT Offset ExceptionBlock::trySize() const
03232 {
03233    return trySize_; 
03234 }
03235 
03236 SYMTAB_EXPORT bool ExceptionBlock::contains(Offset a) const
03237 { 
03238    return (a >= tryStart_ && a < tryStart_ + trySize_); 
03239 }
03240 
03241 #if !defined(SERIALIZATION_DISABLED)
03242 Serializable * ExceptionBlock::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
03243 {
03244     ifxml_start_element(sb, tag);
03245     gtranslate(sb, tryStart_, "tryStart");
03246     gtranslate(sb, trySize_, "trySize");
03247     gtranslate(sb, catchStart_, "catchStart");
03248     gtranslate(sb, hasTry_, "hasTry");
03249     ifxml_end_element(sb, tag);
03250     return NULL;
03251 }
03252 #else
03253 Serializable * ExceptionBlock::serialize_impl(SerializerBase *, const char *) THROW_SPEC (SerializerError)
03254 {
03255    return NULL;
03256 }
03257 #endif
03258 
03259 SYMTAB_EXPORT relocationEntry::relocationEntry() :
03260    target_addr_(0), 
03261    rel_addr_(0), 
03262    addend_(0), 
03263    rtype_(Region::RT_REL), 
03264    name_(""), 
03265    dynref_(NULL), 
03266    relType_(0)
03267 {
03268 }   
03269 
03270 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, std::string n, 
03271       Symbol *dynref, unsigned long relType) :
03272    target_addr_(ta), 
03273    rel_addr_(ra), 
03274    addend_(0), 
03275    rtype_(Region::RT_REL), 
03276    name_(n), 
03277    dynref_(dynref), 
03278    relType_(relType)
03279 {
03280 }
03281 
03282 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, Offset add, 
03283       std::string n, Symbol *dynref, unsigned long relType) :
03284    target_addr_(ta), 
03285    rel_addr_(ra), 
03286    addend_(add), 
03287    rtype_(Region::RT_REL), 
03288    name_(n), 
03289    dynref_(dynref), 
03290    relType_(relType)
03291 {
03292 }
03293 
03294 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ra, std::string n, 
03295       Symbol *dynref, unsigned long relType, Region::RegionType rtype) :
03296    target_addr_(0), 
03297    rel_addr_(ra), 
03298    addend_(0), 
03299    rtype_(rtype), 
03300    name_(n), 
03301    dynref_(dynref), 
03302    relType_(relType),
03303    rel_struct_addr_(0)
03304 {
03305 }
03306 
03307 SYMTAB_EXPORT relocationEntry::relocationEntry(Offset ta, Offset ra, Offset add,
03308         std::string n, Symbol *dynref, unsigned long relType,
03309         Region::RegionType rtype) :
03310     target_addr_(ta),
03311     rel_addr_(ra),
03312     addend_(add),
03313     rtype_(rtype),
03314     name_(n),
03315     dynref_(dynref),
03316     relType_(relType)
03317 {
03318 }
03319 
03320 SYMTAB_EXPORT Offset relocationEntry::target_addr() const 
03321 {
03322     return target_addr_;
03323 }
03324 
03325 SYMTAB_EXPORT void relocationEntry::setTargetAddr(const Offset off)
03326 {
03327     target_addr_ = off;
03328 }
03329 
03330 SYMTAB_EXPORT Offset relocationEntry::rel_addr() const 
03331 {
03332     return rel_addr_;
03333 }
03334 
03335 SYMTAB_EXPORT void relocationEntry::setRelAddr(const Offset value)
03336 {
03337     rel_addr_ = value;
03338 }
03339 
03340 SYMTAB_EXPORT const string &relocationEntry::name() const 
03341 {
03342     return name_;
03343 }
03344 
03345 SYMTAB_EXPORT Symbol *relocationEntry::getDynSym() const 
03346 {
03347     return dynref_;
03348 }
03349 
03350 SYMTAB_EXPORT bool relocationEntry::addDynSym(Symbol *dynref) 
03351 {
03352     dynref_ = dynref;
03353     return true;
03354 }
03355 
03356 SYMTAB_EXPORT Region::RegionType relocationEntry::regionType() const
03357 {
03358     return rtype_;
03359 }
03360 
03361 SYMTAB_EXPORT unsigned long relocationEntry::getRelType() const 
03362 {
03363     return relType_;
03364 }
03365 
03366 SYMTAB_EXPORT Offset relocationEntry::addend() const
03367 {
03368         return addend_;
03369 }
03370 
03371 SYMTAB_EXPORT void relocationEntry::setAddend(const Offset value)
03372 {
03373         addend_ = value;
03374 }
03375 
03376 SYMTAB_EXPORT void relocationEntry::setRegionType(const Region::RegionType value)
03377 {
03378         rtype_ = value;
03379 }
03380 
03381 SYMTAB_EXPORT void relocationEntry::setName(const std::string &newName) {
03382     name_ = newName;
03383 }
03384 
03385 bool relocationEntry::operator==(const relocationEntry &r) const
03386 {
03387     if (target_addr_ != r.target_addr_) return false;
03388     if (rel_addr_ != r.rel_addr_) return false;
03389     if (addend_ != r.addend_) return false;
03390     if (rtype_ != r.rtype_) return false;
03391     if (name_ != r.name_) return false;
03392     if (relType_ != r.relType_) return false;
03393     if (dynref_ && !r.dynref_) return false;
03394     if (!dynref_ && r.dynref_) return false;
03395     if (dynref_)
03396     {
03397         if (dynref_->getMangledName() != r.dynref_->getMangledName()) return false;
03398         if (dynref_->getOffset() != r.dynref_->getOffset()) return false;
03399     }
03400 
03401     return true;
03402 }
03403 
03404 #if !defined(SERIALIZATION_DISABLED)
03405 Serializable *relocationEntry::serialize_impl(SerializerBase *sb, const char *tag) THROW_SPEC (SerializerError)
03406 {
03407     //  on deserialize need to rebuild symtab::undefDynSyms before deserializing relocations
03408 
03409     std::string symname = dynref_ ? dynref_->getName() : std::string("");
03410     Offset symoff = dynref_ ? dynref_->getOffset() : (Offset) -1;
03411 
03412       ifxml_start_element(sb, tag);
03413       gtranslate(sb, target_addr_, "targetAddress");
03414       gtranslate(sb, rel_addr_, "relocationAddress");
03415       gtranslate(sb, addend_, "Addend");
03416       gtranslate(sb, name_, "relocationName");
03417       gtranslate(sb,  rtype_, Region::regionType2Str, "regionType");
03418       gtranslate(sb, relType_, "relocationType");
03419       gtranslate(sb, symname, "SymbolName");
03420       gtranslate(sb, symoff, "SymbolOffset");
03421       ifxml_end_element(sb, tag);
03422 
03423       if (sb->isInput())
03424       {
03425           dynref_ = NULL;
03426           if (symname != std::string(""))
03427           {
03428               //  if we have a name for this symbol, the offset should not be -1;
03429               if (symoff == (Offset) -1)
03430               {
03431                   fprintf(stderr, "%s[%d]:  inconsistent symname and offset combo!\n", 
03432                           FILE__, __LINE__);
03433               }
03434 
03435               SerContextBase *scb = sb->getContext();
03436               if (!scb)
03437               {
03438                   fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
03439                   SER_ERR("FIXME");
03440               }
03441 
03442               SerContext<Symtab> *scs = dynamic_cast<SerContext<Symtab> *>(scb);
03443 
03444               if (!scs)
03445               {
03446                   fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
03447                   SER_ERR("FIXME");
03448               }
03449 
03450               Symtab *st = scs->getScope();
03451 
03452               if (!st)
03453               {
03454                   fprintf(stderr, "%s[%d]:  SERIOUS:  FIXME\n", FILE__, __LINE__);
03455                   SER_ERR("FIXME");
03456               }
03457 
03458               std::vector<Symbol *> *syms = st->findSymbolByOffset(symoff);
03459               if (!syms || !syms->size())
03460               {
03461                   serialize_printf("%s[%d]:  cannot find symbol by offset %p\n", 
03462                           FILE__, __LINE__, (void *)symoff);
03463                   return NULL;
03464               }
03465 
03466               //  Might want to try to select the "best" symbol here if there is
03467               //  more than one.  Or Maybe just returning the first is sufficient.
03468 
03469               dynref_ = (*syms)[0];
03470           }
03471       }
03472       return NULL;
03473 }
03474 #else
03475 Serializable *relocationEntry::serialize_impl(SerializerBase *, const char *) THROW_SPEC (SerializerError)
03476 {
03477    return NULL;
03478 }
03479 #endif
03480 
03481 ostream & Dyninst::SymtabAPI::operator<< (ostream &os, const relocationEntry &r) 
03482 {
03483     if( r.getDynSym() != NULL ) {
03484         os << "Name: " << setw(20) << ( "'" + r.getDynSym()->getMangledName() + "'" );
03485     }else{
03486         os << "Name: " << setw(20) << r.name();
03487     }
03488     os << " Offset: " << std::hex << std::setfill('0') << setw(8) << r.rel_addr() 
03489        << std::dec << std::setfill(' ')
03490        << " Offset: " << std::hex << std::setfill('0') << setw(8) << r.target_addr() 
03491        << std::dec << std::setfill(' ')
03492        << " Addend: " << r.addend()
03493        << " Region: " << Region::regionType2Str(r.regionType())
03494        << " Type: " << setw(15) << relocationEntry::relType2Str(r.getRelType())
03495        << "(" << r.getRelType() << ")";
03496     if( r.getDynSym() != NULL ) {
03497         os << " Symbol Offset: " << std::hex << std::setfill('0') << setw(8) << r.getDynSym()->getOffset();
03498         os << std::setfill(' ');
03499         if( r.getDynSym()->isCommonStorage() ) {
03500             os << " COM";
03501         }else if( r.getDynSym()->getRegion() == NULL ) {
03502             os << " UND";
03503         }
03504     }
03505     return os;
03506 }
03507 
03508 const char *Symbol::symbolType2Str(SymbolType t) 
03509 {
03510    switch (t) 
03511    {
03512       CASE_RETURN_STR(ST_UNKNOWN);
03513       CASE_RETURN_STR(ST_FUNCTION);
03514       CASE_RETURN_STR(ST_OBJECT);
03515       CASE_RETURN_STR(ST_MODULE);
03516       CASE_RETURN_STR(ST_SECTION);
03517       CASE_RETURN_STR(ST_TLS);
03518       CASE_RETURN_STR(ST_DELETED);
03519       CASE_RETURN_STR(ST_NOTYPE);
03520       CASE_RETURN_STR(ST_INDIRECT);
03521    };
03522 
03523    return "invalid symbol type";
03524 }
03525 
03526 const char *Symbol::symbolLinkage2Str(SymbolLinkage t) 
03527 {
03528    switch (t) 
03529    {
03530       CASE_RETURN_STR(SL_UNKNOWN);
03531       CASE_RETURN_STR(SL_GLOBAL);
03532       CASE_RETURN_STR(SL_LOCAL);
03533       CASE_RETURN_STR(SL_WEAK);
03534    };
03535 
03536    return "invalid symbol linkage";
03537 }
03538 
03539 const char *Symbol::symbolTag2Str(SymbolTag t) 
03540 {
03541    switch (t) 
03542    {
03543       CASE_RETURN_STR(TAG_UNKNOWN);
03544       CASE_RETURN_STR(TAG_USER);
03545       CASE_RETURN_STR(TAG_LIBRARY);
03546       CASE_RETURN_STR(TAG_INTERNAL);
03547    };
03548 
03549    return "invalid symbol tag";
03550 }
03551 
03552 const char *Symbol::symbolVisibility2Str(SymbolVisibility t) 
03553 {
03554    switch(t) {
03555       CASE_RETURN_STR(SV_UNKNOWN);
03556       CASE_RETURN_STR(SV_DEFAULT);
03557       CASE_RETURN_STR(SV_INTERNAL);
03558       CASE_RETURN_STR(SV_HIDDEN);
03559       CASE_RETURN_STR(SV_PROTECTED);
03560    }
03561    return "invalid symbol visibility";
03562 }
03563 
03564 bool Symtab::hasStackwalkDebugInfo()
03565 {
03566 
03567     Object *obj = getObject();
03568     if (!obj)
03569     {
03570         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
03571         return false;
03572     }
03573    return obj->hasFrameDebugInfo();
03574 }
03575 
03576 bool Symtab::getRegValueAtFrame(Address pc, 
03577                                 Dyninst::MachRegister reg, 
03578                                 Dyninst::MachRegisterVal &reg_result,
03579                                 MemRegReader *reader)
03580 {
03581     Object *obj = getObject();
03582     if (!obj)
03583     {
03584         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
03585         return false;
03586     }
03587    return obj->getRegValueAtFrame(pc, reg, reg_result, reader);
03588 }
03589 
03590 Object *Symtab::getObject()
03591 {
03592    if (obj_private)
03593       return obj_private;
03594 
03595    //TODO: This likely triggered because we serialized in an object
03596    // from cache, but now the user is requesting more information from
03597    // the on disk object.  We should create a new 'Object' from data
03598    // (likely a file path) serialized in.
03599    
03600    fprintf(stderr, "%s[%d]:  FIXME:  request for object that does not exist!\n", FILE__, __LINE__);
03601    return NULL;
03602    //obj_private = new Object();
03603    //return obj_private;
03604 }
03605 
03606 void Symtab::parseTypesNow()
03607 {
03608    if (isTypeInfoValid_)
03609       return;
03610 
03611    parseTypes();
03612 }
03613 
03614 #if defined (cap_serialization)
03615 //  Not sure this is strictly necessary, problems only seem to exist with Module 
03616 // annotations when the file was split off, so there's probably something else that
03617 //  can be done to instantiate the relevant functions.
03618 
03619 bool dummy_for_ser_instance(std::string file, SerializerBase *sb)
03620 {
03621    if (file == std::string("no_such_file")) 
03622    {
03623       if (!sb) 
03624       {
03625          fprintf(stderr, "%s[%d]:  really should not happen\n", FILE__, __LINE__);
03626          return false;
03627       }
03628       fprintf(stderr, "%s[%d]:  WARN:  disabled serializer init here\n", FILE__, __LINE__);
03629    }
03630    return true;
03631 }
03632 
03633 #endif
03634 
03635 
03636 #if !defined(SERIALIZATION_DISABLED)
03637 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_serializer(Symtab *t, std::string file)
03638 {
03639     SerializerBin *ser;
03640     SerContext<Symtab> *scs = new SerContext<Symtab>(t, file);
03641     ser = new SerializerBin(scs, "SerializerBin", file, sd_serialize, false);
03642     return ser;
03643 }
03644 
03645 SYMTAB_EXPORT SerializerBase *nonpublic_make_bin_symtab_deserializer(Symtab *t, std::string file)
03646 {
03647     SerializerBin *ser;
03648     SerContext<Symtab> *scs = new SerContext<Symtab>(t, file);
03649     ser = new SerializerBin(scs, "DeserializerBin", file, sd_deserialize, false);
03650     return ser;
03651 }
03652 
03653 SYMTAB_EXPORT void nonpublic_free_bin_symtab_serializer(SerializerBase *sb)
03654 {
03655     SerializerBin *sbin = dynamic_cast<SerializerBin *>(sb);
03656     if (sbin)
03657     {
03658         delete(sbin);
03659     }
03660     else
03661         fprintf(stderr, "%s[%d]:  FIXME\n", FILE__, __LINE__);
03662 
03663 }
03664 #endif
03665 
03666 SYMTAB_EXPORT Offset Symtab::getElfDynamicOffset()
03667 {
03668 #if defined(os_linux) || defined(os_freebsd)
03669     Object *obj = getObject();
03670     if (!obj)
03671     {
03672         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
03673         return 0;
03674     }
03675    return obj->getDynamicAddr();
03676 #else
03677    return 0;
03678 #endif
03679 }
03680 
03681 SYMTAB_EXPORT bool Symtab::removeLibraryDependency(std::string lib)
03682 {
03683 #if defined(os_aix) || defined(os_windows)
03684    return false;
03685 #else
03686    Object *obj = getObject();
03687     if (!obj) {
03688         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
03689         return false;
03690     }
03691    return obj->removePrereqLibrary(lib);
03692 #endif
03693 }
03694    
03695 SYMTAB_EXPORT bool Symtab::addLibraryPrereq(std::string name)
03696 {
03697 #if defined(os_aix)
03698    return false;
03699 #endif
03700 
03701    Object *obj = getObject();
03702     if (!obj)
03703     {
03704         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
03705         return false;
03706     }
03707    // remove forward slashes and back slashes
03708    size_t size = name.find_last_of("/");
03709    size_t lastBS = name.find_last_of("\\");
03710    if (lastBS > size) {
03711       size = lastBS;
03712    }
03713 
03714    string filename = name.substr(size+1);
03715 
03716 #if ! defined(os_windows) 
03717    obj->insertPrereqLibrary(filename);
03718 #else 
03719    // must add a symbol for an exported function belonging to the library 
03720    // to get the Windows loader to load the library
03721 
03722    Symtab *symtab = Symtab::findOpenSymtab(name);
03723    if (!symtab) {
03724       if (!Symtab::openFile(symtab, name)) {
03725          return false;
03726       }
03727    }
03728    
03729    // find an exported function
03730    vector<Symbol*> funcs;
03731    symtab->getAllSymbolsByType(funcs, Symbol::ST_FUNCTION);
03732    vector<Symbol*>::iterator fit = funcs.begin(); 
03733    for (; fit != funcs.end() && !(*fit)->isInDynSymtab(); fit++);
03734    if (fit == funcs.end()) {
03735       return false;
03736    }
03737    
03738    string funcName = string((*fit)->getPrettyName());
03739    if (funcName.empty()) {
03740       funcName = string((*fit)->getMangledName());
03741       if (funcName.empty()) {
03742          assert(0);
03743          return false;
03744       }
03745    }
03746    symtab->getObject()->addReference((*fit)->getOffset(), 
03747                                      name, 
03748                                      funcName);
03749    obj->addReference((*fit)->getOffset(), filename, funcName);
03750 #endif
03751    return true;
03752 }
03753 
03754 SYMTAB_EXPORT bool Symtab::addSysVDynamic(long name, long value)
03755 {
03756 #if defined(os_linux) || defined(os_freebsd)
03757     Object *obj = getObject();
03758     if (!obj)
03759     {
03760         fprintf(stderr, "%s[%d]:  getObject failed here\n", FILE__, __LINE__);
03761         return false;
03762     }
03763   obj->insertDynamicEntry(name, value);
03764    return true;
03765 #else
03766    return false;
03767 #endif
03768 }
03769 
03770 SYMTAB_EXPORT bool Symtab::addExternalSymbolReference(Symbol *externalSym, Region *localRegion,
03771         relocationEntry localRel)
03772 {
03773     // Adjust this to the correct value
03774     localRel.setRegionType(getObject()->getRelType());
03775 
03776     // Create placeholder Symbol for external Symbol reference
03777     // Bernat, 7SEP2010 - according to Matt, these symbols should have
03778     // type "undefined", which means a region of NULL. Changing
03779     // from "localRegion" to NULL. 
03780     Symbol *symRef = new Symbol(externalSym->getMangledName(),
03781                                 externalSym->getType(),
03782                                 Symbol::SL_GLOBAL,
03783                                 Symbol::SV_DEFAULT,
03784                                 (Address)0,
03785                                 getDefaultModule(),
03786                                 NULL, // localRegion,
03787                                 externalSym->getSize(),
03788                                 true,
03789                                 false);
03790 
03791    if( !addSymbol(symRef, externalSym) ) return false;
03792 
03793    localRegion->addRelocationEntry(localRel);
03794 
03795    // Make sure the Symtab holding the external symbol gets linked
03796    // with this Symtab
03797    explicitSymtabRefs_.insert(externalSym->getSymtab());
03798 
03799    return true;
03800 }
03801 
03802 // on windows we can't specify the trap table's location by adding a dynamic
03803 // symbol as we don on windows
03804 SYMTAB_EXPORT bool Symtab::addTrapHeader_win(Address ptr)
03805 {
03806 #if defined(os_windows)
03807    getObject()->setTrapHeader(ptr);
03808    return true;
03809 #else
03810    ptr = ptr; //keep compiler happy
03811    assert(0);
03812    return false;
03813 #endif
03814 }
03815 
03816 bool Symtab::getExplicitSymtabRefs(std::set<Symtab *> &refs) {
03817     refs = explicitSymtabRefs_;
03818     return (refs.size() != 0);
03819 }
03820 
03821 SYMTAB_EXPORT bool Symtab::addLinkingResource(Archive *library) {
03822     linkingResources_.push_back(library);
03823 
03824     return true;
03825 }
03826 
03827 SYMTAB_EXPORT bool Symtab::getLinkingResources(std::vector<Archive *> &libs) {
03828     libs = linkingResources_;
03829     return (linkingResources_.size() != 0);
03830 }
03831 
03832 SYMTAB_EXPORT Address Symtab::getLoadAddress()
03833 {
03834 #if defined(os_linux) || defined(os_freebsd) || defined(os_aix)
03835    return getObject()->getLoadAddress();
03836 #else
03837    return 0x0;
03838 #endif
03839 }
03840 
03841 SYMTAB_EXPORT bool Symtab::isDefensiveBinary() const
03842 {
03843     return isDefensiveBinary_;
03844 }
03845 
03846 SYMTAB_EXPORT bool Symtab::canBeShared()
03847 {
03848    return mf->canBeShared();
03849 }
03850 
03851 SYMTAB_EXPORT Offset Symtab::getInitOffset()
03852 {
03853 #if defined(os_linux) || defined(os_freebsd)
03854    return getObject()->getInitAddr();
03855 #else
03856    return 0x0;
03857 #endif
03858 
03859 }
03860 
03861 SYMTAB_EXPORT Offset Symtab::getFiniOffset()
03862 {
03863 #if defined(os_linux) || defined(os_freebsd)
03864    return getObject()->getFiniAddr();
03865 #else
03866    return 0x0;
03867 #endif
03868 
03869 }
03870 
03871 void Symtab::getSegmentsSymReader(std::vector<SymSegment> &segs) {
03872 #if !defined(os_windows)
03873    obj_private->getSegmentsSymReader(segs);
03874 #endif
03875 }
03876 
03877 
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1