Object-nt.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 #define WIN32_LEAN_AND_MEAN
00032 
00033 #include <windows.h>
00034 #include <cvconst.h>
00035 #include <oleauto.h>
00036 #if !defined __out_ecount_opt
00037 #define __out_ecount_opt(x)
00038 #endif
00039 #include <dbghelp.h>
00040 
00041 #include <iostream>
00042 #include <iomanip>
00043 #include <limits.h>
00044 #include <crtdbg.h>
00045 #include <winnt.h>
00046 
00047 #include "symtabAPI/src/Object.h"
00048 #include "symtabAPI/src/Object-nt.h"
00049 
00050 #include "LineInformation.h"
00051 #include "Collections.h"
00052 #include "Symtab.h"
00053 #include "Module.h"
00054 #include "Function.h"
00055 #include "Variable.h"
00056 #include "emitWin.h"
00057 
00058 #include "common/h/headers.h"
00059 
00060 using namespace Dyninst;
00061 using namespace Dyninst::SymtabAPI;
00062 
00063 Type *getType(HANDLE p, Offset mod_base, int typeIndex, Module *mod = NULL);
00064 bool pd_debug_export_symbols = false;
00065 using namespace std;
00066 
00067 std::string convertCharToString(const char *ptr){
00068     std::string str;
00069     if(ptr)
00070     str = ptr;
00071     else
00072     str = "";
00073     return str;
00074 }
00075 
00076 static void printSysError(unsigned errNo) {
00077     char buf[1000];
00078     
00079     int result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNo,
00080                             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
00081                                 buf, 1000, NULL);
00082     if (!result) {
00083     fprintf(stderr, "Couldn't print error message\n");
00084         printSysError(GetLastError());
00085     }
00086     fprintf(stderr, "*** System error [%d]: %s\n", errNo, buf);
00087     fflush(stderr);
00088 }
00089 
00090 //---------------------------------------------------------------------------
00091 // prototypes of functions used in this file
00092 //---------------------------------------------------------------------------
00093 BOOL CALLBACK SymEnumSymbolsCallback( PSYMBOL_INFO pSymInfo,
00094                                         ULONG symSize,
00095                                         PVOID userContext );
00096 /*
00097  * stripAtSuffix 
00098  *
00099  * Strips off of a string any suffix that consists of an @ sign followed by
00100  * decimal digits.
00101  *
00102  * str  The string to strip the suffix from.  The string is altered in place.
00103  */
00104  static void stripAtSuffix(char *str)
00105  {
00106     // many symbols have a name like foo@4, we must remove the @4
00107     // just searching for an @ is not enough,
00108     // as it may occur on other positions. We search for the last one
00109     // and check that it is followed only by digits.
00110     char *p = strrchr(str, '@');
00111     if (p) {
00112       char *q = p+1;
00113       strtoul(p+1, &q, 10);
00114       if (q > p+1 && *q == '\0') {
00115         *p = '\0';
00116       }
00117     }
00118 }
00119 
00120 char *cplus_demangle(char *c, int, bool includeTypes) { 
00121     
00122     char buf[1000];
00123     if (c[0]=='_') {
00124     // VC++ 5.0 seems to decorate C symbols differently to C++ symbols
00125     // and the UnDecorateSymbolName() function provided by imagehlp.lib
00126     // doesn't manage (or want) to undecorate them, so it has to be done
00127     // manually, removing a leading underscore from functions & variables
00128     // and the trailing "$stuff" from variables (actually "$Sstuff")
00129     unsigned i;
00130     for (i=1; i<sizeof(buf) && c[i]!='$' && c[i]!='\0'; i++)
00131         buf[i-1]=c[i];
00132     buf[i-1]='\0';
00133     stripAtSuffix(buf);
00134     if (buf[0] == '\0') 
00135         return 0; // avoid null names which seem to annoy Paradyn
00136     return P_strdup(buf);
00137     }
00138     else {
00139        if (includeTypes) {
00140       if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE| UNDNAME_NO_ACCESS_SPECIFIERS|UNDNAME_NO_MEMBER_TYPE|UNDNAME_NO_MS_KEYWORDS)) {
00141         //   printf("Undecorate with types: %s = %s\n", c, buf);
00142         stripAtSuffix(buf);
00143         return P_strdup(buf);
00144       }
00145        }
00146        else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_NAME_ONLY)) {
00147      //else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE|UNDNAME_32_BIT_DECODE)) {
00148      //printf("Undecorate: %s = %s\n", c, buf);
00149      stripAtSuffix(buf);          
00150      return P_strdup(buf);
00151        }
00152     }
00153     return 0;
00154 }
00155 
00156 //---------------------------------------------------------------------------
00157 // Object method implementation
00158 //---------------------------------------------------------------------------
00159 struct  CompareSymAddresses: public binary_function<const Object::intSymbol*, const Object::intSymbol*, bool> 
00160 {
00161     bool operator()(const Object::intSymbol *s1, const Object::intSymbol* s2) {
00162         bool ret = false;
00163         // first try comparing by address
00164         if( s1->GetAddr() < s2->GetAddr() ) 
00165         {
00166             ret = true;
00167         }
00168         else if( s1->GetAddr() > s2->GetAddr() )
00169         {
00170             ret = false;
00171         }
00172         else
00173         {
00174             // the two symbols have the same address
00175             // use our next criteria (the existence of a size)
00176             // for a given address, we want symbols with a size
00177             // to occur before those without so that we can
00178             // use the size if we wish
00179             if( (s1->GetSize() != 0) && (s2->GetSize() == 0) )
00180             {
00181                 ret = true;
00182             }
00183             else if( (s1->GetSize() == 0) && (s2->GetSize() != 0) )
00184             {
00185                 ret = false;
00186             }
00187         }
00188         return ret;
00189     }
00190 };
00191 
00192 Object::Module::Module( std::string _name, DWORD64 _baseAddr, DWORD64 _extent )  :
00193                         name(_name),
00194                         baseAddr(_baseAddr),
00195                         extent(_extent),
00196                         isDll( false )
00197 {
00198     defFile = new Object::File();
00199     files.push_back( defFile );
00200 }
00201 
00202 Object::File*
00203 Object::Module::FindFile( std::string name )
00204 {
00205     File* ret = NULL;
00206     for( std::vector<File *>::iterator iter = files.begin();
00207             iter != files.end();
00208             iter++ )
00209     {
00210         if( (*iter)->GetName() == name )
00211         {
00212             ret = *iter;
00213             break;
00214         }
00215     }
00216     return ret;
00217 }
00218 
00219 void
00220 Object::File::DefineSymbols( dyn_hash_map<std::string, std::vector< Symbol *> >& allSyms,
00221                              map<Symbol *, std::string> &symsToMods,
00222                              const std::string& modName ) const
00223 {
00224     for( std::vector<Object::intSymbol*>::const_iterator iter = syms.begin(); iter != syms.end(); iter++ ) {
00225         const Object::intSymbol* curSym = * iter;
00226     assert( curSym != NULL );
00227     curSym->DefineSymbol( allSyms, symsToMods, modName );
00228     }
00229 }
00230 
00231 void
00232 Object::intSymbol::DefineSymbol(dyn_hash_map<std::string,std::vector<Symbol *> >&allSyms,
00233                 map<Symbol *, std::string> &symsToMods,
00234                                 const std::string& modName ) const
00235 {
00236     Symbol *sym = new Symbol(GetName(), 
00237                              (Symbol::SymbolType) GetType(),
00238                              (Symbol::SymbolLinkage) GetLinkage(),
00239                              Symbol::SV_UNKNOWN,
00240                              (Offset)GetAddr(),
00241                              NULL,
00242                              GetRegion(),
00243                              GetSize());
00244     allSyms[GetName()].push_back(sym);
00245     symsToMods[sym] = modName;
00246 }
00247 
00248 void
00249 Object::Module::DefineSymbols( const Object* obj,
00250                                dyn_hash_map<std::string, std::vector< Symbol *> > & syms,
00251                                map<Symbol *, std::string> &symsToMods ) const
00252 {
00253     // define Paradyn/dyninst modules and symbols
00254     if( !isDll )
00255     {
00256         // this is an EXE
00257         for( std::vector<Object::File*>::const_iterator iter = files.begin();
00258                 iter != files.end();
00259              iter++ ) {
00260             const File* curFile = *iter;
00261             assert( curFile != NULL );
00262             
00263             //fprintf(stderr, "ObjMod::DefineSymbols for %s\n", curFile->GetName().c_str());
00264             // add a Symbol for the file
00265             Symbol *sym = new Symbol( curFile->GetName(), 
00266                                       Symbol::ST_MODULE,
00267                                       Symbol::SL_GLOBAL,
00268                                       Symbol::SV_UNKNOWN,
00269                                       obj->code_off(),  // TODO use real base of symbols for file
00270                                       NULL,
00271                                       NULL, 0 );    // TODO Pass Section pointer also
00272             // TODO also pass size
00273             // add symbols for each of the file's symbols
00274             syms[curFile->GetName()].push_back(sym);
00275             symsToMods[sym] = curFile->GetName();
00276 
00277             curFile->DefineSymbols( syms, symsToMods, curFile->GetName() );
00278         }
00279     }
00280     else
00281     {
00282         // we represent a DLL
00283         // add one Symbol for the entire module
00284 
00285         Symbol *sym = new Symbol(name,
00286                                  Symbol::ST_MODULE,
00287                                  Symbol::SL_GLOBAL,
00288                                  Symbol::SV_UNKNOWN,
00289                                  obj->code_off(),
00290                                  NULL,
00291                                  NULL,                  //TODO pass Sections pointer
00292                                  obj->code_len());
00293     
00294         syms[name].push_back(sym); 
00295         symsToMods[sym] = name;
00296 
00297         // add symbols for each of the module's symbols
00298         for( std::vector<Object::File*>::const_iterator iter = files.begin();
00299                 iter != files.end();
00300                 iter++ )
00301         {
00302             const File* curFile = *iter;
00303             assert( curFile != NULL );
00304             // add symbols for each of the file's symbols
00305             curFile->DefineSymbols( syms, symsToMods, name );
00306         }
00307     }
00308 }
00309 
00310 void
00311 Object::Module::PatchSymbolSizes( const Object* obj,
00312                                   const std::vector<Object::intSymbol*>& allSyms ) const
00313 {
00314     DWORD64 lastFuncAddr = NULL;
00315     unsigned int i;
00316     
00317     for( i = 0; i < allSyms.size(); i++ )
00318     {
00319         Object::intSymbol* sym = allSyms[i];
00320         assert( sym != NULL );
00321         if( (sym->GetName() != "") && (sym->GetSize() == 0) &&
00322         ((sym->GetType() == Symbol::ST_FUNCTION) ||
00323          (sym->GetType() == Symbol::ST_OBJECT)))
00324     {
00325         // check for function aliases
00326         // note that this check depends on the allSymbols
00327         // array being sorted so that aliases are considered
00328         // after the "real" function symbol
00329         bool isAlias = false;
00330         if( (sym->GetType() == Symbol::ST_FUNCTION) &&
00331         (sym->GetAddr() == lastFuncAddr) &&
00332         (sym->GetSize() == 0) )
00333         {
00334         // this function is an alias
00335                 // we currently leave their size as zero to indicate 
00336                 // that they are uninstrumentable.  Ideally, this will
00337                 // change once a mechanism becomes available to identify
00338                 // these as function aliases.
00339                 isAlias = true;
00340             }
00341         if( !isAlias )
00342             {
00343                 //
00344                 // patch the symbol's size
00345                 //
00346                 // We consider the symbol's size to be the distance
00347                 // to the next symbol.  (Sometimes this causes us to
00348                 // overestimate, because compilers sometimes leave some
00349                 // "padding" between the end of a function and the beginning
00350                 // of the next.)
00351                 //
00352                 // Note that we have to use the next symbol whose
00353                 // address is different from the current one, to handle
00354                 // cases where aliases are included in the symbol table
00355         //
00356         DWORD64 cb;
00357         
00358                 //
00359                 // find next function or object symbol in our section with
00360                 // an address different from ours
00361                 //
00362                 // the while test looks complicated -
00363                 // all we're trying to do is skip to the next
00364                 // function or object symbol within the array whose
00365                 // address is not the same as allSymbols[i].
00366                 unsigned int j = i + 1;
00367                 while((j < allSyms.size()) &&
00368                 (((allSyms[j]->GetType() != Symbol::ST_FUNCTION) &&
00369                                 (allSyms[j]->GetType() != Symbol::ST_OBJECT)) ||
00370                                 (allSyms[j]->GetAddr() == sym->GetAddr())))
00371                 {
00372                     j++;
00373                 }
00374                 if( j < allSyms.size() &&
00375                     (allSyms[j]->GetType() == sym->GetType()) )
00376                 {
00377                     // we found a symbol from the same section
00378                     // with a different address -
00379                     // size is just the delta between symbols
00380                     cb = allSyms[j]->GetAddr() - sym->GetAddr();
00381                 }
00382                 else
00383                 {
00384                     // we couldn't find another symbol in our section
00385                     // with a different address -
00386                     // size is the remainder of the current section
00387                     if( sym->GetType() == Symbol::ST_FUNCTION )
00388                     {
00389                         // size is remainder of the .text section
00390                         cb = (obj->code_off() + obj->code_len()) - 
00391                             sym->GetAddr();
00392                     }
00393                     else
00394                     {
00395                         // size is remainder of the .data section
00396                         cb = (obj->data_off() + obj->data_len()) - 
00397                             sym->GetAddr();
00398                     }
00399                 }
00400                 sym->SetSize( (unsigned int) cb );
00401             }
00402             // update the last known function symbol
00403             if( sym->GetType() == Symbol::ST_FUNCTION )
00404             {
00405                 lastFuncAddr = sym->GetAddr();
00406             }
00407         }
00408     }
00409 }
00410 
00411 void
00412 Object::Module::BuildSymbolMap( const Object* obj ) const
00413 {
00414     std::vector<Object::intSymbol*> allSyms;
00415     // add all symbols to our allSyms std::vector
00416     std::vector<Object::File*>::const_iterator iter = files.begin();
00417     for(;   iter != files.end();    iter++ )
00418     {
00419         assert( *iter != NULL );
00420         const std::vector<Object::intSymbol*>& curSyms = (*iter)->GetSymbols();
00421         for( std::vector<Object::intSymbol*>::const_iterator symIter = curSyms.begin(); symIter != curSyms.end();symIter++ )
00422         {
00423             assert( *symIter != NULL );
00424             allSyms.push_back( *symIter );
00425         }
00426     }
00427     // sort the symbols by address
00428     sort( allSyms.begin(), allSyms.end(), CompareSymAddresses());
00429     for( unsigned int i = 1; i < allSyms.size(); i++ )
00430     {
00431         if( allSyms[i-1]->GetAddr() > allSyms[i]->GetAddr() )
00432         {
00433             cout << "WARNING - sort failed" << endl;
00434             assert( false );
00435         }
00436     }
00437     // patch up any symbol sizes which weren't given to us
00438     PatchSymbolSizes( obj, allSyms );
00439 }
00440 
00441 Object::~Object( void )
00442 {
00443 }
00444 
00445 #define SymTagFunction 0x5
00446 #define SymTagData 0x7
00447 #define SymTagPublicSymbol 0xa
00448 #define SymTagMisc 0x3808       // Seen with NB11, VC++6-produced executables
00449 //
00450 // Our recognition of interesting symbols (functions and global data)
00451 // is complicated due to lack of consistency in how they are
00452 // presented to us in the pSymInfo struct.  For example,
00453 // Microsoft's own system DLLs like kernel32.dll only seem to provide
00454 // us their exports - these have the SYMFLAG_EXPORT bit set in
00455 // pSymInfo->Flags.  In contrast, EXEs with full debug information
00456 // may have pSymInfo->Flags == 0, with pSymInfo->Tag indicating the
00457 // type of symbol.
00458 //
00459 static BOOL isGlobalSymbol(PSYMBOL_INFO pSymInfo) {
00460  return ((pSymInfo->Flags & SYMFLAG_EXPORT) ||
00461      (pSymInfo->Flags & SYMFLAG_FUNCTION) ||
00462      ((!pSymInfo->Flags) && 
00463       ((pSymInfo->Tag == SymTagFunction) ||
00464        (pSymInfo->Tag == SymTagData) ||
00465        (pSymInfo->Tag == SymTagPublicSymbol) ||
00466        (pSymInfo->Tag == SymTagMisc))) );
00467 }
00468 
00469 void Object::ParseGlobalSymbol(PSYMBOL_INFO pSymInfo)
00470 {
00471     Object::Module* curMod = GetCurrentModule();
00472     assert( curMod != NULL );
00473     
00474     IMAGEHLP_LINE64 lineInfo;
00475     DWORD dwDisplacement = 0;
00476     ZeroMemory( &lineInfo, sizeof(lineInfo) );
00477     lineInfo.SizeOfStruct = sizeof(lineInfo);
00478     Object::File* pFile = NULL;
00479     if( SymGetLineFromAddr64( hProc,
00480                                 pSymInfo->Address,
00481                                 &dwDisplacement,
00482                                 &lineInfo ) ) {
00483         // ensure we have a file for this object
00484         pFile = curMod->FindFile( lineInfo.FileName );
00485         if( pFile == NULL ) {
00486             pFile = new Object::File( lineInfo.FileName );
00487             curMod->AddFile( pFile );
00488         }
00489     }
00490     else {
00491         pFile = curMod->GetDefaultFile();
00492     }
00493     assert( pFile != NULL );
00494     // is it a function or not?
00495     // TODO why is there a discrepancy between code base addr for
00496     // EXEs and DLLs?
00497     DWORD symType = Symbol::ST_UNKNOWN;
00498     DWORD symLinkage = Symbol::SL_UNKNOWN;
00499     DWORD64 codeLen = code_len();
00500     DWORD64 codeBase = code_off();
00501     symType = Symbol::ST_FUNCTION;
00502     //codeBase += get_base_addr();
00503     if ((pSymInfo->Flags & SYMFLAG_FUNCTION) ||
00504         (pSymInfo->Tag == SymTagFunction && !pSymInfo->Flags))
00505     {
00506         symLinkage = Symbol::SL_UNKNOWN;
00507     }
00508     else if ((pSymInfo->Flags == SYMFLAG_EXPORT && 
00509         isText((Offset) pSymInfo->Address - (Offset)mf->base_addr())) ||
00510         (pSymInfo->Name && (!strcmp(pSymInfo->Name, "loadsnstores") ||
00511         !strcmp(pSymInfo->Name, "_loadsnstores"))
00512         ))
00513     {
00514         symType = Symbol::ST_FUNCTION;
00515         symLinkage = Symbol::SL_UNKNOWN;
00516     }
00517     else
00518     {
00519         symType = Symbol::ST_OBJECT;
00520         symLinkage = Symbol::SL_GLOBAL;
00521     }
00522     // register the symbol
00523     Offset baseAddr = 0;
00524     //  if (desc.isSharedObject())
00525     //if(curModule->IsDll())
00526     //   baseAddr = get_base_addr();
00527     if( !isForwarded( ((Offset) pSymInfo->Address) - baseAddr ) )
00528     {
00529         pFile->AddSymbol( new Object::intSymbol
00530                           ( pSymInfo->Name,
00531                             pSymInfo->Address - get_base_addr(),
00532                             symType,
00533                             symLinkage,
00534                             pSymInfo->Size,
00535                             findEnclosingRegion((Offset)(pSymInfo->Address - get_base_addr())) ));
00536     } 
00537 }
00538    
00539 BOOL CALLBACK SymEnumSymbolsCallback( PSYMBOL_INFO pSymInfo,
00540                                         ULONG symSize,
00541                                         PVOID userContext )
00542 {
00543     assert( pSymInfo != NULL );
00544     Object* obj = (Object*) userContext;
00545     assert( obj != NULL );
00546 
00547 #if 0
00548     fprintf(stderr, "symEnumSymsCallback, %s, Flags:0x%x, Tag:0x%x, Type:%d, Addr:0x%x...\n",
00549            pSymInfo->Name,
00550        pSymInfo->Flags,
00551        pSymInfo->Tag,
00552        pSymInfo->TypeIndex,
00553        pSymInfo->Address);
00554 #endif
00555 
00556    if (isGlobalSymbol(pSymInfo))
00557    {
00558       obj->ParseGlobalSymbol(pSymInfo);
00559    }
00560    else if ((pSymInfo->Flags & SYMFLAG_LOCAL) ||
00561         (pSymInfo->Flags & SYMFLAG_PARAMETER)) {
00562       //parsing_printf("Is a local variable\n");
00563       //obj->ParseLocalSymbol(pSymInfo);
00564    }
00565    else {
00566       //parsing_printf(" skipping\n");
00567    }
00568    // keep enumerating symbols
00569    return TRUE;
00570 }
00571 
00572 /*
00573  * This function finds all the global symbols
00574  * in a module and all of the source files. (i.e. so this function would find
00575  * the 'main' symbol and find the starting point of 'foo.c'
00576  *
00577  */
00578 void Object::ParseSymbolInfo( bool alloc_syms )
00579 {
00580    // build a Module object for the current module (EXE or DLL)
00581    // Note that the CurrentModuleScoper object ensures that the
00582    // curModule member will be reset when we leave the scope of
00583    // this function.
00584    // curModule = new Object::Module( file_, desc.code() );
00585    string file_ = mf->filename();
00586    static unsigned count = 1;
00587    hProc = (HANDLE) count++;
00588    if(!SymInitialize(hProc, NULL, false)){
00589       DWORD dwErr = GetLastError();
00590       if(dwErr) {
00591          fprintf( stderr, "SymInitialize failed for %s\n",
00592                ((file_.length() > 0) ? file_.c_str() 
00593                 : "<no name available>"));
00594          goto done;
00595       }
00596    }
00597    assert( hProc != NULL );
00598    assert( hProc != INVALID_HANDLE_VALUE );
00599 
00600    // grab load address
00601    if (peHdr) imageBase = peHdr->OptionalHeader.ImageBase;
00602    else imageBase = 0; 
00603 
00604    // load symbols for this module
00605    //DWORD64 dw64BaseAddr = (DWORD64)desc.loadAddr();
00606    HANDLE mapAddr = mf->base_addr();
00607    DWORD64 dw64BaseAddr = (DWORD64)mapAddr;
00608    //load address is always same(fake address space)
00609    HANDLE hFile = mf->getFileHandle();
00610    DWORD64 loadRet = SymLoadModule64( hProc,            // proc handle
00611          hFile,     // file handle
00612          NULL,      // image name
00613          NULL,      // shortcut name
00614          dw64BaseAddr,  // load address
00615          0 );       // size of DLL    
00616    if(!loadRet) {
00617       DWORD dwErr = GetLastError();
00618       if(dwErr) {
00619          string file_ = mf->filename();
00620          fprintf( stderr, "SymLoadModule64 failed for %s\n",
00621                ((file_.length() > 0) ? file_.c_str() 
00622                 : "<no name available>"));
00623          //printSysError(dwErr);
00624          goto done;
00625       }
00626    }
00627    // parse symbols for the module
00628    if( !SymEnumSymbols(hProc,              // process handle
00629             dw64BaseAddr,           // load address
00630             "",         // symbol mask (we use none)
00631             SymEnumSymbolsCallback, // called for each symbol
00632             this ) )        // client data
00633    {
00634       int lasterr = GetLastError();
00635       fprintf( stderr, "Failed to enumerate symbols\n");
00636       //printSysError(lasterr);
00637    }
00638 
00639    // We have a module object, with one or more files,
00640    // each with one or more symbols.  However, the symbols
00641    // are not necessarily in order, nor do they necessarily have valid sizes.
00642    assert( curModule != NULL );
00643    curModule->BuildSymbolMap( this );
00644    if (alloc_syms)
00645       curModule->DefineSymbols( this, symbols_, symsToModules_ );
00646    no_of_symbols_ = symbols_.size();
00647 
00648    //fprintf(stderr, "%s[%d]:  removed call to parseFileLineInfo here\n", FILE__, __LINE__);
00649 
00650    // Since PE-COFF is very similar to COFF (in that it's not like ELF),
00651    // the .text and .data sections are perfectly mapped to code/data segments
00652    code_vldS_ = code_off_;
00653    code_vldE_ = code_off_ + code_len_;
00654    data_vldS_ = data_off_;
00655    data_vldE_ = data_off_ + data_len_;
00656 
00657 done:
00658    delete curModule;
00659 }
00660 
00661 // Ensure that the optional header has a TLS directory entry
00662 // calculate the TLS directory address and make sure it's valid
00663 // calculate the address of the TLS callback array and make sure it's valid
00664 // for each TLS callback, add a function symbol
00665 void Object::AddTLSFunctions()
00666 {
00667    // ensure that the optional header has a TLS directory entry
00668    if (!peHdr || peHdr->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_TLS) {
00669       return;
00670    }
00671 
00672    // calculate the TLS directory address and make sure it's valid
00673    unsigned long tlsSize = peHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size;
00674    if (!tlsSize) {
00675       return;
00676    }
00677    Address imgBase = peHdr->OptionalHeader.ImageBase;
00678    Offset tlsMemOff = peHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress;
00679    Region *secn = findEnclosingRegion(tlsMemOff);
00680    if (!secn || (tlsMemOff - secn->getMemOffset()) > secn->getDiskSize()) {
00681       return;
00682    }
00683    Offset tlsDiskOff = tlsMemOff 
00684       + (Offset)secn->getDiskOffset() 
00685       - (Offset)secn->getMemOffset();
00686    IMAGE_TLS_DIRECTORY *tlsDir = (IMAGE_TLS_DIRECTORY*) 
00687       ( tlsDiskOff + (Offset)mf->base_addr() );
00688 
00689    // calculate the address of the TLS callback array and make sure it's valid
00690    secn = findEnclosingRegion(tlsDir->AddressOfCallBacks - imgBase);
00691    Offset cbOffSec = tlsDir->AddressOfCallBacks 
00692       - secn->getMemOffset() 
00693       - imgBase;
00694    if (!secn || cbOffSec > secn->getDiskSize()) {
00695       return;
00696    }
00697    Offset cbOffDisk = cbOffSec + secn->getDiskOffset();
00698    PIMAGE_TLS_CALLBACK *tlsCBs = (PIMAGE_TLS_CALLBACK*) 
00699       ( cbOffDisk + (Offset)mf->base_addr() );
00700    unsigned maxCBs = (secn->getDiskSize() - cbOffSec) / sizeof(PIMAGE_TLS_CALLBACK);
00701 
00702    // for each TLS callback, add a function symbol
00703    for (unsigned tidx=0; tidx < maxCBs && tlsCBs[tidx] != NULL ; tidx++) {
00704       Offset funcOff = ((Address) tlsCBs[tidx]) - imgBase;
00705       secn = findEnclosingRegion(funcOff);
00706       if (!secn) {
00707          continue;
00708       }
00709       Offset baseAddr = 0;
00710       Object::File *pFile = curModule->GetDefaultFile();
00711       char funcName [128];
00712       snprintf(funcName, 128, "tls_cb_%d", tidx);
00713       pFile->AddSymbol( new Object::intSymbol
00714                        ( funcName,
00715                          funcOff,
00716                          Symbol::ST_FUNCTION,
00717                          Symbol::SL_GLOBAL,
00718                          0, // unknown size
00719                          secn ));
00720    }
00721 }
00722 
00723 Region::perm_t getRegionPerms(DWORD flags){
00724     if((flags & IMAGE_SCN_MEM_EXECUTE) && (flags & IMAGE_SCN_MEM_WRITE))
00725         return Region::RP_RWX;
00726     else if(flags & IMAGE_SCN_MEM_EXECUTE)
00727         return Region::RP_RX;
00728     else if(flags & IMAGE_SCN_MEM_WRITE)
00729         return Region::RP_RW;
00730     else
00731         return Region::RP_R;
00732 }
00733 
00734 Region::RegionType getRegionType(DWORD flags){
00735     if((flags & IMAGE_SCN_CNT_CODE) && (flags & IMAGE_SCN_CNT_INITIALIZED_DATA))
00736         return Region::RT_TEXTDATA;
00737     else if(flags & IMAGE_SCN_CNT_CODE)
00738         return Region::RT_TEXT;
00739     else if((flags & IMAGE_SCN_CNT_INITIALIZED_DATA) || (flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
00740         return Region::RT_DATA;
00741     else
00742         return Region::RT_OTHER;
00743 }
00744 
00745 std::vector<std::pair<string, IMAGE_IMPORT_DESCRIPTOR> > & Object::getImportDescriptorTable()
00746 {
00747    if (!idt_.empty()) {
00748       return idt_;
00749    }
00750 
00751    if (peHdr->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_IMPORT)
00752       assert(0 && "PE header doesn't specify the IDT address");
00753 
00754    //1. get the RVA of import table from Data directory
00755    DWORD dwITrva = peHdr->OptionalHeader.
00756       DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
00757    //printf("Import Table RVA: %lx\n", dwITrva);
00758 
00759    //2. get the offset in disk file
00760    DWORD dwIToffset = RVA2Offset(dwITrva);
00761    //printf("import table disk offset: %lx\n", dwIToffset);
00762 
00763    PIMAGE_IMPORT_DESCRIPTOR import_d = (PIMAGE_IMPORT_DESCRIPTOR)
00764       (((char*)mf->base_addr())+dwIToffset);
00765 
00766    while(import_d ->Name != NULL && import_d->FirstThunk !=NULL){
00767       IMAGE_IMPORT_DESCRIPTOR ie;
00768       memcpy(&ie, import_d, sizeof(IMAGE_IMPORT_DESCRIPTOR));
00769       string str((char*)(((char*)mf->base_addr())+RVA2Offset(import_d->Name)));
00770       idt_.push_back(pair<string,IMAGE_IMPORT_DESCRIPTOR>(str,ie));
00771       //printf("%s\n",ie.name);
00772       import_d ++;
00773    }
00774    return idt_;
00775    //cout<<"size of import table"<<image_import_descriptor.size()<<endl;
00776 }
00777 
00778 map<string, map<string, WORD> > & Object::getHintNameTable()
00779 {
00780    if (!hnt_.empty()) {
00781       return hnt_;
00782    }
00783 
00784    vector<pair<string, IMAGE_IMPORT_DESCRIPTOR> > idt = getImportDescriptorTable();
00785    for (vector<pair<string, IMAGE_IMPORT_DESCRIPTOR> >::iterator dit = idt.begin();
00786         dit != idt.end();
00787         dit++) 
00788    {
00789       assert(sizeof(Offset) == getAddressWidth());
00790       Offset * iat = (Offset*)((char*)mf->base_addr() + RVA2Offset(dit->second.FirstThunk));
00791 
00792       for (unsigned idx=0; iat[idx] != 0; idx++) {
00793          assert (0 == (0x80000000 & iat[idx])); //ensure IAT is not ordinal-based
00794          IMAGE_IMPORT_BY_NAME *hintName = (IMAGE_IMPORT_BY_NAME *)
00795             ((char*)mf->base_addr() + RVA2Offset(iat[idx]));
00796          hnt_[dit->first][string((char*)hintName->Name)] = hintName->Hint;
00797       }
00798    }
00799    
00800    return hnt_;
00801 }
00802 
00803 void Object::FindInterestingSections(bool alloc_syms, bool defensive)
00804 {
00805    // now that we have the file mapped, look for 
00806    // the .text and .data sections
00807    assert( peHdr == NULL );
00808    HANDLE mapAddr = mf->base_addr();
00809    peHdr = ImageNtHeader( mapAddr );
00810 
00811    if (peHdr == NULL) {
00812       code_ptr_ = (char*)mapAddr;
00813       code_off_ = 0;
00814       HANDLE hFile = mf->getFileHandle();
00815       code_len_ = mf->size();
00816       is_aout_ = false;
00817       fprintf(stderr,"Adding Symtab object with no program header, will " 
00818               "designate it as code, code_ptr_=%lx code_len_=%lx\n",
00819               code_ptr_,code_len_);
00820       if (alloc_syms) {
00821           Region *bufReg = new Region
00822                     (0, //region number
00823                      ".text", 
00824                      code_off_, // disk offset
00825                      code_len_, // disk size
00826                      code_off_, // mem offset
00827                      code_len_, // mem size
00828                      code_ptr_, // raw data ptr
00829                      Region::RP_RWX, 
00830                      Region::RT_TEXT,
00831                      true);// is loadable
00832           regions_.push_back(bufReg);
00833       }
00834       return;
00835    }
00836 
00837    assert( peHdr->FileHeader.SizeOfOptionalHeader > 0 ); 
00838 
00839    string file_ = mf->filename();
00840    curModule = new Object::Module( file_, 0 );
00841    assert( curModule != NULL );
00842 
00843    curModule->SetIsDll( (peHdr->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0 );
00844    if(curModule->IsDll())
00845       is_aout_ = false;
00846    else
00847       is_aout_ = true;
00848 
00849    getImportDescriptorTable(); //save the binary's original table, we may change it later
00850 
00851    //get exported functions
00852    // note: there is an error in the PE specification regarding the export 
00853    //       table Base.  The spec claims that you are supposed to subtract 
00854    //       the Base to get correct ordinal indices into the Export Address 
00855    //       table, but this is false, at least in the typical case for which 
00856    //       Base=1, I haven't observed any binaries with different bases
00857     if (!is_aout_ && peHdr->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXPORT) {
00858         assert(sizeof(Offset) == getAddressWidth());
00859         unsigned long size;
00860         IMAGE_EXPORT_DIRECTORY *eT2 = (IMAGE_EXPORT_DIRECTORY *)::ImageDirectoryEntryToData(mapAddr, false, IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
00861         if (eT2) {
00862             DWORD *funcNamePtrs = (DWORD *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, ULONG(eT2->AddressOfNames), NULL);
00863             DWORD *funcAddrs = (DWORD *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, ULONG(eT2->AddressOfFunctions), NULL);
00864             WORD *funcAddrNameMap = (WORD *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, ULONG(eT2->AddressOfNameOrdinals), NULL);
00865             if (funcNamePtrs && funcAddrs && funcAddrNameMap) {
00866                 for (unsigned i = 0; i < eT2->NumberOfNames; ++i) {
00867                     char *name = (char *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, funcNamePtrs[i], NULL);
00868                     int funcIndx = funcAddrNameMap[i];
00869                     Address funcAddr = funcAddrs[funcIndx];
00870                     if ((funcAddr >= (Address) eT2) &&
00871                         (funcAddr < ((Address) eT2 + size))) continue;
00872                     Symbol *sym = new Symbol(name,
00873                         Symbol::ST_FUNCTION, 
00874                         Symbol::SL_GLOBAL, 
00875                         Symbol::SV_DEFAULT,
00876                         funcAddr);
00877                     sym->setDynamic(true); // it's exported, equivalent to ELF dynamic syms
00878                     symbols_[name].push_back(sym);
00879                     symsToModules_[sym] = curModule->GetName();
00880                 }
00881             }
00882         }
00883     }
00884 
00885    SecAlignment = peHdr ->OptionalHeader.SectionAlignment;
00886    unsigned int nSections = peHdr->FileHeader.NumberOfSections;
00887    no_of_sections_ = nSections;
00888    Address prov_begin = (Address)-1;
00889    Address prov_end = (Address)-1;
00890    code_off_ = (Address)-1;
00891    code_len_ = (Address)-1;
00892 
00893    if (defensive) {
00894        // add section for peHdr, determine the size taken up by the section 
00895        // in the program's address space.  
00896        unsigned long secSize = ( peHdr->OptionalHeader.SizeOfHeaders 
00897                                  / peHdr->OptionalHeader.SectionAlignment ) 
00898                               * peHdr->OptionalHeader.SectionAlignment;
00899        if (  peHdr->OptionalHeader.SizeOfHeaders 
00900            % peHdr->OptionalHeader.SectionAlignment ) 
00901        {
00902           secSize += peHdr->OptionalHeader.SectionAlignment;
00903        }
00904        prov_begin = 0;
00905        prov_end = prov_begin + secSize;
00906        regions_.push_back(
00907            new Region(
00908             0, "PROGRAM_HEADER", 0, peHdr->OptionalHeader.SizeOfHeaders, 
00909             0, secSize, (char*)mapAddr,
00910             getRegionPerms(IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE), 
00911             getRegionType(IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA),
00912             true));
00913    }
00914 
00915    PIMAGE_SECTION_HEADER pScnHdr = (PIMAGE_SECTION_HEADER)(((char*)peHdr) + 
00916                                  sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) +
00917                                  peHdr->FileHeader.SizeOfOptionalHeader);
00918    bool foundText = false;
00919    for( unsigned int i = 0; i < nSections; i++ ) {
00920       // rawDataPtr should be set to be zero if the amount of raw data
00921       // for the section is zero
00922 
00923       Offset diskOffset = 0; 
00924       if (pScnHdr->SizeOfRawData != 0) {
00925          // the loader rounds PointerToRawData to the previous fileAlignment 
00926          // boundary  (usually 512 bytes)
00927          diskOffset = (Offset)
00928              ((pScnHdr->PointerToRawData / peHdr->OptionalHeader.FileAlignment) 
00929               * peHdr->OptionalHeader.FileAlignment);
00930       }
00931       Offset secSize = (pScnHdr->Misc.VirtualSize > pScnHdr->SizeOfRawData) ? 
00932           pScnHdr->Misc.VirtualSize : pScnHdr->SizeOfRawData;
00933       if (alloc_syms)
00934           regions_.push_back
00935               (new Region(i+1, 
00936                           (const char *)pScnHdr->Name,
00937                           diskOffset,
00938                           pScnHdr->SizeOfRawData,
00939                           pScnHdr->VirtualAddress, 
00940                           secSize,
00941                           (char *)(diskOffset + (Offset)mapAddr), 
00942                           getRegionPerms(pScnHdr->Characteristics),
00943                           getRegionType(pScnHdr->Characteristics)));
00944 //        regions_.push_back(new Section(i, (const char*)pScnHdr->Name, 
00945 //                                      pScnHdr->VirtualAddress, 
00946 //                                      pScnHdr->Misc.VirtualSize, 
00947 //                                      rawDataPtr));
00948 
00949       if( strncmp( (const char*)pScnHdr->Name, ".text", 8 ) == 0 ) {
00950          // note that section numbers are one-based
00951          textSectionId = i + 1;
00952          code_ptr_    = (char*)(((char*)mapAddr) +
00953                                 pScnHdr->PointerToRawData);
00954          code_off_    = pScnHdr->VirtualAddress;
00955 
00956          // Since we're reporting the size of sections on the disk,
00957          // we need to check whether the size of raw data is smaller.
00958          //code_len_    = pScnHdr->Misc.VirtualSize;
00959          code_len_ = ((pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize) ?
00960                       pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize);
00961 
00962          foundText = true;
00963          if (prov_begin == -1) {
00964              prov_begin = code_off_;
00965              prov_end = code_off_ + code_len_;
00966          } else {
00967              if (prov_begin > code_off_) {
00968                  prov_begin = code_off_;
00969              }
00970              if ( prov_end < (code_off_ + code_len_) ) {
00971                   prov_end = (code_off_ + code_len_);
00972              }
00973          }
00974       }
00975       else if( strncmp( (const char*)pScnHdr->Name, ".data", 8 ) == 0 ) {
00976          // note that section numbers are one-based
00977          dataSectionId = i + 1;
00978          data_ptr_    = (char *)(((char*)mapAddr) +
00979                                  pScnHdr->PointerToRawData);
00980          data_off_    = pScnHdr->VirtualAddress;
00981          data_len_ = (pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize ?
00982                       pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize);
00983          if (defensive) { // don't parse .data in a non-defensive binary
00984              if (prov_begin == -1) {
00985                 prov_begin = data_off_;
00986                 prov_end = data_off_ + data_len_;
00987              } else {
00988                  if (prov_begin > data_off_) {
00989                      prov_begin = data_off_;
00990                  }
00991                  if (prov_end < (data_off_ + data_len_)) {
00992                      prov_end = (data_off_ + data_len_);
00993                  }
00994              }
00995          }
00996       }
00997       else {
00998          Offset sec_len = (pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize) ?
00999                            pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize;
01000          if (-1 == prov_begin) {
01001             prov_begin = pScnHdr->VirtualAddress;
01002             prov_end = prov_begin + sec_len;
01003          } else {
01004              if (prov_begin > pScnHdr->VirtualAddress) {
01005                  prov_begin = pScnHdr->VirtualAddress;
01006              }
01007              if (prov_end < (pScnHdr->VirtualAddress + sec_len)) {
01008                  prov_end = (pScnHdr->VirtualAddress + sec_len);
01009              }
01010          }
01011       }
01012       pScnHdr += 1;
01013    } // end section for loop
01014 
01015    if (-1 == code_len_ || defensive) {
01016        // choose the smaller/larger of the two offsets/lengths, 
01017        // if both are initialized (i.e., are not equal to -1)
01018        if (code_off_ == -1)
01019            code_off_ = prov_begin;
01020        else if (prov_begin != -1 && 
01021                 code_off_ > prov_begin) 
01022            code_off_ = prov_begin;
01023 
01024        if (code_len_ == -1)
01025            code_len_ = prov_end - code_off_;
01026        else if (prov_end != -1 &&
01027                 code_len_ < (prov_end - code_off_))
01028            code_len_ = (prov_end - code_off_);
01029 
01030        assert(code_off_ != -1 && code_len_ != -1); // no sections in binary? 
01031    }
01032 }
01033 
01034 // Assumes region list is sorted and regions don't overlap
01035 Region *Object::findEnclosingRegion(const Offset where)
01036 {
01037     // search for "where" in regions (regions must not overlap)
01038     int first = 0; 
01039     int last = regions_.size() - 1;
01040     while (last >= first) {
01041         Region *curreg = regions_[(first + last) / 2];
01042         if (where >= curreg->getMemOffset()
01043             && where < (curreg->getMemOffset()
01044                         + curreg->getMemSize())) {
01045             return curreg;
01046         }
01047         else if (where < curreg->getMemOffset()) {
01048             last = ((first + last) / 2) - 1;
01049         }
01050         else {/* where >= (cursec->getSecAddr()
01051                            + cursec->getSecSize()) */
01052             first = ((first + last) / 2) + 1;
01053         }
01054     }
01055     return NULL;
01056 }
01057 
01058 bool Object::isForwarded( Offset addr )
01059 {
01060     //calls to forwarded symbols are routed to another dll and 
01061     //are not in the current dll's code space
01062     //we MUST NOT try to parse these - bad things happen
01063     
01064     //we detect forwarded symbols by checking if the relative 
01065     //virtual address of the symbol falls within the dll's exports section
01066     if(peHdr && peHdr->FileHeader.Characteristics & IMAGE_FILE_DLL )
01067     {
01068         PIMAGE_DATA_DIRECTORY dataDir = peHdr->OptionalHeader.DataDirectory;
01069         Offset exportStart = dataDir->VirtualAddress;
01070         Offset exportEnd = exportStart + dataDir->Size;
01071         if( addr >= exportStart && addr < exportEnd )
01072             return true;  //this sym is forwarded
01073     }
01074     return false;
01075 }
01076 
01077 bool Object::getCatchBlock(ExceptionBlock &b, Offset addr, 
01078                            unsigned size) const 
01079 { 
01080    return false; 
01081 }
01082 
01083 bool Object::isText( const Offset addr ) const 
01084 {
01085    return( addr >= code_off_ && addr < code_off_ + code_len_ );
01086 }
01087 
01088 void fixup_filename(std::string &filename)
01089 {
01090     if (filename.substr(0,22) == "\\Device\\HarddiskVolume") {
01091         TCHAR volumePath[1024];
01092         if (GetVolumePathName(filename.c_str(), volumePath, 1024)) {
01093             std::string::size_type filePathIndex = filename.find_first_of("\\/", 22);
01094             if (filePathIndex != std::string::npos)
01095                 filename = volumePath + filename.substr(++filePathIndex);
01096             else
01097                 filename = volumePath + filename.substr(23);
01098         } else {
01099             filename = "c:"+filename.substr(23);
01100         }
01101     }
01102 }
01103 
01104 Object::Object(MappedFile *mf_,
01105                bool defensive, 
01106                void (*err_func)(const char *), bool alloc_syms) :
01107     AObject(mf_, err_func),
01108     curModule( NULL ),
01109     peHdr( NULL ),
01110     trapHeaderPtr_( 0 )
01111 {
01112    FindInterestingSections(alloc_syms, defensive);
01113    if (alloc_syms && defensive) {
01114       AddTLSFunctions();
01115    }
01116    ParseSymbolInfo(alloc_syms);
01117 }
01118 
01119 SYMTAB_EXPORT ObjectType Object::objType() const 
01120 {
01121     return is_aout() ? obj_Executable : obj_SharedLib;
01122 }
01123 
01124 
01125 void Object::getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *mod_langs)
01126 {
01127     return;
01128 }
01129 
01130 struct line_info_tmp_t {
01131     line_info_tmp_t(unsigned long a, unsigned int l) {addr = a; line_no = l;}
01132     unsigned long addr;
01133     unsigned int line_no;
01134 };
01135 
01136 struct line_info_tmp_lt {
01137     bool operator()(const line_info_tmp_t &a, const line_info_tmp_t &b) {
01138       return a.addr < b.addr;
01139     };
01140 };
01141 
01142 typedef std::multiset<line_info_tmp_t, line_info_tmp_lt> info_for_file_t;
01143 typedef std::map<std::string, info_for_file_t*> info_for_all_files_t;
01144 
01145 static BOOL CALLBACK add_line_info(SRCCODEINFO *srcinfo, void *param)
01146 {
01147     info_for_all_files_t *all_info = (info_for_all_files_t *) param;
01148     info_for_all_files_t::iterator iter = all_info->find(std::string(srcinfo->FileName));
01149     info_for_file_t *finfo = NULL;
01150     if (iter == all_info->end()) {
01151         finfo = new info_for_file_t();
01152         (*all_info)[std::string(srcinfo->FileName)] = finfo;
01153     }
01154     else {
01155         finfo = (*iter).second;
01156     }
01157     finfo->insert(line_info_tmp_t((unsigned long) srcinfo->Address, srcinfo->LineNumber));
01158     return true;
01159 }
01160 
01161 static bool store_line_info(dyn_hash_map<std::string, LineInformation> *lineInfo,
01162                             info_for_all_files_t *baseInfo)
01163 {
01164    for (info_for_all_files_t::iterator i = baseInfo->begin(); i != baseInfo->end(); i++)
01165    {
01166        const char *filename = (*i).first.c_str();
01167        for (info_for_file_t::iterator j = (*i).second->begin(); j != (*i).second->end(); j++) {
01168            info_for_file_t::iterator next = j;
01169            next++;
01170            if (next != (*i).second->end())
01171                (*lineInfo)[filename].addLine(filename, j->line_no, 0, j->addr, next->addr);
01172            else
01173                (*lineInfo)[filename].addLine(filename, j->line_no, 0, j->addr, j->addr);
01174        }
01175        delete (*i).second;
01176    }
01177    return true;
01178 }
01179 
01180 void Object::parseFileLineInfo(Symtab *, dyn_hash_map<std::string, LineInformation> &li)
01181 {   
01182   int result;
01183   static Offset last_file = 0x0;
01184 
01185   Offset baseAddr = get_base_addr();
01186   if (last_file == baseAddr)
01187     return;
01188   last_file = baseAddr;
01189   info_for_all_files_t inf;
01190   result = SymEnumLines(hProc, 
01191                   baseAddr,
01192                   NULL, 
01193                   NULL,
01194                   add_line_info, 
01195                   &inf); 
01196   if (!result) {
01197     //Not a big deal. The module probably didn't have any debug information.
01198     DWORD dwErr = GetLastError();
01199     //printf("[%s:%u] - Couldn't SymEnumLines on %s in %s\n", 
01200     //     __FILE__, __LINE__, src_file_name, libname);
01201     return;
01202   }
01203   store_line_info(&li, &inf);
01204 }
01205 
01206 typedef struct localsStruct {
01207     Function *func;
01208     Offset base;
01209     HANDLE p;
01210     map<unsigned, unsigned> foundSyms;
01211     localsStruct() : foundSyms() {}
01212 } localsStruct;
01213 
01214 Dyninst::MachRegister WinConvert(Register reg) {
01215     //  Info from CV_HREG_e structure; from comments online this is correct
01216     switch(reg) {
01217     case CV_REG_EAX:
01218         return x86::eax;
01219     case CV_REG_EBX:
01220         return x86::ebx;
01221     case CV_REG_ECX:
01222         return x86::ecx;
01223     case CV_REG_EDX:
01224         return x86::edx;
01225     case CV_REG_ESP:
01226         return x86::esp;
01227     case CV_REG_EBP:
01228         return x86::ebp;
01229     case CV_REG_ESI:
01230         return x86::esi;
01231     case CV_REG_EDI:
01232         return x86::edi;
01233     default:
01234         return Dyninst::InvalidReg;
01235     }
01236 }
01237 
01238 BOOL CALLBACK enumLocalSymbols(PSYMBOL_INFO pSymInfo, unsigned long symSize,
01239                                void *userContext)
01240 {
01241     Type *type;
01242     Function *func;
01243     storageClass storage;
01244     localVar *newvar;
01245     MachRegister reg;
01246     signed long frameOffset;
01247     Offset base;
01248     HANDLE p;
01249  
01250     char *storageName;
01251     char *paramType;
01252 
01253     //
01254     //Skip this variable if it's already been found.
01255     //
01256     localsStruct *locals = (localsStruct *) userContext;
01257     if (locals->foundSyms.find(pSymInfo->Index) != locals->foundSyms.end())
01258         return true;
01259     locals->foundSyms[pSymInfo->Index] = 1;
01260     base = locals->base;
01261     func = locals->func;
01262     p = locals->p;
01263 
01264     //Get type
01265     type = getType(p, base, pSymInfo->TypeIndex, func->getModule());
01266     
01267     //Get variable storage location information
01268     if ((pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE) ||
01269         ((pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) && 
01270          (pSymInfo->Register = CV_REG_EBP)))
01271     {
01272         reg = x86::ebp;
01273         frameOffset = (signed) pSymInfo->Address;
01274         storage = storageRegOffset;
01275         storageName = "Frame Relative";
01276     }
01277     else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE)
01278     {
01279         reg = WinConvert(pSymInfo->Register);
01280         frameOffset = (signed) pSymInfo->Address;
01281         storage = storageRegOffset;
01282         storageName = "Register Relative";
01283     }
01284     else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) {
01285         reg = WinConvert(pSymInfo->Register);
01286         frameOffset = 0;
01287         storage = storageReg;
01288         storageName = "Register";
01289     }
01290     else {
01291         frameOffset = (signed) pSymInfo->Address;
01292         storage = storageAddr;
01293         storageName = "Absolute";
01294     }
01295     
01296     VariableLocation loc;
01297     loc.stClass = storage;
01298     loc.refClass = storageNoRef;
01299     loc.frameOffset = frameOffset;
01300     loc.lowPC = 0;
01301     loc.hiPC = (Address) -1;
01302     loc.mr_reg = reg;
01303     
01304     std::string vName = convertCharToString(pSymInfo->Name);
01305     std::string fName = convertCharToString(func->getModule()->fileName().c_str());
01306    newvar = new localVar(vName, type, fName, -1, func);
01307     newvar->addLocation(loc);
01308 
01309     //Store the variable as a local or parameter appropriately
01310    if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) {
01311       assert(func);
01312       if (!func->addParam(newvar)) {
01313          fprintf(stderr, "%s[%d]:  addParam failed\n", FILE__, __LINE__);
01314          return false;
01315       }
01316       paramType = "parameter";
01317    }
01318    else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) {
01319       assert(func);
01320       if (!func->addLocalVar(newvar)) {
01321          fprintf(stderr, "%s[%d]:  addLocalVar failed\n", FILE__, __LINE__);
01322          return false;
01323       }
01324       paramType = "local";
01325    }
01326    else {
01327        
01328       fprintf(stderr, "[%s:%u] - Local variable of unknown type.  %s in %s\n",
01329               __FILE__, __LINE__, pSymInfo->Name, func->getAllPrettyNames()[0].c_str());
01330       paramType = "unknown";
01331    }
01332 
01333     
01334    const char *typeName;
01335    if (type) {
01336       typeName = type->getName().c_str();
01337    }
01338    else {
01339       typeName = "unknown";
01340    }
01341    
01342    return true;
01343 }
01344 
01345 
01346 static void enumLocalVars(Function *func, 
01347                           localsStruct *locals) 
01348 {
01349     IMAGEHLP_STACK_FRAME frame;
01350     memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
01351 
01352     frame.InstructionOffset = locals->base + func->getOffset();
01353     int result = SymSetContext(locals->p, &frame, NULL);
01354     /*if (!result) {            
01355         fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
01356         printSysError(GetLastError());
01357     }*/
01358     result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
01359     /*if (!result) {
01360         fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
01361         printSysError(GetLastError());
01362     }*/
01363     
01364     if(func->getSize())
01365     {
01366         memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
01367 
01368         frame.InstructionOffset = locals->base +
01369                     func->getOffset() + 
01370                     func->getSize();
01371         result = SymSetContext(locals->p, &frame, NULL);
01372         result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
01373     }
01374 
01375 //TODO?? replace this with??
01376 #if 0
01377     for (unsigned i=0; i<points.size(); i++) {
01378         frame.InstructionOffset = points[i]->addr();
01379         bool result = SymSetContext(locals->p, &frame, NULL);
01380         /*if (!result) {            
01381             fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
01382             printSysError(GetLastError());
01383         }*/
01384         result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
01385         /*if (!result) {
01386             fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
01387             printSysError(GetLastError());
01388         }*/
01389     }
01390 #endif
01391 
01392 }
01393 
01394 static int variantValue(VARIANT *v) {
01395     switch(v->vt) {    
01396        case VT_I8:
01397            return (int) v->llVal;
01398        case VT_I4:
01399            return (int) v->lVal;
01400        case VT_UI1:
01401            return (int) v->bVal;
01402        case VT_I2:
01403            return (int) v->iVal;
01404        case VT_I1:
01405            return (int) v->cVal;
01406        case VT_UI2:
01407            return (int) v->uiVal;
01408        case VT_UI4:
01409            return (int) v->ulVal;
01410        case VT_UI8:
01411            return (int) v->ullVal;
01412        case VT_INT:
01413            return (int) v->intVal;
01414        case VT_UINT:
01415            return (int) v->uintVal;
01416        default:
01417            return 0;
01418     }
01419 }
01420 
01421 // Changed. Not adding to stdTypes now
01422 static void addTypeToCollection(Type *type, Module *mod) 
01423 {
01424     typeCollection *tc = typeCollection::getModTypeCollection(mod);
01425     assert(tc);
01426     tc->addType(type);
01427 /*     
01428    typeCollection *collection;
01429 
01430    collection = mod ? tc : Symtab::stdTypes;
01431    assert(collection);
01432    assert(!collection->findType(type->getID()));
01433    collection->addType(type);
01434 */
01435 }
01436 
01437 static char *getTypeName(HANDLE p, Offset base, int typeIndex) {
01438     int result, length;
01439     WCHAR *wname = NULL;
01440     char *name = NULL;
01441 
01442     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMNAME, &wname);
01443     if (!result) 
01444         return NULL;
01445     length = wcslen(wname) + 1;
01446     name = (char *) malloc(length + 1);
01447     result = WideCharToMultiByte(CP_ACP, 0, wname, -1, name, length, NULL, NULL);
01448     LocalFree(wname); 
01449     if (!result) {
01450         int lasterror = GetLastError();
01451 //        printSysError(lasterror);
01452         return NULL;
01453     }
01454     return name;
01455 }
01456 
01457 static dataClass getDataClass(HANDLE p, Offset base, int typeIndex) {
01458     enum SymTagEnum wintype;
01459     int result, basetype;
01460 
01461     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &wintype);
01462     if (!result)
01463         return dataUnknownType;
01464     switch (wintype) {
01465         case SymTagFunction:
01466         case SymTagFunctionType:
01467             return dataFunction;
01468         case SymTagPointerType:
01469             return dataPointer;
01470         case SymTagArrayType:
01471             return dataArray;
01472         case SymTagBaseType:
01473             return dataScalar;
01474         case SymTagEnum:
01475             return dataEnum;
01476         case SymTagTypedef:
01477             return dataTypedef;
01478         case SymTagUDT:
01479             enum UdtKind udtType;
01480             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
01481             if (!result)
01482                 return dataUnknownType;
01483             switch (udtType) {
01484                 case UdtUnion:
01485                     return dataUnion;
01486                 case UdtStruct:
01487                 case UdtClass:
01488                     return dataStructure;
01489                 default:
01490                     return dataUnknownType;
01491             }
01492         case SymTagFunctionArgType:
01493             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &basetype);
01494             if (!result)
01495                 return dataUnknownType;
01496             return getDataClass(p, base, basetype);
01497         default:
01498             return dataUnknownType;
01499     }
01500 }
01501 
01502 static Type *getEnumType(HANDLE p, Offset base, int typeIndex, Module *mod) {
01503     unsigned i;
01504     char *name = NULL;
01505     char *entryName = NULL;
01506     VARIANT entryValue;
01507     typeEnum *type;
01508     int result;
01509     unsigned numEntries, entriesSize;
01510     TI_FINDCHILDREN_PARAMS *entries = NULL;
01511 
01512     name = getTypeName(p, base, typeIndex);
01513     std::string tName = convertCharToString(name);
01514     type = new typeEnum(typeIndex, tName);
01515     addTypeToCollection(type, mod);
01516     free(name);
01517     name = NULL;
01518 
01519     //
01520     //Get the number of entries in this enum, and store them in the entries structure
01521     //
01522     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numEntries);
01523     if (!result)
01524         numEntries = 0;
01525     if (numEntries) {
01526         entriesSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numEntries + 1) * sizeof(ULONG);
01527         entries = (TI_FINDCHILDREN_PARAMS *) malloc(entriesSize);
01528         memset(entries, 0, entriesSize);
01529         entries->Count = numEntries;
01530         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, entries);
01531         if (!result)
01532             numEntries = 0;
01533     }
01534 
01535     for (i=0; i<numEntries; i++) {
01536         entryName = getTypeName(p, base, entries->ChildId[i]);
01537         VariantInit(&entryValue);
01538         result = SymGetTypeInfo(p, base, entries->ChildId[i], TI_GET_VALUE, &entryValue);
01539         if (!result)
01540             continue;
01541         type->addConstant(entryName, variantValue(&entryValue));
01542     }
01543   
01544     if (entries)
01545         free(entries);
01546     return type;    
01547 }
01548 
01549 static Type *getPointerType(HANDLE p, Offset base, int typeIndex, Module *mod) {
01550     int baseTypeIndex, result;
01551     Type *baseType;
01552     typePointer *newType;
01553 
01554     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
01555     if (!result) {
01556         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
01557         return NULL;
01558     }
01559 
01560     //
01561     // Add a place-holder for the pointer type first and fill in it's 
01562     //  base type latter.  This prevents recursion that may happen beneath 
01563     //  the getType function call below.
01564     //
01565     newType = new typePointer(typeIndex, NULL);
01566     addTypeToCollection(newType, mod);
01567 
01568     baseType = getType(p, base, baseTypeIndex, mod);
01569     if (!baseType) {
01570         fprintf(stderr, "[%s:%u] - getType failed\n", __FILE__, __LINE__);
01571         return NULL;
01572     }
01573 
01574     newType->setPtr(baseType);
01575     return newType;
01576 }
01577 
01578 static Type *getArrayType(HANDLE p, Offset base, int typeIndex, Module *mod) {
01579     int result, baseIndex, index;
01580     Type *indexType, *newType, *baseType;
01581     unsigned size, num_elements;
01582     ULONG64 size64;
01583     std::string bname;
01584     std::string name;
01585 
01586     //Get the index type (usually an int of some kind).  Currently not used.
01587     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_ARRAYINDEXTYPEID, &index);
01588     if (!result) {
01589         fprintf(stderr, "[%s:%u] - TI_GET_ARRAYINDEXTYPEID failed\n", 
01590                 __FILE__, __LINE__);
01591         return NULL;
01592     }
01593     indexType = getType(p, base, index, mod);
01594 
01595     //Get the base type (the type of the elements in the array)
01596     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseIndex);
01597     if (!result) {
01598         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
01599         return NULL;
01600     }
01601     baseType = getType(p, base, baseIndex, mod);
01602 
01603     bname = baseType->getName();
01604     name = bname + "[]";
01605     
01606     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
01607     if (!result) {
01608         num_elements = 0;
01609     }
01610     else {
01611       size = (unsigned) size64;
01612       num_elements = size / baseType->getSize();
01613     }
01614 
01615     newType = new typeArray(typeIndex, baseType, 0, num_elements-1, name);
01616     newType->getSize();
01617     addTypeToCollection(newType, mod);
01618     assert(newType->getID() == typeIndex);
01619 
01620     return newType;
01621 }
01622 
01623 
01624 static Type *getTypedefType(HANDLE p, Offset base, int typeIndex, Module *mod) {
01625     int result, baseTypeIndex;
01626     Type *baseType, *newType;
01627     char *name;
01628 
01629     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
01630     if (!result) {
01631         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
01632         return NULL;
01633     }
01634     baseType = getType(p, base, baseTypeIndex, mod);
01635     if (!baseType) {
01636         return NULL;
01637     }
01638  
01639     name = getTypeName(p, base, typeIndex);
01640     std::string tName = convertCharToString(name);
01641     newType = new typeTypedef(typeIndex, baseType, tName);
01642     addTypeToCollection(newType, mod);
01643     return newType;
01644 }
01645 
01646 static Type *getUDTType(HANDLE p, Offset base, int typeIndex, Module *mod) {
01647     int result, symtag;
01648     unsigned size, numChildren, childrenSize, child_offset, i, child_size;
01649     fieldListType *newType;
01650     UINT64 size64;
01651     const char *name, *childName;
01652     enum UdtKind udtType;
01653     TI_FINDCHILDREN_PARAMS *children = NULL;
01654 
01655     //
01656     // Get name for structure
01657     //
01658     name = getTypeName(p, base, typeIndex);
01659     std::string tName = convertCharToString(name);
01660     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
01661     if (!result) {
01662         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
01663         return NULL;
01664     }
01665     size = (unsigned) size64;
01666 
01667     //
01668     // Determine whether it's a class, struct, or union and create the 
01669     //  new_type appropriately
01670     //
01671     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
01672     if (!result) {
01673         fprintf(stderr, "[%s:%u] - TI_GET_UDTKIND returned error\n");
01674         return NULL;
01675     }
01676     switch (udtType) {
01677         case UdtUnion:
01678             newType = new typeUnion(typeIndex, tName);
01679             break;
01680         case UdtStruct:
01681         case UdtClass:
01682         default:
01683             newType = new typeStruct(typeIndex, tName);
01684             break;
01685     }
01686     addTypeToCollection(newType, mod);
01687     if (name)
01688        free((void *) name);
01689     name = NULL;
01690 
01691 
01692     //
01693     // Store the number of member variables/functions/stuff in numChildren
01694     //
01695     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numChildren);
01696     if (!result)
01697         numChildren = 0;
01698     //
01699     // Get the list of variables/functions/stuff
01700     //
01701     if (numChildren) {
01702         childrenSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numChildren + 1) * sizeof(ULONG);
01703         children = (TI_FINDCHILDREN_PARAMS *) malloc(childrenSize);
01704         memset(children, 0, childrenSize);
01705         children->Count = numChildren;
01706         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, children);
01707         if (!result)
01708             numChildren = 0;
01709     }
01710 
01711     //
01712     // Create/Find the type of each child and add it to newType appropriately
01713     //
01714     for (i=0; i<numChildren; i++) {
01715         // Create/Get child type
01716         Type *child_type = getType(p, base, children->ChildId[i], mod);
01717         if (!child_type)
01718             continue;
01719 
01720         // Figure out a name of this object
01721         childName = NULL;
01722         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_SYMTAG, &symtag);
01723         if (result && symtag == SymTagBaseClass) {
01724             childName = P_strdup("{superclass}");
01725         }
01726         if (!childName)
01727             childName = getTypeName(p, base, children->ChildId[i]);
01728         if (!childName) 
01729             childName = P_strdup(child_type->getName().c_str());
01730 
01731         // Find the offset of this member in the structure
01732         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_OFFSET, &child_offset);
01733         if (!result) {
01734             child_offset = 0; //Probably a member function
01735             child_size = 0;
01736         }
01737         else {
01738             child_offset *= 8; //Internally measured in bits
01739             child_size = child_type->getSize();
01740         }
01741 
01742         std::string fName = convertCharToString(childName);
01743         newType->addField(fName, child_type, child_offset);
01744         if (childName)
01745             free((void *) childName);
01746         childName = NULL;
01747     }
01748 
01749     if (children)
01750         free(children);
01751 
01752     return newType;
01753 }
01754 
01755 static Type *getLayeredType(HANDLE p, Offset base, int typeIndex, Module *mod) {
01756     int result, newTypeIndex;
01757     Type *newType;
01758 
01759     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &newTypeIndex);
01760     if (!result) {
01761         fprintf(stderr, "TI_GET_TYPEID failed\n");
01762         return NULL;
01763     }
01764 
01765     newType = getType(p, base, newTypeIndex, mod);
01766     return newType;
01767 }
01768 
01769 static Type *getFunctionType(HANDLE p, Offset base, int typeIndex, Module *mod) {
01770     int result, retTypeIndex;
01771     typeFunction *newType;
01772     Type *retType;
01773     unsigned num_params, args_size, i;
01774     std::vector<Type *> params;
01775     TI_FINDCHILDREN_PARAMS *args = NULL;
01776     std::string name;
01777 
01778     //Create the function early to avoid recursive references
01779     std::string tName = "";
01780     newType = new typeFunction(typeIndex, NULL, tName);
01781     addTypeToCollection(newType, mod);
01782 
01783     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &retTypeIndex);
01784     if (!result) {
01785         fprintf(stderr, "[%s:%u] - Couldn't TI_GET_TYPEID\n", __FILE__, __LINE__);
01786         return NULL;
01787     }
01788 
01789     retType = getType(p, base, retTypeIndex, mod);
01790     if (!retType) {
01791         return NULL;
01792     }
01793     newType->setRetType(retType);
01794 
01795     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_COUNT, &num_params);
01796     if (!result)
01797         goto done_params;
01798 
01799     args_size = sizeof(TI_FINDCHILDREN_PARAMS) + (num_params + 1) * sizeof(ULONG);
01800     args = (TI_FINDCHILDREN_PARAMS *) malloc(args_size);
01801     memset(args, 0, args_size);
01802     args->Count = num_params;
01803     result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, args);
01804     if (!result)
01805         goto done_params;
01806     
01807     for (i=0; i<num_params; i++) {
01808         Type *arg_type = getType(p, base, args->ChildId[i], mod);
01809         if (!arg_type) {
01810             continue;
01811         }
01812         params.push_back(arg_type);
01813     }
01814 
01815 done_params:
01816 
01817     //
01818     // Build a type name that looks like the following:
01819     //   (return_type)(param1_type, param2_type, ...)
01820     name = "(";
01821     name += retType->getName();
01822     name += ")(";
01823     for (i=0; i<params.size(); i++) {
01824         if (i != 0)
01825             name += ", ";
01826         name += params[i]->getName();
01827     }
01828     name += "()";
01829     
01830     std::string newName = name;
01831     newType->setName(newName);
01832 
01833     for (i=0; i<params.size(); i++) {
01834         //TODO?? have a name for the parameter. Required??
01835         newType->addParam(params[i]);
01836     }
01837 
01838     if (args)
01839         free(args);
01840 
01841     return newType;
01842 }
01843 
01844 static Type *getBaseType(HANDLE p, Offset base, int typeIndex, Module *mod) {
01845     BasicType baseType;
01846     int result;
01847     ULONG64 size64;
01848     unsigned size;
01849     Type *newType;
01850 
01851     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_BASETYPE, &baseType);
01852     if (!result) {
01853         fprintf(stderr, "[%s:%u] - TI_GET_BASETYPE return error\n");
01854         return NULL;
01855     }
01856 
01857     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
01858     if (!result) {
01859         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
01860         return NULL;
01861     }
01862     size = (unsigned) size64;
01863     switch(baseType) {
01864      case btNoType:
01865          newType = NULL;
01866          break;
01867      case btVoid:
01868          newType = new typeScalar(typeIndex, size, "void");
01869          break;
01870      case btChar:
01871          newType = new typeScalar(typeIndex, size, "char");
01872          break;
01873      case btWChar:
01874          newType = new typeScalar(typeIndex, size, "wchar");
01875          break;
01876      case btInt:
01877          if (size == 8)
01878            newType = new typeScalar(typeIndex, size, "long long int");
01879          else if (size == 4)
01880            newType = new typeScalar(typeIndex, size, "int");
01881          else if (size == 2)
01882            newType = new typeScalar(typeIndex, size, "short");
01883          else if (size == 1)
01884            newType = new typeScalar(typeIndex, size, "char");
01885          else
01886            newType = new typeScalar(typeIndex, size, "");
01887          break;
01888      case btUInt:
01889          if (size == 8)
01890            newType = new typeScalar(typeIndex, size, "unsigned long long int");
01891          else if (size == 4)
01892            newType = new typeScalar(typeIndex, size, "unsigned int");
01893          else if (size == 2)
01894            newType = new typeScalar(typeIndex, size, "unsigned short");
01895          else if (size == 1)
01896            newType = new typeScalar(typeIndex, size, "unsigned char");
01897          else
01898            newType = new typeScalar(typeIndex, size, "");
01899          break;
01900      case btFloat:
01901          if (size == 8)
01902              newType = new typeScalar(typeIndex, size, "double");
01903          else
01904              newType = new typeScalar(typeIndex, size, "float");
01905          break;
01906      case btBCD:
01907          newType = new typeScalar(typeIndex, size, "BCD");
01908          break;
01909      case btBool:
01910          newType = new typeScalar(typeIndex, size, "bool");
01911          break;
01912      case btLong:
01913          newType = new typeScalar(typeIndex, size, "long");
01914          break;
01915      case btULong:
01916          newType = new typeScalar(typeIndex, size, "unsigned long");
01917          break;
01918      case btCurrency:
01919          newType = new typeScalar(typeIndex, size, "currency");
01920          break;
01921      case btDate:
01922          newType = new typeScalar(typeIndex, size, "Date");
01923          break;
01924      case btVariant:
01925          newType = new typeScalar(typeIndex, size, "variant");
01926          break;
01927      case btComplex:
01928          newType = new typeScalar(typeIndex, size, "complex");
01929          break;
01930      case btBit:
01931          newType = new typeScalar(typeIndex, size, "bit");
01932          break;
01933      case btBSTR:
01934          newType = new typeScalar(typeIndex, size, "bstr");
01935          break;
01936      case btHresult:
01937          newType = new typeScalar(typeIndex, size, "Hresult");
01938          break;
01939      default:
01940          fprintf(stderr, "Couldn't parse baseType %d for %d\n", baseType, typeIndex);
01941          assert(0);
01942          break;
01943    }
01944    if (newType)
01945        addTypeToCollection(newType, mod);
01946    return newType;
01947 }
01948 
01949 static Type *getType(HANDLE p, Offset base, int typeIndex, Module *mod) 
01950 {
01951    static unsigned depth = 0;
01952    BOOL result;
01953    Type *foundType = NULL;
01954    typeCollection *collection;
01955    enum SymTagEnum symtag;
01956 
01957    if (!typeIndex)
01958        return NULL;
01959 
01960    //
01961    // Check if this type has already been created (they're indexed by typeIndex).
01962    // If it has, go ahead and return the existing one.
01963    // If not, then start creating a new type.
01964    //
01965    if (mod)
01966        collection = typeCollection::getModTypeCollection(mod);
01967    else
01968        collection = (typeCollection*)Symtab::stdTypes;
01969    assert(collection);
01970 
01971 
01972    //
01973    // Check to see if we've already parsed this type
01974    //
01975    foundType = collection->findType(typeIndex);
01976    if (foundType) {
01977        return foundType;
01978    }
01979 
01980    //
01981    // Types on Windows are stored as part of a special type of symbol.  TI_GET_SYMTAG 
01982    // Gets the meta information about the type.
01983    //
01984    result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &symtag);
01985    if (!result) {
01986        depth--;
01987        return NULL;
01988    }
01989    switch (symtag) {
01990        case SymTagBaseType:
01991            foundType = getBaseType(p, base, typeIndex, mod);
01992            break;
01993        case SymTagEnum:
01994            foundType = getEnumType(p, base, typeIndex, mod);
01995            break;
01996        case SymTagFunctionType:
01997            foundType = getFunctionType(p, base, typeIndex, mod);
01998            break;
01999        case SymTagPointerType:
02000            foundType = getPointerType(p, base, typeIndex, mod);
02001            break;
02002        case SymTagArrayType:
02003            foundType = getArrayType(p, base, typeIndex, mod);
02004            break;
02005        case SymTagTypedef:
02006            foundType = getTypedefType(p, base, typeIndex, mod);
02007            break;
02008        case SymTagUDT:
02009            foundType = getUDTType(p, base, typeIndex, mod);
02010            break;
02011        case SymTagFunctionArgType:
02012        case SymTagData:
02013        case SymTagFunction:
02014        case SymTagBaseClass:
02015            foundType = getLayeredType(p, base, typeIndex, mod);
02016            if (foundType)
02017              typeIndex = foundType->getID();
02018            break;
02019        case SymTagThunk:
02020            foundType = NULL;
02021            break;
02022        case SymTagVTableShape:
02023        case SymTagVTable:
02024            break;
02025        default:
02026            fprintf(stderr, "Unknown type %d\n", symtag);
02027            assert(0);
02028            foundType = NULL;
02029            break;
02030    }
02031 
02032    return foundType;
02033 }
02034 
02035 typedef struct proc_mod_pair {
02036     HANDLE handle;
02037     Symtab *obj;
02038     Offset base_addr;
02039 } proc_mod_pair;
02040 
02041 static void findLocalVars(Function *func, proc_mod_pair base) {
02042     Module *mod = func->getModule();
02043     localsStruct locals;
02044     HANDLE p = base.handle;
02045 
02046     locals.func = func;
02047     locals.base = base.base_addr;
02048     locals.p = p;
02049 
02050     enumLocalVars(func, &locals);
02051     //
02052     // The windows debugging interface allows us to get local variables
02053     // at specific points, which makes it hard to enumerate all locals (as we want).
02054     // Instead we'll get the local variables at the most common points below.
02055     //
02056     //TODO?
02057     //=const std::vector<instPoint*> &points = ifunc->funcEntries();
02058     //=enumLocalVars(func, ifunc->funcEntries(), &locals);
02059     //=enumLocalVars(func, ifunc->funcExits(), &locals);
02060     //=enumLocalVars(func, ifunc->funcCalls(), &locals);
02061     //=enumLocalVars(func, ifunc->funcArbitraryPoints(), &locals);
02062 }
02063 
02064 BOOL CALLBACK add_type_info(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, void *info)
02065 {
02066    HANDLE p;
02067    Offset obj_base;
02068    proc_mod_pair *pair;
02069    Symtab *obj;
02070    Type *type;
02071    char *name;
02072    Address addr;
02073 
02074    if (!isGlobalSymbol(pSymInfo)) {
02075        //We do local symbols elsewhere
02076        return TRUE;
02077    }
02078 
02079    pair = (proc_mod_pair *) info;
02080    p = pair->handle;
02081    obj_base = pair->base_addr;
02082    obj = pair->obj;
02083    name = pSymInfo->Name;
02084    addr = (Address) pSymInfo->Address - obj_base;
02085 
02086    std::vector<Module *> mods;
02087    Module *mod;
02088    //TODO?? change later
02089    if(!obj->getAllModules(mods))
02090    {
02091        return true;
02092    }
02093    else
02094        mod = mods[0];
02095    
02096    if (obj->isExec()) {
02097       //When parsing the a.out, sort the type information into specific modules.  This doesn't matter
02098       // for libraries, because there is a 1:1 mapping between modules and objects.
02099       //
02100       //A module is a collection of functions, but doesn't include global data types.  Global variables
02101       // will go into the DEFAULT_MODULE
02102         Function *f = NULL;
02103        if(obj->findFuncByEntryOffset(f, (Offset) pSymInfo->Address))
02104        {
02105          //No containing module.  Only insert this into DEFAULT_MODULE
02106           if (strcmp(f->getModule()->fileName().c_str(), "DEFAULT_MODULE"))
02107               return true;
02108       }
02109    }
02110 
02111    type = getType(p, obj_base, pSymInfo->TypeIndex, mod);
02112 
02113    
02114 //   fprintf(stderr, "[%s:%u] - Variable %s had type %s\n", __FILE__, __LINE__,
02115 //       name, type ? type->getName().c_str() : "{NO TYPE}");
02116    
02117    if (type)
02118    {
02119       Variable *var = NULL;
02120       bool result = obj->findVariableByOffset(var, addr);
02121       if (result) {
02122          var->setType(type);
02123       }
02124       if (name) {
02125          std::string vName = name;
02126          typeCollection *tc = typeCollection::getModTypeCollection(mod);
02127          assert(tc);
02128          tc->addGlobalVariable(vName, type);
02129       }
02130    }
02131    return TRUE;
02132 }
02133 
02134 void Object::parseTypeInfo(Symtab *obj) {
02135     proc_mod_pair pair;
02136     BOOL result;
02137     //
02138     //Parse global variable type information
02139     //
02140 
02141     pair.handle = hProc;
02142     pair.obj = obj;
02143     pair.base_addr = getBaseAddress();
02144     
02145     if (!pair.base_addr) {
02146         pair.base_addr = getLoadAddress();
02147     }
02148   
02149    HANDLE mapAddr = mf->base_addr();
02150     result = SymEnumSymbols(hProc, (DWORD64)mapAddr, NULL, 
02151                             add_type_info, &pair);
02152     if (!result){
02153         printSysError(GetLastError());
02154 //        parsing_printf("SymEnumSymbols was unsuccessful.  Type info may be incomplete\n");
02155     }
02156 
02157     //
02158     // Parse local variables and local type information
02159     //
02160     std::vector<Function *> funcs;
02161     obj->getAllFunctions(funcs);
02162     for (unsigned i=0; i < funcs.size(); i++) {
02163         findLocalVars(funcs[i], pair);
02164     }
02165 }
02166 
02167 bool AObject::getSegments(vector<Segment> &segs) const
02168 {
02169     for(unsigned int i=0; i<regions_.size(); i++){
02170         Segment seg;
02171         seg.data = regions_[i]->getPtrToRawData();
02172         //seg.loadaddr = regions_[i] -> getDiskOffset();
02173         seg.loadaddr = regions_[i] -> getMemOffset();
02174         seg.size = regions_[i] -> getDiskSize();
02175         seg.name = regions_[i] -> getRegionName();
02176         //seg.segFlags = 
02177         segs.push_back(seg);
02178     }
02179     return true;
02180 }
02181 
02182 bool Object::emitDriver(Symtab *obj, string fName, std::vector<Symbol *>&allSymbols, 
02183                         unsigned flag) 
02184 {
02185     emitWin *em = new emitWin((PCHAR)GetMapAddr(), this, err_func_);
02186     return em -> driver(obj, fName);
02187 }
02188 
02189 // automatically discards duplicates
02190 void Object::addReference(Offset off, std::string lib, std::string fun){
02191    ref[lib][off] = fun;
02192 }
02193                         
02194 // retrieve Section Number for an image offset
02195 // dwRO - the image offset to calculate
02196 // returns -1 if an error occurred else returns the corresponding section number
02197 DWORD Object::ImageOffset2SectionNum(DWORD dwRO)
02198 {
02199    PIMAGE_SECTION_HEADER sectionHeader = 
02200       (PIMAGE_SECTION_HEADER)((DWORD)peHdr 
02201                               + sizeof(DWORD) // PE signature
02202                               + sizeof(IMAGE_FILE_HEADER) 
02203                               + peHdr->FileHeader.SizeOfOptionalHeader);
02204     unsigned int SecCount = peHdr ->FileHeader.NumberOfSections;
02205     for(unsigned int i=0;i < SecCount; i++)
02206     {
02207         if((dwRO>=sectionHeader->PointerToRawData) && (dwRO<(sectionHeader->PointerToRawData+sectionHeader->SizeOfRawData)))
02208         {
02209             return (i);
02210         }
02211         sectionHeader++;
02212     }
02213     return(-1);
02214 }
02215 
02216 PIMAGE_SECTION_HEADER Object::ImageOffset2Section(DWORD dwRO)
02217 {
02218    PIMAGE_SECTION_HEADER sectionHeader = 
02219       (PIMAGE_SECTION_HEADER)((DWORD)peHdr 
02220                               + sizeof(DWORD) // PE signature
02221                               + sizeof(IMAGE_FILE_HEADER) 
02222                               + peHdr->FileHeader.SizeOfOptionalHeader);
02223     unsigned int SecCount = peHdr ->FileHeader.NumberOfSections;
02224 
02225     for(unsigned int i=0;i<SecCount;i++)
02226     {
02227         if((dwRO >= sectionHeader->PointerToRawData) && 
02228            (dwRO < (sectionHeader->PointerToRawData + sectionHeader->SizeOfRawData)))
02229         {
02230             return sectionHeader;
02231         }
02232         sectionHeader++;
02233     }
02234     return(NULL);
02235 }
02236 
02237 PIMAGE_SECTION_HEADER Object::ImageRVA2Section(DWORD dwRVA)
02238 {
02239    PIMAGE_SECTION_HEADER sectionHeader = 
02240       (PIMAGE_SECTION_HEADER)((DWORD)peHdr 
02241                               + sizeof(DWORD) // PE signature
02242                               + sizeof(IMAGE_FILE_HEADER) 
02243                               + peHdr->FileHeader.SizeOfOptionalHeader);
02244     unsigned int SecCount = peHdr ->FileHeader.NumberOfSections;
02245 
02246     for(unsigned int i=0;i<SecCount;i++)
02247     {
02248         if((dwRVA>=sectionHeader->VirtualAddress) && (dwRVA<=(sectionHeader->VirtualAddress+sectionHeader->SizeOfRawData)))
02249         {
02250             return sectionHeader;
02251         }
02252         sectionHeader++;
02253     }
02254     return(NULL);
02255 }
02256 
02257 DWORD Object::RVA2Offset(DWORD dwRVA)
02258 {
02259     DWORD offset;
02260     PIMAGE_SECTION_HEADER section = ImageRVA2Section(dwRVA);
02261     if(section==NULL)
02262     {
02263         return(0);
02264     }
02265     offset=dwRVA+section->PointerToRawData-section->VirtualAddress;
02266     return offset;
02267 }
02268 
02269 DWORD Object::Offset2RVA(DWORD dwRO)
02270 {
02271     PIMAGE_SECTION_HEADER section = ImageOffset2Section(dwRO);
02272     if(section==NULL)
02273     {
02274         return(0);
02275     }
02276     return(dwRO+section->VirtualAddress-section->PointerToRawData);
02277 }
02278 
02279 void Object::setTrapHeader(Offset addr)
02280 {
02281    trapHeaderPtr_ = addr;
02282 }
02283 Offset Object::trapHeader()
02284 {
02285    return trapHeaderPtr_;
02286 }
02287 
02288 void Object::insertPrereqLibrary(std::string lib)
02289 {
02290    // must include some function from the library for Windows to load it
02291    ref[lib] = std::map<Offset, std::string>();
02292 }
02293 
02294  bool Region::isStandardCode()
02295 {
02296    return (getRegionPermissions() == RP_RX ||
02297            getRegionPermissions() == RP_RWX);
02298 }
02299 
02300 Dyninst::Architecture Object::getArch()
02301 {
02302    return Dyninst::Arch_x86;
02303 }
02304 
02305 /*
02306     for(it=ref.begin(); it!=ref.end(); it++){
02307         IMAGE_IMPORT_DESCRIPTOR newID;
02308         newID.ForwarderChain=0;
02309         newID.TimeDateStamp=0;
02310         newID.OriginalFirstThunk = 0;
02311         newID.FirstThunk = (*it).first;
02312         //printf("IAT address: %x\n", newID.FirstThunk);
02313 
02314         //look through the old import table to check if the library has been there
02315         bool isExisting = false;
02316         for(unsigned int i=0; i<oldImp.size(); i++){
02317 
02318             //if already been there, use the same of RVA of name
02319             if(strcmp(oldImp[i].name, (*it).second.first.c_str()) == 0){
02320                 isExisting = true;
02321                 newID.Name = oldImp[i].id.Name;
02322                 break;
02323             }
02324         }   
02325 
02326         char* ptrLib;
02327         unsigned long strLen;
02328         //otherwise, it's a new library
02329         if(!isExisting){
02330             newID.Name = strOff;
02331             strLen =(*it).second.first.size();
02332             //library name must be '\0' terminated, so len plus one
02333             ptrLib = (char*) GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, strLen+1);
02334             memcpy(ptrLib,(*it).second.first.c_str(), strLen);
02335             info.push_back(std::pair<char*,unsigned long> (ptrLib, strLen+1));
02336             strOff+=(strLen+1);
02337         }
02338 
02339         memcpy(newIT+pos*sizeof(IMAGE_IMPORT_DESCRIPTOR),(char*)&newID, sizeof(IMAGE_IMPORT_DESCRIPTOR));
02340 
02341         //write the pointer to function name into (*it).first
02342         Offset o = (Offset)((char*)dynSec->getPtrToRawData())+(*it).first-dynSec->getMemOffset();
02343         printf("Offset to write the pointer to function name: %x\n", o);
02344         memcpy(((char*)dynSec->getPtrToRawData())+(*it).first-dynSec->getMemOffset(), (char*)&strOff, 4);
02345         strLen = (*it).second.second.size();
02346     
02347         //functin name must start with a two byte hint
02348         //function name also '0\' terminated
02349         ptrLib = (char*)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, 2+strLen+1);
02350         memcpy(ptrLib+2, (*it).second.second.c_str(), strLen);
02351         info.push_back(std::pair<char*, unsigned long> (ptrLib, strLen+3));
02352         strOff+=(2+strLen+1);
02353 
02354         pos++;
02355     }
02356 */
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on 12 Jul 2013 for SymtabAPI by  doxygen 1.6.1