Fix missing parameter name from inline wrapper
[dyninst.git] / symtabAPI / src / Object-nt.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  * 
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  * 
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  * 
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  * 
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  * 
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30                              
31 #define WIN32_LEAN_AND_MEAN
32
33 #include <windows.h>
34 #include <cvconst.h>
35 #include <oleauto.h>
36 #if !defined __out_ecount_opt
37 #define __out_ecount_opt(x)
38 #endif
39 #include <dbghelp.h>
40
41 #include <iostream>
42 #include <iomanip>
43 #include <limits.h>
44 #include <crtdbg.h>
45 #include <winnt.h>
46
47 #include "symtabAPI/src/Object.h"
48 #include "symtabAPI/src/Object-nt.h"
49
50 #include "LineInformation.h"
51 #include "Collections.h"
52 #include "Symtab.h"
53 #include "Module.h"
54 #include "Function.h"
55 #include "Variable.h"
56 #include "emitWin.h"
57
58 #include "common/src/headers.h"
59
60 #if defined(_MSC_VER)
61 #define snprintf _snprintf
62 #endif
63
64 using namespace Dyninst;
65 using namespace Dyninst::SymtabAPI;
66
67 Type *getType(HANDLE p, Offset mod_base, int typeIndex, Module *mod = NULL);
68 bool pd_debug_export_symbols = false;
69 using namespace std;
70
71 std::string convertCharToString(const char *ptr){
72     std::string str;
73     if(ptr)
74         str = ptr;
75     else
76         str = "";
77     return str;
78 }
79
80 static void printSysError(unsigned errNo) {
81     char buf[1000];
82         
83         int result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNo,
84                                                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
85                                                                 buf, 1000, NULL);
86     if (!result) {
87         fprintf(stderr, "Couldn't print error message\n");
88                 printSysError(GetLastError());
89     }
90     fprintf(stderr, "*** System error [%d]: %s\n", errNo, buf);
91     fflush(stderr);
92 }
93
94 //---------------------------------------------------------------------------
95 // prototypes of functions used in this file
96 //---------------------------------------------------------------------------
97 BOOL CALLBACK SymEnumSymbolsCallback( PSYMBOL_INFO pSymInfo,
98                                                                                 ULONG symSize,
99                                                                                 PVOID userContext );
100 /*
101  * stripAtSuffix 
102  *
103  * Strips off of a string any suffix that consists of an @ sign followed by
104  * decimal digits.
105  *
106  * str  The string to strip the suffix from.  The string is altered in place.
107  */
108  static void stripAtSuffix(char *str)
109  {
110     // many symbols have a name like foo@4, we must remove the @4
111     // just searching for an @ is not enough,
112     // as it may occur on other positions. We search for the last one
113     // and check that it is followed only by digits.
114     char *p = strrchr(str, '@');
115     if (p) {
116       char *q = p+1;
117       strtoul(p+1, &q, 10);
118       if (q > p+1 && *q == '\0') {
119                 *p = '\0';
120       }
121     }
122 }
123
124 char *cplus_demangle(char *c, int, bool includeTypes) { 
125     
126     char buf[1000];
127     if (c[0]=='_') {
128         // VC++ 5.0 seems to decorate C symbols differently to C++ symbols
129         // and the UnDecorateSymbolName() function provided by imagehlp.lib
130         // doesn't manage (or want) to undecorate them, so it has to be done
131         // manually, removing a leading underscore from functions & variables
132         // and the trailing "$stuff" from variables (actually "$Sstuff")
133         unsigned i;
134         for (i=1; i<sizeof(buf) && c[i]!='$' && c[i]!='\0'; i++)
135             buf[i-1]=c[i];
136         buf[i-1]='\0';
137         stripAtSuffix(buf);
138         if (buf[0] == '\0') 
139                 return 0; // avoid null names which seem to annoy Paradyn
140         return P_strdup(buf);
141     }
142     else {
143        if (includeTypes) {
144           if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE| UNDNAME_NO_ACCESS_SPECIFIERS|UNDNAME_NO_MEMBER_TYPE|UNDNAME_NO_MS_KEYWORDS)) {
145             //   printf("Undecorate with types: %s = %s\n", c, buf);
146             stripAtSuffix(buf);
147             return P_strdup(buf);
148           }
149        }
150        else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_NAME_ONLY)) {
151          //else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE|UNDNAME_32_BIT_DECODE)) {
152          //printf("Undecorate: %s = %s\n", c, buf);
153          stripAtSuffix(buf);          
154          return P_strdup(buf);
155        }
156     }
157     return 0;
158 }
159
160 //---------------------------------------------------------------------------
161 // Object method implementation
162 //---------------------------------------------------------------------------
163 struct  CompareSymAddresses: public binary_function<const Object::intSymbol*, const Object::intSymbol*, bool> 
164 {
165         bool operator()(const Object::intSymbol *s1, const Object::intSymbol* s2) {
166                 bool ret = false;
167                 // first try comparing by address
168                 if( s1->GetAddr() < s2->GetAddr() ) 
169                 {
170                         ret = true;
171                 }
172                 else if( s1->GetAddr() > s2->GetAddr() )
173                 {
174                         ret = false;
175                 }
176                 else
177                 {
178                         // the two symbols have the same address
179                         // use our next criteria (the existence of a size)
180                         // for a given address, we want symbols with a size
181                         // to occur before those without so that we can
182                         // use the size if we wish
183                         if( (s1->GetSize() != 0) && (s2->GetSize() == 0) )
184                         {
185                                 ret = true;
186                         }
187                         else if( (s1->GetSize() == 0) && (s2->GetSize() != 0) )
188                         {
189                                 ret = false;
190                         }
191                 }
192                 return ret;
193         }
194 };
195
196 Object::Module::Module( std::string _name, DWORD64 _baseAddr, DWORD64 _extent )  :
197                                                 name(_name),
198                                                 baseAddr(_baseAddr),
199                                                 extent(_extent),
200                                                 isDll( false )
201 {
202         defFile = new Object::File();
203         files.push_back( defFile );
204 }
205
206 Object::File*
207 Object::Module::FindFile( std::string name )
208 {
209         File* ret = NULL;
210         for( std::vector<File *>::iterator iter = files.begin();
211                         iter != files.end();
212                         iter++ )
213         {
214                 if( (*iter)->GetName() == name )
215                 {
216                         ret = *iter;
217                         break;
218                 }
219         }
220         return ret;
221 }
222
223 void
224 Object::File::DefineSymbols( dyn_hash_map<std::string, std::vector< Symbol *> >& allSyms,
225                              map<Symbol *, std::string> &symsToMods,
226                              const std::string& modName ) const
227 {
228     for( std::vector<Object::intSymbol*>::const_iterator iter = syms.begin(); iter != syms.end(); iter++ ) {
229         const Object::intSymbol* curSym = * iter;
230         assert( curSym != NULL );
231         curSym->DefineSymbol( allSyms, symsToMods, modName );
232     }
233 }
234
235 void
236 Object::intSymbol::DefineSymbol(dyn_hash_map<std::string,std::vector<Symbol *> >&allSyms,
237                                 map<Symbol *, std::string> &symsToMods,
238                                 const std::string& modName ) const
239 {
240     Symbol *sym = new Symbol(GetName(), 
241                              (Symbol::SymbolType) GetType(),
242                              (Symbol::SymbolLinkage) GetLinkage(),
243                              Symbol::SV_UNKNOWN,
244                              (Offset)GetAddr(),
245                              NULL,
246                              GetRegion(),
247                              GetSize());
248     allSyms[GetName()].push_back(sym);
249     symsToMods[sym] = modName;
250 }
251
252 void
253 Object::Module::DefineSymbols( const Object* obj,
254                                dyn_hash_map<std::string, std::vector< Symbol *> > & syms,
255                                map<Symbol *, std::string> &symsToMods ) const
256 {
257     // define Paradyn/dyninst modules and symbols
258     if( !isDll )
259         {
260         // this is an EXE
261         for( std::vector<Object::File*>::const_iterator iter = files.begin();
262                 iter != files.end();
263              iter++ ) {
264             const File* curFile = *iter;
265             assert( curFile != NULL );
266             
267             //fprintf(stderr, "ObjMod::DefineSymbols for %s\n", curFile->GetName().c_str());
268             // add a Symbol for the file
269             Symbol *sym = new Symbol( curFile->GetName(), 
270                                       Symbol::ST_MODULE,
271                                       Symbol::SL_GLOBAL,
272                                       Symbol::SV_UNKNOWN,
273                                       obj->code_off(),  // TODO use real base of symbols for file
274                                       NULL,
275                                       NULL, 0 );        // TODO Pass Section pointer also
276             // TODO also pass size
277             // add symbols for each of the file's symbols
278             syms[curFile->GetName()].push_back(sym);
279             symsToMods[sym] = curFile->GetName();
280
281             curFile->DefineSymbols( syms, symsToMods, curFile->GetName() );
282         }
283     }
284     else
285     {
286         // we represent a DLL
287         // add one Symbol for the entire module
288
289         Symbol *sym = new Symbol(name,
290                                  Symbol::ST_MODULE,
291                                  Symbol::SL_GLOBAL,
292                                  Symbol::SV_UNKNOWN,
293                                  obj->code_off(),
294                                  NULL,
295                                  NULL,                                  //TODO pass Sections pointer
296                                  obj->code_len());
297     
298         syms[name].push_back(sym); 
299         symsToMods[sym] = name;
300
301         // add symbols for each of the module's symbols
302         for( std::vector<Object::File*>::const_iterator iter = files.begin();
303                 iter != files.end();
304                 iter++ )
305         {
306             const File* curFile = *iter;
307             assert( curFile != NULL );
308             // add symbols for each of the file's symbols
309             curFile->DefineSymbols( syms, symsToMods, name );
310         }
311     }
312 }
313
314 void
315 Object::Module::PatchSymbolSizes( const Object* obj,
316                                                                   const std::vector<Object::intSymbol*>& allSyms ) const
317 {
318         DWORD64 lastFuncAddr = NULL;
319         unsigned int i;
320         
321         for( i = 0; i < allSyms.size(); i++ )
322     {
323                 Object::intSymbol* sym = allSyms[i];
324                 assert( sym != NULL );
325                 if( (sym->GetName() != "") && (sym->GetSize() == 0) &&
326             ((sym->GetType() == Symbol::ST_FUNCTION) ||
327              (sym->GetType() == Symbol::ST_OBJECT)))
328         {
329             // check for function aliases
330             // note that this check depends on the allSymbols
331             // array being sorted so that aliases are considered
332             // after the "real" function symbol
333             bool isAlias = false;
334             if( (sym->GetType() == Symbol::ST_FUNCTION) &&
335                 (sym->GetAddr() == lastFuncAddr) &&
336                 (sym->GetSize() == 0) )
337             {
338                 // this function is an alias
339                                 // we currently leave their size as zero to indicate 
340                                 // that they are uninstrumentable.  Ideally, this will
341                                 // change once a mechanism becomes available to identify
342                                 // these as function aliases.
343                                 isAlias = true;
344                         }
345             if( !isAlias )
346                         {
347                                 //
348                                 // patch the symbol's size
349                                 //
350                                 // We consider the symbol's size to be the distance
351                                 // to the next symbol.  (Sometimes this causes us to
352                                 // overestimate, because compilers sometimes leave some
353                                 // "padding" between the end of a function and the beginning
354                                 // of the next.)
355                                 //
356                                 // Note that we have to use the next symbol whose
357                                 // address is different from the current one, to handle
358                                 // cases where aliases are included in the symbol table
359                 //
360                 DWORD64 cb;
361                 
362                                 //
363                                 // find next function or object symbol in our section with
364                                 // an address different from ours
365                                 //
366                                 // the while test looks complicated -
367                                 // all we're trying to do is skip to the next
368                                 // function or object symbol within the array whose
369                                 // address is not the same as allSymbols[i].
370                                 unsigned int j = i + 1;
371                                 while((j < allSyms.size()) &&
372                                 (((allSyms[j]->GetType() != Symbol::ST_FUNCTION) &&
373                                                                 (allSyms[j]->GetType() != Symbol::ST_OBJECT)) ||
374                                                                 (allSyms[j]->GetAddr() == sym->GetAddr())))
375                                 {
376                                         j++;
377                                 }
378                                 if( j < allSyms.size() &&
379                                         (allSyms[j]->GetType() == sym->GetType()) )
380                                 {
381                                         // we found a symbol from the same section
382                                         // with a different address -
383                                         // size is just the delta between symbols
384                                         cb = allSyms[j]->GetAddr() - sym->GetAddr();
385                                 }
386                                 else
387                                 {
388                                         // we couldn't find another symbol in our section
389                                         // with a different address -
390                                         // size is the remainder of the current section
391                                         if( sym->GetType() == Symbol::ST_FUNCTION )
392                                         {
393                                                 // size is remainder of the .text section
394                                                 cb = (obj->code_off() + obj->code_len()) - 
395                                                         sym->GetAddr();
396                                         }
397                                         else
398                                         {
399                                                 // size is remainder of the .data section
400                                                 cb = (obj->data_off() + obj->data_len()) - 
401                                                         sym->GetAddr();
402                                         }
403                                 }
404                                 sym->SetSize( (unsigned int) cb );
405                         }
406                         // update the last known function symbol
407                         if( sym->GetType() == Symbol::ST_FUNCTION )
408                         {
409                                 lastFuncAddr = sym->GetAddr();
410                         }
411                 }
412     }
413 }
414
415 void
416 Object::Module::BuildSymbolMap( const Object* obj ) const
417 {
418         std::vector<Object::intSymbol*> allSyms;
419         // add all symbols to our allSyms std::vector
420         std::vector<Object::File*>::const_iterator iter = files.begin();
421         for(;   iter != files.end();    iter++ )
422         {
423                 assert( *iter != NULL );
424                 const std::vector<Object::intSymbol*>& curSyms = (*iter)->GetSymbols();
425                 for( std::vector<Object::intSymbol*>::const_iterator symIter = curSyms.begin(); symIter != curSyms.end();symIter++ )
426                 {
427                         assert( *symIter != NULL );
428                         allSyms.push_back( *symIter );
429                 }
430         }
431         // sort the symbols by address
432         sort( allSyms.begin(), allSyms.end(), CompareSymAddresses());
433         for( unsigned int i = 1; i < allSyms.size(); i++ )
434         {
435                 if( allSyms[i-1]->GetAddr() > allSyms[i]->GetAddr() )
436                 {
437                         cout << "WARNING - sort failed" << endl;
438                         assert( false );
439                 }
440         }
441         // patch up any symbol sizes which weren't given to us
442         PatchSymbolSizes( obj, allSyms );
443 }
444
445 Object::~Object( void )
446 {
447 }
448
449 #define SymTagFunction 0x5
450 #define SymTagData 0x7
451 #define SymTagPublicSymbol 0xa
452 #define SymTagMisc 0x3808               // Seen with NB11, VC++6-produced executables
453 //
454 // Our recognition of interesting symbols (functions and global data)
455 // is complicated due to lack of consistency in how they are
456 // presented to us in the pSymInfo struct.  For example,
457 // Microsoft's own system DLLs like kernel32.dll only seem to provide
458 // us their exports - these have the SYMFLAG_EXPORT bit set in
459 // pSymInfo->Flags.  In contrast, EXEs with full debug information
460 // may have pSymInfo->Flags == 0, with pSymInfo->Tag indicating the
461 // type of symbol.
462 //
463 static BOOL isGlobalSymbol(PSYMBOL_INFO pSymInfo) {
464  return ((pSymInfo->Flags & SYMFLAG_EXPORT) ||
465          (pSymInfo->Flags & SYMFLAG_FUNCTION) ||
466          ((!pSymInfo->Flags) && 
467           ((pSymInfo->Tag == SymTagFunction) ||
468            (pSymInfo->Tag == SymTagData) ||
469            (pSymInfo->Tag == SymTagPublicSymbol) ||
470            (pSymInfo->Tag == SymTagMisc))) );
471 }
472
473 void Object::ParseGlobalSymbol(PSYMBOL_INFO pSymInfo)
474 {
475         Object::Module* curMod = GetCurrentModule();
476         assert( curMod != NULL );
477         
478         IMAGEHLP_LINE64 lineInfo;
479         DWORD dwDisplacement = 0;
480         ZeroMemory( &lineInfo, sizeof(lineInfo) );
481         lineInfo.SizeOfStruct = sizeof(lineInfo);
482         Object::File* pFile = NULL;
483         if( SymGetLineFromAddr64( hProc,
484                                                                 pSymInfo->Address,
485                                                                 &dwDisplacement,
486                                                                 &lineInfo ) ) {
487                 // ensure we have a file for this object
488                 pFile = curMod->FindFile( lineInfo.FileName );
489                 if( pFile == NULL ) {
490                         pFile = new Object::File( lineInfo.FileName );
491                         curMod->AddFile( pFile );
492                 }
493         }
494         else {
495                 pFile = curMod->GetDefaultFile();
496         }
497         assert( pFile != NULL );
498         // is it a function or not?
499         // TODO why is there a discrepancy between code base addr for
500         // EXEs and DLLs?
501         DWORD symType = Symbol::ST_UNKNOWN;
502         DWORD symLinkage = Symbol::SL_UNKNOWN;
503         DWORD64 codeLen = code_len();
504         DWORD64 codeBase = code_off();
505         symType = Symbol::ST_FUNCTION;
506         //codeBase += get_base_addr();
507         // Logic: if it's tagged/flagged as a function, function.
508         // If it's tagged/flagged as a public symbol and it points
509         // to text, function.
510         // Otherwise, variable.
511         if ((pSymInfo->Flags & SYMFLAG_FUNCTION) ||
512                 (pSymInfo->Tag == SymTagFunction))
513         {
514                 symLinkage = Symbol::SL_UNKNOWN;
515         }
516         else if (((pSymInfo->Flags & SYMFLAG_EXPORT) || 
517                           (pSymInfo->Tag == SymTagPublicSymbol)) && 
518                  isText((Offset) pSymInfo->Address - (Offset)mf->base_addr()))
519         {
520                 symType = Symbol::ST_FUNCTION;
521                 symLinkage = Symbol::SL_UNKNOWN;
522         }
523         else
524         {
525                 symType = Symbol::ST_OBJECT;
526                 symLinkage = Symbol::SL_GLOBAL;
527         }
528     // register the symbol
529     Offset baseAddr = 0;
530     //  if (desc.isSharedObject())
531     //if(curModule->IsDll())
532     //   baseAddr = get_base_addr();
533     if( !isForwarded( ((Offset) pSymInfo->Address) - baseAddr ) )
534     {
535         pFile->AddSymbol( new Object::intSymbol
536                           ( pSymInfo->Name,
537                             pSymInfo->Address - get_base_addr(),
538                             symType,
539                             symLinkage,
540                             pSymInfo->Size,
541                             findEnclosingRegion((Offset)(pSymInfo->Address - get_base_addr())) ));
542     } 
543 }
544    
545 BOOL CALLBACK SymEnumSymbolsCallback( PSYMBOL_INFO pSymInfo,
546                                                                                 ULONG symSize,
547                                                                                 PVOID userContext )
548 {
549         assert( pSymInfo != NULL );
550         Object* obj = (Object*) userContext;
551         assert( obj != NULL );
552
553 #if 0
554         if(pSymInfo->Name && (strcmp(pSymInfo->Name, "test1_1_func1_1") == 0))
555         fprintf(stderr, "symEnumSymsCallback, %s, Flags:0x%x, Tag:0x%x, Type:%d, Addr:0x%x...\n",
556                    pSymInfo->Name,
557            pSymInfo->Flags,
558            pSymInfo->Tag,
559            pSymInfo->TypeIndex,
560            pSymInfo->Address);
561 #endif
562
563    if (isGlobalSymbol(pSymInfo))
564    {
565       obj->ParseGlobalSymbol(pSymInfo);
566    }
567    else if ((pSymInfo->Flags & SYMFLAG_LOCAL) ||
568             (pSymInfo->Flags & SYMFLAG_PARAMETER)) {
569       //parsing_printf("Is a local variable\n");
570       //obj->ParseLocalSymbol(pSymInfo);
571    }
572    else {
573       //parsing_printf(" skipping\n");
574    }
575    // keep enumerating symbols
576    return TRUE;
577 }
578
579 /*
580  * This function finds all the global symbols
581  * in a module and all of the source files. (i.e. so this function would find
582  * the 'main' symbol and find the starting point of 'foo.c'
583  *
584  */
585 void Object::ParseSymbolInfo( bool alloc_syms )
586 {
587    // build a Module object for the current module (EXE or DLL)
588    // Note that the CurrentModuleScoper object ensures that the
589    // curModule member will be reset when we leave the scope of
590    // this function.
591    // curModule = new Object::Module( file_, desc.code() );
592    string file_ = mf->filename();
593    static unsigned count = 1;
594    hProc = (HANDLE) count++;
595    if(!SymInitialize(hProc, NULL, false)){
596       DWORD dwErr = GetLastError();
597       if(dwErr) {
598          fprintf( stderr, "SymInitialize failed for %s\n",
599                ((file_.length() > 0) ? file_.c_str() 
600                 : "<no name available>"));
601          goto done;
602       }
603    }
604    assert( hProc != NULL );
605    assert( hProc != INVALID_HANDLE_VALUE );
606
607    // grab load address
608    if (peHdr) imageBase = peHdr->OptionalHeader.ImageBase;
609    else imageBase = 0; 
610
611    // load symbols for this module
612    //DWORD64 dw64BaseAddr = (DWORD64)desc.loadAddr();
613    HANDLE mapAddr = mf->base_addr();
614    DWORD64 dw64BaseAddr = (DWORD64)mapAddr;
615    //load address is always same(fake address space)
616    HANDLE hFile = mf->getFileHandle();
617    DWORD64 loadRet = SymLoadModule64( hProc,                    // proc handle
618          hFile,         // file handle
619          NULL,          // image name
620          NULL,          // shortcut name
621          dw64BaseAddr,  // load address
622          0 );           // size of DLL    
623    if(!loadRet) {
624       DWORD dwErr = GetLastError();
625       if(dwErr) {
626          string file_ = mf->filename();
627          fprintf( stderr, "SymLoadModule64 failed for %s\n",
628                ((file_.length() > 0) ? file_.c_str() 
629                 : "<no name available>"));
630          //printSysError(dwErr);
631          goto done;
632       }
633    }
634    // parse symbols for the module
635    if( !SymEnumSymbols(hProc,                      // process handle
636             dw64BaseAddr,                   // load address
637             "",                 // symbol mask (we use none)
638             SymEnumSymbolsCallback, // called for each symbol
639             this ) )            // client data
640    {
641       int lasterr = GetLastError();
642       fprintf( stderr, "Failed to enumerate symbols\n");
643       //printSysError(lasterr);
644    }
645
646    // We have a module object, with one or more files,
647    // each with one or more symbols.  However, the symbols
648    // are not necessarily in order, nor do they necessarily have valid sizes.
649    assert( curModule != NULL );
650    curModule->BuildSymbolMap( this );
651    if (alloc_syms)
652       curModule->DefineSymbols( this, symbols_, symsToModules_ );
653    no_of_symbols_ = symbols_.size();
654
655    //fprintf(stderr, "%s[%d]:  removed call to parseFileLineInfo here\n", FILE__, __LINE__);
656
657    // Since PE-COFF is very similar to COFF (in that it's not like ELF),
658    // the .text and .data sections are perfectly mapped to code/data segments
659    code_vldS_ = code_off_;
660    code_vldE_ = code_off_ + code_len_;
661    data_vldS_ = data_off_;
662    data_vldE_ = data_off_ + data_len_;
663
664 done:
665    delete curModule;
666 }
667
668 // Ensure that the optional header has a TLS directory entry
669 // calculate the TLS directory address and make sure it's valid
670 // calculate the address of the TLS callback array and make sure it's valid
671 // for each TLS callback, add a function symbol
672 void Object::AddTLSFunctions()
673 {
674    // ensure that the optional header has a TLS directory entry
675    if (!peHdr || peHdr->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_TLS) {
676       return;
677    }
678
679    // calculate the TLS directory address and make sure it's valid
680    unsigned long tlsSize = peHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size;
681    if (!tlsSize) {
682       return;
683    }
684    Address imgBase = peHdr->OptionalHeader.ImageBase;
685    Offset tlsMemOff = peHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress;
686    Region *secn = findEnclosingRegion(tlsMemOff);
687    if (!secn || (tlsMemOff - secn->getMemOffset()) > secn->getDiskSize()) {
688       return;
689    }
690    Offset tlsDiskOff = tlsMemOff 
691       + (Offset)secn->getDiskOffset() 
692       - (Offset)secn->getMemOffset();
693    IMAGE_TLS_DIRECTORY *tlsDir = (IMAGE_TLS_DIRECTORY*) 
694       ( tlsDiskOff + (Offset)mf->base_addr() );
695
696    // calculate the address of the TLS callback array and make sure it's valid
697    secn = findEnclosingRegion(tlsDir->AddressOfCallBacks - imgBase);
698    Offset cbOffSec = tlsDir->AddressOfCallBacks 
699       - secn->getMemOffset() 
700       - imgBase;
701    if (!secn || cbOffSec > secn->getDiskSize()) {
702       return;
703    }
704    Offset cbOffDisk = cbOffSec + secn->getDiskOffset();
705    PIMAGE_TLS_CALLBACK *tlsCBs = (PIMAGE_TLS_CALLBACK*) 
706       ( cbOffDisk + (Offset)mf->base_addr() );
707    unsigned maxCBs = (secn->getDiskSize() - cbOffSec) / sizeof(PIMAGE_TLS_CALLBACK);
708
709    // for each TLS callback, add a function symbol
710    for (unsigned tidx=0; tidx < maxCBs && tlsCBs[tidx] != NULL ; tidx++) {
711       Offset funcOff = ((Address) tlsCBs[tidx]) - imgBase;
712       secn = findEnclosingRegion(funcOff);
713       if (!secn) {
714          continue;
715       }
716       Offset baseAddr = 0;
717       Object::File *pFile = curModule->GetDefaultFile();
718       char funcName [128];
719       snprintf(funcName, 128, "tls_cb_%d", tidx);
720       pFile->AddSymbol( new Object::intSymbol
721                        ( funcName,
722                          funcOff,
723                          Symbol::ST_FUNCTION,
724                          Symbol::SL_GLOBAL,
725                          0, // unknown size
726                          secn ));
727    }
728 }
729
730 Region::perm_t getRegionPerms(DWORD flags){
731     if((flags & IMAGE_SCN_MEM_EXECUTE) && (flags & IMAGE_SCN_MEM_WRITE))
732         return Region::RP_RWX;
733     else if(flags & IMAGE_SCN_MEM_EXECUTE)
734         return Region::RP_RX;
735     else if(flags & IMAGE_SCN_MEM_WRITE)
736         return Region::RP_RW;
737     else
738         return Region::RP_R;
739 }
740
741 Region::RegionType getRegionType(DWORD flags){
742     if((flags & IMAGE_SCN_CNT_CODE) && (flags & IMAGE_SCN_CNT_INITIALIZED_DATA))
743         return Region::RT_TEXTDATA;
744     else if(flags & IMAGE_SCN_CNT_CODE)
745         return Region::RT_TEXT;
746     else if((flags & IMAGE_SCN_CNT_INITIALIZED_DATA) || (flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
747         return Region::RT_DATA;
748     else
749         return Region::RT_OTHER;
750 }
751
752 std::vector<std::pair<string, IMAGE_IMPORT_DESCRIPTOR> > & Object::getImportDescriptorTable()
753 {
754    if (!idt_.empty()) {
755       return idt_;
756    }
757
758    if (peHdr->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_IMPORT)
759       assert(0 && "PE header doesn't specify the IDT address");
760
761    //1. get the RVA of import table from Data directory
762    DWORD dwITrva = peHdr->OptionalHeader.
763       DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
764    //printf("Import Table RVA: %lx\n", dwITrva);
765
766    //2. get the offset in disk file
767    DWORD dwIToffset = RVA2Offset(dwITrva);
768    //printf("import table disk offset: %lx\n", dwIToffset);
769
770    PIMAGE_IMPORT_DESCRIPTOR import_d = (PIMAGE_IMPORT_DESCRIPTOR)
771       (((char*)mf->base_addr())+dwIToffset);
772
773    while(import_d ->Name != NULL && import_d->FirstThunk !=NULL){
774       IMAGE_IMPORT_DESCRIPTOR ie;
775       memcpy(&ie, import_d, sizeof(IMAGE_IMPORT_DESCRIPTOR));
776       string str((char*)(((char*)mf->base_addr())+RVA2Offset(import_d->Name)));
777       idt_.push_back(pair<string,IMAGE_IMPORT_DESCRIPTOR>(str,ie));
778       //printf("%s\n",ie.name);
779       import_d ++;
780    }
781    return idt_;
782    //cout<<"size of import table"<<image_import_descriptor.size()<<endl;
783 }
784
785 map<string, map<string, WORD> > & Object::getHintNameTable()
786 {
787    if (!hnt_.empty()) {
788       return hnt_;
789    }
790
791    vector<pair<string, IMAGE_IMPORT_DESCRIPTOR> > idt = getImportDescriptorTable();
792    for (vector<pair<string, IMAGE_IMPORT_DESCRIPTOR> >::iterator dit = idt.begin();
793         dit != idt.end();
794         dit++) 
795    {
796       assert(sizeof(Offset) == getAddressWidth());
797       Offset * iat = (Offset*)((char*)mf->base_addr() + RVA2Offset(dit->second.FirstThunk));
798
799       for (unsigned idx=0; iat[idx] != 0; idx++) {
800          assert (0 == (0x80000000 & iat[idx])); //ensure IAT is not ordinal-based
801          IMAGE_IMPORT_BY_NAME *hintName = (IMAGE_IMPORT_BY_NAME *)
802             ((char*)mf->base_addr() + RVA2Offset(iat[idx]));
803          hnt_[dit->first][string((char*)hintName->Name)] = hintName->Hint;
804       }
805    }
806    
807    return hnt_;
808 }
809
810 void Object::FindInterestingSections(bool alloc_syms, bool defensive)
811 {
812    // now that we have the file mapped, look for 
813    // the .text and .data sections
814    assert( peHdr == NULL );
815    HANDLE mapAddr = mf->base_addr();
816    peHdr = ImageNtHeader( mapAddr );
817
818    if (peHdr == NULL) {
819       code_ptr_ = (char*)mapAddr;
820       code_off_ = 0;
821       HANDLE hFile = mf->getFileHandle();
822       code_len_ = mf->size();
823       is_aout_ = false;
824       fprintf(stderr,"Adding Symtab object with no program header, will " 
825               "designate it as code, code_ptr_=%lx code_len_=%lx\n",
826               code_ptr_,code_len_);
827       if (alloc_syms) {
828           Region *bufReg = new Region
829                     (0, //region number
830                      ".text", 
831                      code_off_, // disk offset
832                      code_len_, // disk size
833                      code_off_, // mem offset
834                      code_len_, // mem size
835                      code_ptr_, // raw data ptr
836                      Region::RP_RWX, 
837                      Region::RT_TEXT,
838                      true);// is loadable
839           regions_.push_back(bufReg);
840       }
841       return;
842    }
843
844    assert( peHdr->FileHeader.SizeOfOptionalHeader > 0 ); 
845
846    string file_ = mf->filename();
847    curModule = new Object::Module( file_, 0 );
848    assert( curModule != NULL );
849
850    curModule->SetIsDll( (peHdr->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0 );
851    if(curModule->IsDll())
852       is_aout_ = false;
853    else
854       is_aout_ = true;
855
856    getImportDescriptorTable(); //save the binary's original table, we may change it later
857
858    //get exported functions
859    // note: there is an error in the PE specification regarding the export 
860    //       table Base.  The spec claims that you are supposed to subtract 
861    //       the Base to get correct ordinal indices into the Export Address 
862    //       table, but this is false, at least in the typical case for which 
863    //       Base=1, I haven't observed any binaries with different bases
864         if (!is_aout_ && peHdr->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXPORT) {
865                 assert(sizeof(Offset) == getAddressWidth());
866                 unsigned long size;
867                 IMAGE_EXPORT_DIRECTORY *eT2 = (IMAGE_EXPORT_DIRECTORY *)::ImageDirectoryEntryToData(mapAddr, false, IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
868                 if (eT2) {
869                         DWORD *funcNamePtrs = (DWORD *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, ULONG(eT2->AddressOfNames), NULL);
870                         DWORD *funcAddrs = (DWORD *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, ULONG(eT2->AddressOfFunctions), NULL);
871                         WORD *funcAddrNameMap = (WORD *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, ULONG(eT2->AddressOfNameOrdinals), NULL);
872                         if (funcNamePtrs && funcAddrs && funcAddrNameMap) {
873                                 for (unsigned i = 0; i < eT2->NumberOfNames; ++i) {
874                                         char *name = (char *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, funcNamePtrs[i], NULL);
875                                         int funcIndx = funcAddrNameMap[i];
876                                         Address funcAddr = funcAddrs[funcIndx];
877                                         if ((funcAddr >= (Address) eT2) &&
878                                                 (funcAddr < ((Address) eT2 + size))) continue;
879                                         Symbol *sym = new Symbol(name,
880                                                 Symbol::ST_FUNCTION, 
881                                         Symbol::SL_GLOBAL, 
882                                     Symbol::SV_DEFAULT,
883                                         funcAddr);
884                                         sym->setDynamic(true); // it's exported, equivalent to ELF dynamic syms
885                                         symbols_[name].push_back(sym);
886                                         symsToModules_[sym] = curModule->GetName();
887                                 }
888                         }
889                 }
890         }
891
892    SecAlignment = peHdr ->OptionalHeader.SectionAlignment;
893    unsigned int nSections = peHdr->FileHeader.NumberOfSections;
894    no_of_sections_ = nSections;
895    Address prov_begin = (Address)-1;
896    Address prov_end = (Address)-1;
897    code_off_ = (Address)-1;
898    code_len_ = (Address)-1;
899
900    if (defensive) {
901        // add section for peHdr, determine the size taken up by the section 
902        // in the program's address space.  
903        unsigned long secSize = ( peHdr->OptionalHeader.SizeOfHeaders 
904                                  / peHdr->OptionalHeader.SectionAlignment ) 
905                               * peHdr->OptionalHeader.SectionAlignment;
906        if (  peHdr->OptionalHeader.SizeOfHeaders 
907            % peHdr->OptionalHeader.SectionAlignment ) 
908        {
909           secSize += peHdr->OptionalHeader.SectionAlignment;
910        }
911        prov_begin = 0;
912        prov_end = prov_begin + secSize;
913        regions_.push_back(
914            new Region(
915             0, "PROGRAM_HEADER", 0, peHdr->OptionalHeader.SizeOfHeaders, 
916             0, secSize, (char*)mapAddr,
917             getRegionPerms(IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE), 
918             getRegionType(IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA),
919             true));
920    }
921
922    PIMAGE_SECTION_HEADER pScnHdr = (PIMAGE_SECTION_HEADER)(((char*)peHdr) + 
923                                  sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) +
924                                  peHdr->FileHeader.SizeOfOptionalHeader);
925    bool foundText = false;
926    for( unsigned int i = 0; i < nSections; i++ ) {
927       // rawDataPtr should be set to be zero if the amount of raw data
928       // for the section is zero
929
930       Offset diskOffset = 0; 
931       if (pScnHdr->SizeOfRawData != 0) {
932          // the loader rounds PointerToRawData to the previous fileAlignment 
933          // boundary  (usually 512 bytes)
934          diskOffset = (Offset)
935              ((pScnHdr->PointerToRawData / peHdr->OptionalHeader.FileAlignment) 
936               * peHdr->OptionalHeader.FileAlignment);
937       }
938       Offset secSize = (pScnHdr->Misc.VirtualSize > pScnHdr->SizeOfRawData) ? 
939           pScnHdr->Misc.VirtualSize : pScnHdr->SizeOfRawData;
940       if (alloc_syms)
941           regions_.push_back
942               (new Region(i+1, 
943                           (const char *)pScnHdr->Name,
944                           diskOffset,
945                           pScnHdr->SizeOfRawData,
946                           pScnHdr->VirtualAddress, 
947                           secSize,
948                           (char *)(diskOffset + (Offset)mapAddr), 
949                           getRegionPerms(pScnHdr->Characteristics),
950                           getRegionType(pScnHdr->Characteristics)));
951 //        regions_.push_back(new Section(i, (const char*)pScnHdr->Name, 
952 //                                      pScnHdr->VirtualAddress, 
953 //                                      pScnHdr->Misc.VirtualSize, 
954 //                                      rawDataPtr));
955
956       if( strncmp( (const char*)pScnHdr->Name, ".text", 8 ) == 0 ) {
957          // note that section numbers are one-based
958          textSectionId = i + 1;
959          code_ptr_    = (char*)(((char*)mapAddr) +
960                                 pScnHdr->PointerToRawData);
961          code_off_    = pScnHdr->VirtualAddress;
962
963          // Since we're reporting the size of sections on the disk,
964          // we need to check whether the size of raw data is smaller.
965          //code_len_    = pScnHdr->Misc.VirtualSize;
966          code_len_ = ((pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize) ?
967                       pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize);
968
969          foundText = true;
970          if (prov_begin == -1) {
971              prov_begin = code_off_;
972              prov_end = code_off_ + code_len_;
973          } else {
974              if (prov_begin > code_off_) {
975                  prov_begin = code_off_;
976              }
977              if ( prov_end < (code_off_ + code_len_) ) {
978                   prov_end = (code_off_ + code_len_);
979              }
980          }
981       }
982       else if( strncmp( (const char*)pScnHdr->Name, ".data", 8 ) == 0 ) {
983          // note that section numbers are one-based
984          dataSectionId = i + 1;
985          data_ptr_    = (char *)(((char*)mapAddr) +
986                                  pScnHdr->PointerToRawData);
987          data_off_    = pScnHdr->VirtualAddress;
988          data_len_ = (pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize ?
989                       pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize);
990          if (defensive) { // don't parse .data in a non-defensive binary
991              if (prov_begin == -1) {
992                 prov_begin = data_off_;
993                 prov_end = data_off_ + data_len_;
994              } else {
995                  if (prov_begin > data_off_) {
996                      prov_begin = data_off_;
997                  }
998                  if (prov_end < (data_off_ + data_len_)) {
999                      prov_end = (data_off_ + data_len_);
1000                  }
1001              }
1002          }
1003       }
1004       else {
1005          Offset sec_len = (pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize) ?
1006                            pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize;
1007          if (-1 == prov_begin) {
1008             prov_begin = pScnHdr->VirtualAddress;
1009             prov_end = prov_begin + sec_len;
1010          } else {
1011              if (prov_begin > pScnHdr->VirtualAddress) {
1012                  prov_begin = pScnHdr->VirtualAddress;
1013              }
1014              if (prov_end < (pScnHdr->VirtualAddress + sec_len)) {
1015                  prov_end = (pScnHdr->VirtualAddress + sec_len);
1016              }
1017          }
1018       }
1019       pScnHdr += 1;
1020    } // end section for loop
1021
1022    if (-1 == code_len_ || defensive) {
1023        // choose the smaller/larger of the two offsets/lengths, 
1024        // if both are initialized (i.e., are not equal to -1)
1025        if (code_off_ == -1)
1026            code_off_ = prov_begin;
1027        else if (prov_begin != -1 && 
1028                 code_off_ > prov_begin) 
1029            code_off_ = prov_begin;
1030
1031        if (code_len_ == -1)
1032            code_len_ = prov_end - code_off_;
1033        else if (prov_end != -1 &&
1034                 code_len_ < (prov_end - code_off_))
1035            code_len_ = (prov_end - code_off_);
1036
1037        assert(code_off_ != -1 && code_len_ != -1); // no sections in binary? 
1038    }
1039 }
1040
1041 // Assumes region list is sorted and regions don't overlap
1042 Region *Object::findEnclosingRegion(const Offset where)
1043 {
1044     // search for "where" in regions (regions must not overlap)
1045     int first = 0; 
1046     int last = regions_.size() - 1;
1047     while (last >= first) {
1048         Region *curreg = regions_[(first + last) / 2];
1049         if (where >= curreg->getMemOffset()
1050             && where < (curreg->getMemOffset()
1051                         + curreg->getMemSize())) {
1052             return curreg;
1053         }
1054         else if (where < curreg->getMemOffset()) {
1055             last = ((first + last) / 2) - 1;
1056         }
1057         else {/* where >= (cursec->getSecAddr()
1058                            + cursec->getSecSize()) */
1059             first = ((first + last) / 2) + 1;
1060         }
1061     }
1062     return NULL;
1063 }
1064
1065 bool Object::isForwarded( Offset addr )
1066 {
1067         //calls to forwarded symbols are routed to another dll and 
1068     //are not in the current dll's code space
1069         //we MUST NOT try to parse these - bad things happen
1070         
1071         //we detect forwarded symbols by checking if the relative 
1072         //virtual address of the symbol falls within the dll's exports section
1073         if(peHdr && peHdr->FileHeader.Characteristics & IMAGE_FILE_DLL )
1074         {
1075                 PIMAGE_DATA_DIRECTORY dataDir = peHdr->OptionalHeader.DataDirectory;
1076                 Offset exportStart = dataDir->VirtualAddress;
1077                 Offset exportEnd = exportStart + dataDir->Size;
1078                 if( addr >= exportStart && addr < exportEnd )
1079                         return true;  //this sym is forwarded
1080         }
1081         return false;
1082 }
1083
1084 bool Object::getCatchBlock(ExceptionBlock &b, Offset addr, 
1085                            unsigned size) const 
1086
1087    return false; 
1088 }
1089
1090 bool Object::isText( const Offset addr ) const 
1091 {
1092    return( addr >= code_off_ && addr < code_off_ + code_len_ );
1093 }
1094
1095 void fixup_filename(std::string &filename)
1096 {
1097         if (filename.substr(0,22) == "\\Device\\HarddiskVolume") {
1098                 TCHAR volumePath[1024];
1099                 if (GetVolumePathName(filename.c_str(), volumePath, 1024)) {
1100                         std::string::size_type filePathIndex = filename.find_first_of("\\/", 22);
1101                         if (filePathIndex != std::string::npos)
1102                                 filename = volumePath + filename.substr(++filePathIndex);
1103                         else
1104                                 filename = volumePath + filename.substr(23);
1105                 } else {
1106                         filename = "c:"+filename.substr(23);
1107                 }
1108         }
1109 }
1110
1111 Object::Object(MappedFile *mf_,
1112                bool defensive, 
1113                void (*err_func)(const char *), bool alloc_syms) :
1114     AObject(mf_, err_func),
1115     curModule( NULL ),
1116     baseAddr( 0 ),
1117     imageBase( 0 ),
1118     peHdr( NULL ),
1119     trapHeaderPtr_( 0 ),
1120     SecAlignment( 0 ),
1121     textSectionId( 0 ),
1122     dataSectionId( 0 ),
1123     hProc( NULL )
1124 {
1125    FindInterestingSections(alloc_syms, defensive);
1126    if (alloc_syms && defensive) {
1127       AddTLSFunctions();
1128    }
1129    ParseSymbolInfo(alloc_syms);
1130    rebase(0);
1131 }
1132
1133 SYMTAB_EXPORT ObjectType Object::objType() const 
1134 {
1135         return is_aout() ? obj_Executable : obj_SharedLib;
1136 }
1137
1138
1139 void Object::getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *mod_langs)
1140 {
1141         return;
1142 }
1143
1144 struct line_info_tmp_t {
1145         line_info_tmp_t(unsigned long a, unsigned int l) {addr = a; line_no = l;}
1146         unsigned long addr;
1147         unsigned int line_no;
1148 };
1149
1150 struct line_info_tmp_lt {
1151         bool operator()(const line_info_tmp_t &a, const line_info_tmp_t &b) {
1152       return a.addr < b.addr;
1153         };
1154 };
1155
1156 typedef std::multiset<line_info_tmp_t, line_info_tmp_lt> info_for_file_t;
1157 typedef std::map<std::string, info_for_file_t*> info_for_all_files_t;
1158
1159 static BOOL CALLBACK add_line_info(SRCCODEINFO *srcinfo, void *param)
1160 {
1161         info_for_all_files_t *all_info = (info_for_all_files_t *) param;
1162         info_for_all_files_t::iterator iter = all_info->find(std::string(srcinfo->FileName));
1163         info_for_file_t *finfo = NULL;
1164         if (iter == all_info->end()) {
1165                 finfo = new info_for_file_t();
1166                 (*all_info)[std::string(srcinfo->FileName)] = finfo;
1167         }
1168         else {
1169                 finfo = (*iter).second;
1170         }
1171         finfo->insert(line_info_tmp_t((unsigned long) srcinfo->Address, srcinfo->LineNumber));
1172         return true;
1173 }
1174
1175 static bool store_line_info(Symtab* st, info_for_all_files_t *baseInfo)
1176 {
1177    for (info_for_all_files_t::iterator i = baseInfo->begin(); i != baseInfo->end(); i++)
1178    {
1179            const char *filename = (*i).first.c_str();
1180            Module* mod;
1181            
1182            if(!st->findModuleByName(mod, filename)) 
1183            {
1184              mod = st->getDefaultModule();
1185            }    
1186            LineInformation* li_for_module = mod->getLineInformation();
1187            if(!li_for_module) 
1188            {
1189              li_for_module = new LineInformation;
1190              mod->setLineInfo(li_for_module);
1191            }
1192
1193            for (info_for_file_t::iterator j = (*i).second->begin(); j != (*i).second->end(); j++) {
1194                    info_for_file_t::iterator next = j;
1195                    next++;
1196                    if (next != (*i).second->end())
1197                            li_for_module->addLine(filename, j->line_no, 0, j->addr, next->addr);
1198                    else
1199                            li_for_module->addLine(filename, j->line_no, 0, j->addr, j->addr);
1200            }
1201            delete (*i).second;
1202    }
1203    return true;
1204 }
1205
1206 void Object::parseFileLineInfo(Symtab *st)
1207 {   
1208   if(parsedAllLineInfo) return;
1209   
1210   int result;
1211   static Offset last_file = 0x0;
1212
1213   Offset baseAddr = get_base_addr();
1214   if (last_file == baseAddr)
1215     return;
1216   last_file = baseAddr;
1217   info_for_all_files_t inf;
1218   result = SymEnumLines(hProc, 
1219                               baseAddr,
1220                               NULL, 
1221                               NULL,
1222                               add_line_info, 
1223                               &inf); 
1224   // Set to true once we know we've done as much as we can
1225   parsedAllLineInfo = true;
1226   if (!result) {
1227     //Not a big deal. The module probably didn't have any debug information.
1228     DWORD dwErr = GetLastError();
1229     //printf("[%s:%u] - Couldn't SymEnumLines on %s in %s\n", 
1230         //         __FILE__, __LINE__, src_file_name, libname);
1231     return;
1232   }
1233   store_line_info(st, &inf);
1234   
1235 }
1236
1237 typedef struct localsStruct {
1238     Function *func;
1239     Offset base;
1240     HANDLE p;
1241     map<unsigned, unsigned> foundSyms;
1242     localsStruct() : foundSyms() {}
1243 } localsStruct;
1244
1245 Dyninst::MachRegister WinConvert(Register reg) {
1246         //  Info from CV_HREG_e structure; from comments online this is correct
1247         switch(reg) {
1248         case CV_REG_EAX:
1249                 return x86::eax;
1250         case CV_REG_EBX:
1251                 return x86::ebx;
1252         case CV_REG_ECX:
1253                 return x86::ecx;
1254         case CV_REG_EDX:
1255                 return x86::edx;
1256         case CV_REG_ESP:
1257                 return x86::esp;
1258         case CV_REG_EBP:
1259                 return x86::ebp;
1260         case CV_REG_ESI:
1261                 return x86::esi;
1262         case CV_REG_EDI:
1263                 return x86::edi;
1264         default:
1265                 return Dyninst::InvalidReg;
1266         }
1267 }
1268
1269 BOOL CALLBACK enumLocalSymbols(PSYMBOL_INFO pSymInfo, unsigned long symSize,
1270                                void *userContext)
1271 {
1272     Type *type;
1273     Function *func;
1274     storageClass storage;
1275     localVar *newvar;
1276     MachRegister reg;
1277     signed long frameOffset;
1278     Offset base;
1279     HANDLE p;
1280  
1281     char *storageName;
1282     char *paramType;
1283
1284     //
1285     //Skip this variable if it's already been found.
1286     //
1287     localsStruct *locals = (localsStruct *) userContext;
1288     if (locals->foundSyms.find(pSymInfo->Index) != locals->foundSyms.end())
1289         return true;
1290     locals->foundSyms[pSymInfo->Index] = 1;
1291     base = locals->base;
1292     func = locals->func;
1293     p = locals->p;
1294
1295     //Get type
1296     type = getType(p, base, pSymInfo->TypeIndex, func->getModule());
1297     
1298     //Get variable storage location information
1299     if ((pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE) ||
1300         ((pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) && 
1301          (pSymInfo->Register = CV_REG_EBP)))
1302     {
1303                 reg = x86::ebp;
1304                 frameOffset = (signed) pSymInfo->Address;
1305         storage = storageRegOffset;
1306         storageName = "Frame Relative";
1307     }
1308     else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE)
1309     {
1310         reg = WinConvert(pSymInfo->Register);
1311         frameOffset = (signed) pSymInfo->Address;
1312         storage = storageRegOffset;
1313         storageName = "Register Relative";
1314     }
1315     else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) {
1316         reg = WinConvert(pSymInfo->Register);
1317         frameOffset = 0;
1318         storage = storageReg;
1319         storageName = "Register";
1320     }
1321     else {
1322         frameOffset = (signed) pSymInfo->Address;
1323         storage = storageAddr;
1324         storageName = "Absolute";
1325     }
1326         
1327         VariableLocation loc;
1328         loc.stClass = storage;
1329         loc.refClass = storageNoRef;
1330         loc.frameOffset = frameOffset;
1331         loc.lowPC = 0;
1332         loc.hiPC = (Address) -1;
1333         loc.mr_reg = reg;
1334         
1335         std::string vName = convertCharToString(pSymInfo->Name);
1336         std::string fName = convertCharToString(func->getModule()->fileName().c_str());
1337    newvar = new localVar(vName, type, fName, -1, func);
1338         newvar->addLocation(loc);
1339
1340     //Store the variable as a local or parameter appropriately
1341    if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) {
1342       assert(func);
1343       if (!func->addParam(newvar)) {
1344          fprintf(stderr, "%s[%d]:  addParam failed\n", FILE__, __LINE__);
1345          return false;
1346       }
1347       paramType = "parameter";
1348    }
1349    else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) {
1350           assert(func);
1351       if (!func->addLocalVar(newvar)) {
1352          fprintf(stderr, "%s[%d]:  addLocalVar failed\n", FILE__, __LINE__);
1353          return false;
1354       }
1355       paramType = "local";
1356    }
1357    else {
1358            
1359       fprintf(stderr, "[%s:%u] - Local variable of unknown type.  %s in %s\n",
1360               __FILE__, __LINE__, pSymInfo->Name, func->pretty_names_begin()->c_str());
1361       paramType = "unknown";
1362    }
1363
1364     
1365    const char *typeName;
1366    if (type) {
1367       typeName = type->getName().c_str();
1368    }
1369    else {
1370       typeName = "unknown";
1371    }
1372    
1373    return true;
1374 }
1375
1376
1377 static void enumLocalVars(Function *func, 
1378                           localsStruct *locals) 
1379 {
1380     IMAGEHLP_STACK_FRAME frame;
1381     memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
1382
1383     frame.InstructionOffset = locals->base + func->getOffset();
1384     int result = SymSetContext(locals->p, &frame, NULL);
1385         /*if (!result) {            
1386                 fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
1387         printSysError(GetLastError());
1388     }*/
1389     result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1390         /*if (!result) {
1391         fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
1392         printSysError(GetLastError());
1393     }*/
1394         
1395         if(func->getSize())
1396         {
1397                 memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
1398
1399                 frame.InstructionOffset = locals->base +
1400                     func->getOffset() + 
1401                     func->getSize();
1402                 result = SymSetContext(locals->p, &frame, NULL);
1403                 result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1404         }
1405
1406 //TODO?? replace this with??
1407 #if 0
1408     for (unsigned i=0; i<points.size(); i++) {
1409         frame.InstructionOffset = points[i]->addr();
1410         bool result = SymSetContext(locals->p, &frame, NULL);
1411         /*if (!result) {            
1412             fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
1413             printSysError(GetLastError());
1414         }*/
1415         result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1416         /*if (!result) {
1417             fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
1418             printSysError(GetLastError());
1419         }*/
1420     }
1421 #endif
1422
1423 }
1424
1425 static int variantValue(VARIANT *v) {
1426     switch(v->vt) {    
1427        case VT_I8:
1428            return (int) v->llVal;
1429        case VT_I4:
1430            return (int) v->lVal;
1431        case VT_UI1:
1432            return (int) v->bVal;
1433        case VT_I2:
1434            return (int) v->iVal;
1435        case VT_I1:
1436            return (int) v->cVal;
1437        case VT_UI2:
1438            return (int) v->uiVal;
1439        case VT_UI4:
1440            return (int) v->ulVal;
1441        case VT_UI8:
1442            return (int) v->ullVal;
1443        case VT_INT:
1444            return (int) v->intVal;
1445        case VT_UINT:
1446            return (int) v->uintVal;
1447        default:
1448            return 0;
1449     }
1450 }
1451
1452 // Changed. Not adding to stdTypes now
1453 static void addTypeToCollection(Type *type, Module *mod) 
1454 {
1455         typeCollection *tc = typeCollection::getModTypeCollection(mod);
1456         assert(tc);
1457         tc->addType(type);
1458 /*         
1459    typeCollection *collection;
1460
1461    collection = mod ? tc : Symtab::stdTypes;
1462    assert(collection);
1463    assert(!collection->findType(type->getID()));
1464    collection->addType(type);
1465 */
1466 }
1467
1468 static char *getTypeName(HANDLE p, Offset base, int typeIndex) {
1469     int result, length;
1470     WCHAR *wname = NULL;
1471     char *name = NULL;
1472
1473     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMNAME, &wname);
1474     if (!result) 
1475         return NULL;
1476     length = wcslen(wname) + 1;
1477     name = (char *) malloc(length + 1);
1478     result = WideCharToMultiByte(CP_ACP, 0, wname, -1, name, length, NULL, NULL);
1479     LocalFree(wname); 
1480     if (!result) {
1481         int lasterror = GetLastError();
1482 //        printSysError(lasterror);
1483         return NULL;
1484     }
1485     return name;
1486 }
1487
1488 static dataClass getDataClass(HANDLE p, Offset base, int typeIndex) {
1489     enum SymTagEnum wintype;
1490     int result, basetype;
1491
1492     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &wintype);
1493     if (!result)
1494         return dataUnknownType;
1495     switch (wintype) {
1496         case SymTagFunction:
1497         case SymTagFunctionType:
1498             return dataFunction;
1499         case SymTagPointerType:
1500             return dataPointer;
1501         case SymTagArrayType:
1502             return dataArray;
1503         case SymTagBaseType:
1504             return dataScalar;
1505         case SymTagEnum:
1506             return dataEnum;
1507         case SymTagTypedef:
1508             return dataTypedef;
1509         case SymTagUDT:
1510             enum UdtKind udtType;
1511             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
1512             if (!result)
1513                 return dataUnknownType;
1514             switch (udtType) {
1515                 case UdtUnion:
1516                     return dataUnion;
1517                 case UdtStruct:
1518                 case UdtClass:
1519                     return dataStructure;
1520                 default:
1521                     return dataUnknownType;
1522             }
1523         case SymTagFunctionArgType:
1524             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &basetype);
1525             if (!result)
1526                 return dataUnknownType;
1527             return getDataClass(p, base, basetype);
1528         default:
1529             return dataUnknownType;
1530     }
1531 }
1532
1533 static Type *getEnumType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1534     unsigned i;
1535     char *name = NULL;
1536     char *entryName = NULL;
1537     VARIANT entryValue;
1538     typeEnum *type;
1539     int result;
1540     unsigned numEntries, entriesSize;
1541     TI_FINDCHILDREN_PARAMS *entries = NULL;
1542
1543     name = getTypeName(p, base, typeIndex);
1544         std::string tName = convertCharToString(name);
1545     type = new typeEnum(typeIndex, tName);
1546     addTypeToCollection(type, mod);
1547     free(name);
1548     name = NULL;
1549
1550     //
1551     //Get the number of entries in this enum, and store them in the entries structure
1552     //
1553     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numEntries);
1554     if (!result)
1555         numEntries = 0;
1556     if (numEntries) {
1557         entriesSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numEntries + 1) * sizeof(ULONG);
1558         entries = (TI_FINDCHILDREN_PARAMS *) malloc(entriesSize);
1559         memset(entries, 0, entriesSize);
1560         entries->Count = numEntries;
1561         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, entries);
1562         if (!result)
1563             numEntries = 0;
1564     }
1565
1566     for (i=0; i<numEntries; i++) {
1567         entryName = getTypeName(p, base, entries->ChildId[i]);
1568         VariantInit(&entryValue);
1569         result = SymGetTypeInfo(p, base, entries->ChildId[i], TI_GET_VALUE, &entryValue);
1570         if (!result)
1571             continue;
1572         type->addConstant(entryName, variantValue(&entryValue));
1573     }
1574   
1575     if (entries)
1576         free(entries);
1577     return type;    
1578 }
1579
1580 static Type *getPointerType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1581     int baseTypeIndex, result;
1582     Type *baseType;
1583     typePointer *newType;
1584
1585     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
1586     if (!result) {
1587         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1588         return NULL;
1589     }
1590
1591     //
1592     // Add a place-holder for the pointer type first and fill in it's 
1593     //  base type latter.  This prevents recursion that may happen beneath 
1594     //  the getType function call below.
1595     //
1596     newType = new typePointer(typeIndex, NULL);
1597     addTypeToCollection(newType, mod);
1598
1599     baseType = getType(p, base, baseTypeIndex, mod);
1600     if (!baseType) {
1601         fprintf(stderr, "[%s:%u] - getType failed\n", __FILE__, __LINE__);
1602         return NULL;
1603     }
1604
1605     newType->setPtr(baseType);
1606     return newType;
1607 }
1608
1609 static Type *getArrayType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1610     int result, baseIndex, index;
1611     Type *indexType, *newType, *baseType;
1612     unsigned size, num_elements;
1613     ULONG64 size64;
1614     std::string bname;
1615     std::string name;
1616
1617     //Get the index type (usually an int of some kind).  Currently not used.
1618     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_ARRAYINDEXTYPEID, &index);
1619     if (!result) {
1620         fprintf(stderr, "[%s:%u] - TI_GET_ARRAYINDEXTYPEID failed\n", 
1621                 __FILE__, __LINE__);
1622         return NULL;
1623     }
1624     indexType = getType(p, base, index, mod);
1625
1626     //Get the base type (the type of the elements in the array)
1627     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseIndex);
1628     if (!result) {
1629         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1630         return NULL;
1631     }
1632     baseType = getType(p, base, baseIndex, mod);
1633
1634     bname = baseType->getName();
1635     name = bname + "[]";
1636         
1637     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1638     if (!result) {
1639         num_elements = 0;
1640     }
1641     else {
1642       size = (unsigned) size64;
1643       num_elements = size / baseType->getSize();
1644     }
1645
1646     newType = new typeArray(typeIndex, baseType, 0, num_elements-1, name);
1647     newType->getSize();
1648     addTypeToCollection(newType, mod);
1649     assert(newType->getID() == typeIndex);
1650
1651     return newType;
1652 }
1653
1654
1655 static Type *getTypedefType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1656     int result, baseTypeIndex;
1657     Type *baseType, *newType;
1658     char *name;
1659
1660     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
1661     if (!result) {
1662         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1663         return NULL;
1664     }
1665     baseType = getType(p, base, baseTypeIndex, mod);
1666     if (!baseType) {
1667         return NULL;
1668     }
1669  
1670     name = getTypeName(p, base, typeIndex);
1671         std::string tName = convertCharToString(name);
1672     newType = new typeTypedef(typeIndex, baseType, tName);
1673     addTypeToCollection(newType, mod);
1674     return newType;
1675 }
1676
1677 static Type *getUDTType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1678     int result, symtag;
1679     unsigned size, numChildren, childrenSize, child_offset, i, child_size;
1680     fieldListType *newType;
1681     UINT64 size64;
1682     const char *name, *childName;
1683     enum UdtKind udtType;
1684     TI_FINDCHILDREN_PARAMS *children = NULL;
1685
1686     //
1687     // Get name for structure
1688     //
1689     name = getTypeName(p, base, typeIndex);
1690         std::string tName = convertCharToString(name);
1691         result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1692     if (!result) {
1693         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
1694         return NULL;
1695     }
1696     size = (unsigned) size64;
1697
1698     //
1699     // Determine whether it's a class, struct, or union and create the 
1700     //  new_type appropriately
1701     //
1702     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
1703     if (!result) {
1704         fprintf(stderr, "[%s:%u] - TI_GET_UDTKIND returned error\n");
1705         return NULL;
1706     }
1707     switch (udtType) {
1708         case UdtUnion:
1709             newType = new typeUnion(typeIndex, tName);
1710             break;
1711         case UdtStruct:
1712         case UdtClass:
1713         default:
1714             newType = new typeStruct(typeIndex, tName);
1715             break;
1716     }
1717     addTypeToCollection(newType, mod);
1718     if (name)
1719        free((void *) name);
1720     name = NULL;
1721
1722
1723     //
1724     // Store the number of member variables/functions/stuff in numChildren
1725     //
1726     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numChildren);
1727     if (!result)
1728         numChildren = 0;
1729     //
1730     // Get the list of variables/functions/stuff
1731     //
1732     if (numChildren) {
1733         childrenSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numChildren + 1) * sizeof(ULONG);
1734         children = (TI_FINDCHILDREN_PARAMS *) malloc(childrenSize);
1735         memset(children, 0, childrenSize);
1736         children->Count = numChildren;
1737         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, children);
1738         if (!result)
1739             numChildren = 0;
1740     }
1741
1742     //
1743     // Create/Find the type of each child and add it to newType appropriately
1744     //
1745     for (i=0; i<numChildren; i++) {
1746         // Create/Get child type
1747         Type *child_type = getType(p, base, children->ChildId[i], mod);
1748         if (!child_type)
1749             continue;
1750
1751         // Figure out a name of this object
1752         childName = NULL;
1753         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_SYMTAG, &symtag);
1754         if (result && symtag == SymTagBaseClass) {
1755             childName = P_strdup("{superclass}");
1756         }
1757         if (!childName)
1758             childName = getTypeName(p, base, children->ChildId[i]);
1759         if (!childName) 
1760             childName = P_strdup(child_type->getName().c_str());
1761
1762         // Find the offset of this member in the structure
1763         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_OFFSET, &child_offset);
1764         if (!result) {
1765             child_offset = 0; //Probably a member function
1766             child_size = 0;
1767         }
1768         else {
1769             child_offset *= 8; //Internally measured in bits
1770             child_size = child_type->getSize();
1771         }
1772
1773                 std::string fName = convertCharToString(childName);
1774         newType->addField(fName, child_type, child_offset);
1775         if (childName)
1776             free((void *) childName);
1777         childName = NULL;
1778     }
1779
1780     if (children)
1781         free(children);
1782
1783     return newType;
1784 }
1785
1786 static Type *getLayeredType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1787     int result, newTypeIndex;
1788     Type *newType;
1789
1790     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &newTypeIndex);
1791     if (!result) {
1792         fprintf(stderr, "TI_GET_TYPEID failed\n");
1793         return NULL;
1794     }
1795
1796     newType = getType(p, base, newTypeIndex, mod);
1797     return newType;
1798 }
1799
1800 static Type *getFunctionType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1801     int result, retTypeIndex;
1802     typeFunction *newType;
1803     Type *retType;
1804     unsigned num_params, args_size, i;
1805     std::vector<Type *> params;
1806     TI_FINDCHILDREN_PARAMS *args = NULL;
1807     std::string name;
1808
1809     //Create the function early to avoid recursive references
1810         std::string tName = "";
1811     newType = new typeFunction(typeIndex, NULL, tName);
1812     addTypeToCollection(newType, mod);
1813
1814     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &retTypeIndex);
1815     if (!result) {
1816         fprintf(stderr, "[%s:%u] - Couldn't TI_GET_TYPEID\n", __FILE__, __LINE__);
1817         return NULL;
1818     }
1819
1820     retType = getType(p, base, retTypeIndex, mod);
1821     if (!retType) {
1822         return NULL;
1823     }
1824     newType->setRetType(retType);
1825
1826     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_COUNT, &num_params);
1827     if (!result)
1828         goto done_params;
1829
1830     args_size = sizeof(TI_FINDCHILDREN_PARAMS) + (num_params + 1) * sizeof(ULONG);
1831     args = (TI_FINDCHILDREN_PARAMS *) malloc(args_size);
1832     memset(args, 0, args_size);
1833     args->Count = num_params;
1834     result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, args);
1835     if (!result)
1836         goto done_params;
1837     
1838     for (i=0; i<num_params; i++) {
1839         Type *arg_type = getType(p, base, args->ChildId[i], mod);
1840         if (!arg_type) {
1841             continue;
1842         }
1843         params.push_back(arg_type);
1844     }
1845
1846 done_params:
1847
1848     //
1849     // Build a type name that looks like the following:
1850     //   (return_type)(param1_type, param2_type, ...)
1851     name = "(";
1852     name += retType->getName();
1853     name += ")(";
1854     for (i=0; i<params.size(); i++) {
1855         if (i != 0)
1856             name += ", ";
1857         name += params[i]->getName();
1858     }
1859     name += "()";
1860         
1861         std::string newName = name;
1862     newType->setName(newName);
1863
1864     for (i=0; i<params.size(); i++) {
1865         //TODO?? have a name for the parameter. Required??
1866         newType->addParam(params[i]);
1867     }
1868
1869     if (args)
1870         free(args);
1871
1872     return newType;
1873 }
1874
1875 static Type *getBaseType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1876     BasicType baseType;
1877     int result;
1878     ULONG64 size64;
1879     unsigned size;
1880     Type *newType;
1881
1882     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_BASETYPE, &baseType);
1883     if (!result) {
1884         fprintf(stderr, "[%s:%u] - TI_GET_BASETYPE return error\n");
1885         return NULL;
1886     }
1887
1888     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1889     if (!result) {
1890         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
1891         return NULL;
1892     }
1893     size = (unsigned) size64;
1894     switch(baseType) {
1895          case btNoType:
1896                  newType = NULL;
1897                  break;
1898          case btVoid:
1899          newType = new typeScalar(typeIndex, size, "void");
1900                  break;
1901          case btChar:
1902          newType = new typeScalar(typeIndex, size, "char");
1903                  break;
1904          case btWChar:
1905          newType = new typeScalar(typeIndex, size, "wchar");
1906                  break;
1907          case btInt:
1908          if (size == 8)
1909            newType = new typeScalar(typeIndex, size, "long long int");
1910          else if (size == 4)
1911            newType = new typeScalar(typeIndex, size, "int");
1912          else if (size == 2)
1913            newType = new typeScalar(typeIndex, size, "short");
1914          else if (size == 1)
1915            newType = new typeScalar(typeIndex, size, "char");
1916          else
1917            newType = new typeScalar(typeIndex, size, "");
1918                  break;
1919          case btUInt:
1920          if (size == 8)
1921            newType = new typeScalar(typeIndex, size, "unsigned long long int");
1922          else if (size == 4)
1923            newType = new typeScalar(typeIndex, size, "unsigned int");
1924          else if (size == 2)
1925            newType = new typeScalar(typeIndex, size, "unsigned short");
1926          else if (size == 1)
1927            newType = new typeScalar(typeIndex, size, "unsigned char");
1928          else
1929            newType = new typeScalar(typeIndex, size, "");
1930                  break;
1931          case btFloat:
1932          if (size == 8)
1933              newType = new typeScalar(typeIndex, size, "double");
1934          else
1935              newType = new typeScalar(typeIndex, size, "float");
1936                  break;
1937          case btBCD:
1938          newType = new typeScalar(typeIndex, size, "BCD");
1939                  break;
1940          case btBool:
1941          newType = new typeScalar(typeIndex, size, "bool");
1942                  break;
1943          case btLong:
1944          newType = new typeScalar(typeIndex, size, "long");
1945                  break;
1946          case btULong:
1947          newType = new typeScalar(typeIndex, size, "unsigned long");
1948                  break;
1949          case btCurrency:
1950          newType = new typeScalar(typeIndex, size, "currency");
1951                  break;
1952          case btDate:
1953          newType = new typeScalar(typeIndex, size, "Date");
1954                  break;
1955          case btVariant:
1956          newType = new typeScalar(typeIndex, size, "variant");
1957                  break;
1958          case btComplex:
1959          newType = new typeScalar(typeIndex, size, "complex");
1960                  break;
1961          case btBit:
1962          newType = new typeScalar(typeIndex, size, "bit");
1963                  break;
1964          case btBSTR:
1965          newType = new typeScalar(typeIndex, size, "bstr");
1966                  break;
1967          case btHresult:
1968          newType = new typeScalar(typeIndex, size, "Hresult");
1969                  break;
1970          default:
1971                  fprintf(stderr, "Couldn't parse baseType %d for %d\n", baseType, typeIndex);
1972          assert(0);
1973                  break;
1974    }
1975    if (newType)
1976        addTypeToCollection(newType, mod);
1977    return newType;
1978 }
1979
1980 static Type *getType(HANDLE p, Offset base, int typeIndex, Module *mod) 
1981 {
1982    static unsigned depth = 0;
1983    BOOL result;
1984    Type *foundType = NULL;
1985    typeCollection *collection;
1986    enum SymTagEnum symtag;
1987
1988    if (!typeIndex)
1989        return NULL;
1990
1991    //
1992    // Check if this type has already been created (they're indexed by typeIndex).
1993    // If it has, go ahead and return the existing one.
1994    // If not, then start creating a new type.
1995    //
1996    if (mod)
1997        collection = typeCollection::getModTypeCollection(mod);
1998    else
1999            collection = (typeCollection*)Symtab::stdTypes;
2000    assert(collection);
2001
2002
2003    //
2004    // Check to see if we've already parsed this type
2005    //
2006    foundType = collection->findType(typeIndex);
2007    if (foundType) {
2008        return foundType;
2009    }
2010
2011    //
2012    // Types on Windows are stored as part of a special type of symbol.  TI_GET_SYMTAG 
2013    // Gets the meta information about the type.
2014    //
2015    result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &symtag);
2016    if (!result) {
2017        depth--;
2018        return NULL;
2019    }
2020    switch (symtag) {
2021        case SymTagBaseType:
2022            foundType = getBaseType(p, base, typeIndex, mod);
2023            break;
2024        case SymTagEnum:
2025            foundType = getEnumType(p, base, typeIndex, mod);
2026            break;
2027        case SymTagFunctionType:
2028            foundType = getFunctionType(p, base, typeIndex, mod);
2029            break;
2030        case SymTagPointerType:
2031            foundType = getPointerType(p, base, typeIndex, mod);
2032            break;
2033        case SymTagArrayType:
2034            foundType = getArrayType(p, base, typeIndex, mod);
2035            break;
2036        case SymTagTypedef:
2037            foundType = getTypedefType(p, base, typeIndex, mod);
2038            break;
2039        case SymTagUDT:
2040            foundType = getUDTType(p, base, typeIndex, mod);
2041            break;
2042        case SymTagFunctionArgType:
2043        case SymTagData:
2044        case SymTagFunction:
2045        case SymTagBaseClass:
2046            foundType = getLayeredType(p, base, typeIndex, mod);
2047            if (foundType)
2048              typeIndex = foundType->getID();
2049            break;
2050        case SymTagThunk:
2051            foundType = NULL;
2052            break;
2053        case SymTagVTableShape:
2054        case SymTagVTable:
2055            break;
2056        default:
2057            fprintf(stderr, "Unknown type %d\n", symtag);
2058            assert(0);
2059            foundType = NULL;
2060            break;
2061    }
2062
2063    return foundType;
2064 }
2065
2066 typedef struct proc_mod_pair {
2067         HANDLE handle;
2068         Symtab *obj;
2069     Offset base_addr;
2070 } proc_mod_pair;
2071
2072 static void findLocalVars(Function *func, proc_mod_pair base) {
2073     Module *mod = func->getModule();
2074     localsStruct locals;
2075     HANDLE p = base.handle;
2076
2077     locals.func = func;
2078     locals.base = base.base_addr;
2079     locals.p = p;
2080
2081         enumLocalVars(func, &locals);
2082     //
2083     // The windows debugging interface allows us to get local variables
2084     // at specific points, which makes it hard to enumerate all locals (as we want).
2085     // Instead we'll get the local variables at the most common points below.
2086     //
2087     //TODO?
2088         //=const std::vector<instPoint*> &points = ifunc->funcEntries();
2089     //=enumLocalVars(func, ifunc->funcEntries(), &locals);
2090     //=enumLocalVars(func, ifunc->funcExits(), &locals);
2091     //=enumLocalVars(func, ifunc->funcCalls(), &locals);
2092     //=enumLocalVars(func, ifunc->funcArbitraryPoints(), &locals);
2093 }
2094
2095 BOOL CALLBACK add_type_info(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, void *info)
2096 {
2097    HANDLE p;
2098    Offset obj_base;
2099    proc_mod_pair *pair;
2100    Symtab *obj;
2101    Type *type;
2102    char *name;
2103    Address addr;
2104
2105    if (!isGlobalSymbol(pSymInfo)) {
2106        //We do local symbols elsewhere
2107        return TRUE;
2108    }
2109
2110    pair = (proc_mod_pair *) info;
2111    p = pair->handle;
2112    obj_base = pair->base_addr;
2113    obj = pair->obj;
2114    name = pSymInfo->Name;
2115    addr = (Address) pSymInfo->Address - obj_base;
2116
2117    std::vector<Module *> mods;
2118    Module *mod;
2119    //TODO?? change later
2120    if(!obj->getAllModules(mods))
2121    {
2122            return true;
2123    }
2124    else
2125            mod = mods[0];
2126    
2127    if (obj->isExec()) {
2128       //When parsing the a.out, sort the type information into specific modules.  This doesn't matter
2129       // for libraries, because there is a 1:1 mapping between modules and objects.
2130       //
2131       //A module is a collection of functions, but doesn't include global data types.  Global variables
2132       // will go into the DEFAULT_MODULE
2133                 Function *f = NULL;
2134            if(obj->findFuncByEntryOffset(f, (Offset) pSymInfo->Address))
2135            {
2136              //No containing module.  Only insert this into DEFAULT_MODULE
2137           if (strcmp(f->getModule()->fileName().c_str(), "DEFAULT_MODULE"))
2138               return true;
2139       }
2140    }
2141
2142    type = getType(p, obj_base, pSymInfo->TypeIndex, mod);
2143
2144    
2145 //   fprintf(stderr, "[%s:%u] - Variable %s had type %s\n", __FILE__, __LINE__,
2146 //       name, type ? type->getName().c_str() : "{NO TYPE}");
2147    
2148    if (type)
2149    {
2150       Variable *var = NULL;
2151       bool result = obj->findVariableByOffset(var, addr);
2152       if (result) {
2153          var->setType(type);
2154       }
2155       if (name) {
2156          std::string vName = name;
2157                  typeCollection *tc = typeCollection::getModTypeCollection(mod);
2158                  assert(tc);
2159          tc->addGlobalVariable(vName, type);
2160       }
2161    }
2162    return TRUE;
2163 }
2164
2165 void Object::parseTypeInfo(Symtab *obj) {
2166     proc_mod_pair pair;
2167     BOOL result;
2168     //
2169     //Parse global variable type information
2170     //
2171
2172     pair.handle = hProc;
2173     pair.obj = obj;
2174     pair.base_addr = getBaseAddress();
2175     
2176     if (!pair.base_addr) {
2177         pair.base_addr = getLoadAddress();
2178     }
2179   
2180    HANDLE mapAddr = mf->base_addr();
2181     result = SymEnumSymbols(hProc, (DWORD64)mapAddr, NULL, 
2182                             add_type_info, &pair);
2183         if (!result){
2184                 printSysError(GetLastError());
2185 //        parsing_printf("SymEnumSymbols was unsuccessful.  Type info may be incomplete\n");
2186     }
2187
2188     //
2189     // Parse local variables and local type information
2190     //
2191     std::vector<Function *> funcs;
2192         obj->getAllFunctions(funcs);
2193     for (unsigned i=0; i < funcs.size(); i++) {
2194         findLocalVars(funcs[i], pair);
2195     }
2196 }
2197
2198 bool AObject::getSegments(vector<Segment> &segs) const
2199 {
2200         for(unsigned int i=0; i<regions_.size(); i++){
2201                 Segment seg;
2202                 seg.data = regions_[i]->getPtrToRawData();
2203                 //seg.loadaddr = regions_[i] -> getDiskOffset();
2204                 seg.loadaddr = regions_[i] -> getMemOffset();
2205                 seg.size = regions_[i] -> getDiskSize();
2206                 seg.name = regions_[i] -> getRegionName();
2207                 //seg.segFlags = 
2208                 segs.push_back(seg);
2209         }
2210     return true;
2211 }
2212
2213 bool Object::emitDriver(Symtab *obj, string fName, std::vector<Symbol *>&allSymbols, 
2214                                                 unsigned flag) 
2215 {
2216         emitWin *em = new emitWin((PCHAR)GetMapAddr(), this, err_func_);
2217         return em -> driver(obj, fName);
2218 }
2219
2220 // automatically discards duplicates
2221 void Object::addReference(Offset off, std::string lib, std::string fun){
2222    ref[lib][off] = fun;
2223 }
2224                                                 
2225 // retrieve Section Number for an image offset
2226 // dwRO - the image offset to calculate
2227 // returns -1 if an error occurred else returns the corresponding section number
2228 DWORD Object::ImageOffset2SectionNum(DWORD dwRO)
2229 {
2230    PIMAGE_SECTION_HEADER sectionHeader = 
2231       (PIMAGE_SECTION_HEADER)((DWORD)peHdr 
2232                               + sizeof(DWORD) // PE signature
2233                               + sizeof(IMAGE_FILE_HEADER) 
2234                               + peHdr->FileHeader.SizeOfOptionalHeader);
2235         unsigned int SecCount = peHdr ->FileHeader.NumberOfSections;
2236         for(unsigned int i=0;i < SecCount; i++)
2237         {
2238                 if((dwRO>=sectionHeader->PointerToRawData) && (dwRO<(sectionHeader->PointerToRawData+sectionHeader->SizeOfRawData)))
2239                 {
2240                         return (i);
2241                 }
2242                 sectionHeader++;
2243         }
2244         return(-1);
2245 }
2246
2247 PIMAGE_SECTION_HEADER Object::ImageOffset2Section(DWORD dwRO)
2248 {
2249    PIMAGE_SECTION_HEADER sectionHeader = 
2250       (PIMAGE_SECTION_HEADER)((DWORD)peHdr 
2251                               + sizeof(DWORD) // PE signature
2252                               + sizeof(IMAGE_FILE_HEADER) 
2253                               + peHdr->FileHeader.SizeOfOptionalHeader);
2254         unsigned int SecCount = peHdr ->FileHeader.NumberOfSections;
2255
2256         for(unsigned int i=0;i<SecCount;i++)
2257         {
2258                 if((dwRO >= sectionHeader->PointerToRawData) && 
2259            (dwRO < (sectionHeader->PointerToRawData + sectionHeader->SizeOfRawData)))
2260                 {
2261                         return sectionHeader;
2262                 }
2263                 sectionHeader++;
2264         }
2265         return(NULL);
2266 }
2267
2268 PIMAGE_SECTION_HEADER Object::ImageRVA2Section(DWORD dwRVA)
2269 {
2270    PIMAGE_SECTION_HEADER sectionHeader = 
2271       (PIMAGE_SECTION_HEADER)((DWORD)peHdr 
2272                               + sizeof(DWORD) // PE signature
2273                               + sizeof(IMAGE_FILE_HEADER) 
2274                               + peHdr->FileHeader.SizeOfOptionalHeader);
2275         unsigned int SecCount = peHdr ->FileHeader.NumberOfSections;
2276
2277         for(unsigned int i=0;i<SecCount;i++)
2278         {
2279                 if((dwRVA>=sectionHeader->VirtualAddress) && (dwRVA<=(sectionHeader->VirtualAddress+sectionHeader->SizeOfRawData)))
2280                 {
2281                         return sectionHeader;
2282                 }
2283                 sectionHeader++;
2284         }
2285         return(NULL);
2286 }
2287
2288 DWORD Object::RVA2Offset(DWORD dwRVA)
2289 {
2290         DWORD offset;
2291         PIMAGE_SECTION_HEADER section = ImageRVA2Section(dwRVA);
2292         if(section==NULL)
2293         {
2294                 return(0);
2295         }
2296         offset=dwRVA+section->PointerToRawData-section->VirtualAddress;
2297         return offset;
2298 }
2299
2300 DWORD Object::Offset2RVA(DWORD dwRO)
2301 {
2302         PIMAGE_SECTION_HEADER section = ImageOffset2Section(dwRO);
2303         if(section==NULL)
2304         {
2305                 return(0);
2306         }
2307         return(dwRO+section->VirtualAddress-section->PointerToRawData);
2308 }
2309
2310 void Object::setTrapHeader(Offset addr)
2311 {
2312    trapHeaderPtr_ = addr;
2313 }
2314 Offset Object::trapHeader()
2315 {
2316    return trapHeaderPtr_;
2317 }
2318
2319 void Object::insertPrereqLibrary(std::string lib)
2320 {
2321    // must include some function from the library for Windows to load it
2322    ref[lib] = std::map<Offset, std::string>();
2323 }
2324
2325  bool Region::isStandardCode()
2326 {
2327    return (getRegionPermissions() == RP_RX ||
2328            getRegionPermissions() == RP_RWX);
2329 }
2330
2331 Dyninst::Architecture Object::getArch()
2332 {
2333    return Dyninst::Arch_x86;
2334 }
2335
2336 /*
2337         for(it=ref.begin(); it!=ref.end(); it++){
2338                 IMAGE_IMPORT_DESCRIPTOR newID;
2339                 newID.ForwarderChain=0;
2340                 newID.TimeDateStamp=0;
2341                 newID.OriginalFirstThunk = 0;
2342                 newID.FirstThunk = (*it).first;
2343                 //printf("IAT address: %x\n", newID.FirstThunk);
2344
2345                 //look through the old import table to check if the library has been there
2346                 bool isExisting = false;
2347                 for(unsigned int i=0; i<oldImp.size(); i++){
2348
2349                         //if already been there, use the same of RVA of name
2350                         if(strcmp(oldImp[i].name, (*it).second.first.c_str()) == 0){
2351                                 isExisting = true;
2352                                 newID.Name = oldImp[i].id.Name;
2353                                 break;
2354                         }
2355                 }       
2356
2357                 char* ptrLib;
2358                 unsigned long strLen;
2359                 //otherwise, it's a new library
2360                 if(!isExisting){
2361                         newID.Name = strOff;
2362                         strLen =(*it).second.first.size();
2363                         //library name must be '\0' terminated, so len plus one
2364                         ptrLib = (char*) GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, strLen+1);
2365                         memcpy(ptrLib,(*it).second.first.c_str(), strLen);
2366                         info.push_back(std::pair<char*,unsigned long> (ptrLib, strLen+1));
2367                         strOff+=(strLen+1);
2368                 }
2369
2370                 memcpy(newIT+pos*sizeof(IMAGE_IMPORT_DESCRIPTOR),(char*)&newID, sizeof(IMAGE_IMPORT_DESCRIPTOR));
2371
2372                 //write the pointer to function name into (*it).first
2373                 Offset o = (Offset)((char*)dynSec->getPtrToRawData())+(*it).first-dynSec->getMemOffset();
2374                 printf("Offset to write the pointer to function name: %x\n", o);
2375                 memcpy(((char*)dynSec->getPtrToRawData())+(*it).first-dynSec->getMemOffset(), (char*)&strOff, 4);
2376                 strLen = (*it).second.second.size();
2377         
2378                 //functin name must start with a two byte hint
2379                 //function name also '0\' terminated
2380                 ptrLib = (char*)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, 2+strLen+1);
2381                 memcpy(ptrLib+2, (*it).second.second.c_str(), strLen);
2382                 info.push_back(std::pair<char*, unsigned long> (ptrLib, strLen+3));
2383                 strOff+=(2+strLen+1);
2384
2385                 pos++;
2386         }
2387 */
2388
2389 DWORD* Object::get_dword_ptr(Offset rva)
2390 {
2391         Offset off = RVA2Offset(rva);
2392         int sectionNum = ImageOffset2SectionNum(off);
2393         Region* r = regions_[sectionNum];
2394         char* region_buf = (char*)(r->getPtrToRawData());
2395         return (DWORD*)(region_buf + (off - r->getDiskOffset()));
2396 }
2397
2398 Region* Object::findRegionByName(const std::string& name) const
2399 {
2400         for(auto reg = regions_.begin();
2401                 reg != regions_.end();
2402                 ++reg)
2403         {
2404                 if((*reg)->getRegionName() == name)
2405                 {
2406                         return *reg;
2407                 }
2408         }
2409         return NULL;
2410 }
2411 void Object::applyRelocs(Region* relocs, Offset delta)
2412 {
2413         unsigned char* section_pointer = (unsigned char*)relocs->getPtrToRawData();
2414         unsigned char* section_end = section_pointer+relocs->getMemSize();
2415         while(section_pointer < section_end)
2416         {
2417                 PIMAGE_BASE_RELOCATION curRelocPage = (PIMAGE_BASE_RELOCATION)(section_pointer);
2418                 section_pointer += sizeof(IMAGE_BASE_RELOCATION);
2419                 Offset pageBase = curRelocPage->VirtualAddress;
2420                 if(pageBase == 0) break;
2421                 int numRelocs = (curRelocPage->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
2422                 for(int i = 0; i < numRelocs; ++i)
2423                 {
2424                         WORD curReloc = *(WORD*)(section_pointer);
2425                         section_pointer += sizeof(WORD);
2426                         Offset addr = (curReloc & 0x0FFF) + pageBase;
2427                         WORD type = curReloc >> 12;
2428                         switch(type)
2429                         {
2430                         case IMAGE_REL_BASED_ABSOLUTE:
2431                                 // These are placeholders only
2432                                 break;
2433                         case IMAGE_REL_BASED_HIGHLOW:
2434                                 {
2435                                         // These should be the only things we deal with on Win32; revisit when we hit 64-bit windows
2436                                         DWORD* loc_to_fix = get_dword_ptr(addr);
2437                                         *(loc_to_fix) += delta;
2438                                 }
2439                                 break;
2440                         default:
2441                                 fprintf(stderr, "Unknown relocation type 0x%x for addr %p\n", type, addr);
2442                                 break;
2443                         }
2444                 }
2445         }
2446 }
2447 void Object::rebase(Offset off)
2448 {
2449         if(off == imageBase) return;
2450         Region* relocs = findRegionByName(".reloc");
2451         if(!relocs) {
2452                 fprintf(stderr, "rebase found no .reloc section, bailing\n");
2453                 return;
2454         }
2455         Offset delta = off - imageBase;
2456         applyRelocs(relocs, delta);
2457         imageBase = off;
2458 }