Priorize existing call fallthrough edges over any jumps to increase the effectiveness...
[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
534     if( !isForwarded( ((Offset) pSymInfo->Address) - baseAddr ) )
535     {
536         pFile->AddSymbol( new Object::intSymbol
537                           ( pSymInfo->Name,
538                             pSymInfo->Address - get_base_addr(),
539                             symType,
540                             symLinkage,
541                             pSymInfo->Size,
542                             findEnclosingRegion((Offset)(pSymInfo->Address - get_base_addr())) ));
543     } 
544 }
545    
546 BOOL CALLBACK SymEnumSymbolsCallback( PSYMBOL_INFO pSymInfo,
547                                                                                 ULONG symSize,
548                                                                                 PVOID userContext )
549 {
550         assert( pSymInfo != NULL );
551         Object* obj = (Object*) userContext;
552         assert( obj != NULL );
553
554 #if 0
555         if(pSymInfo->Name && (strcmp(pSymInfo->Name, "test1_1_func1_1") == 0))
556         fprintf(stderr, "symEnumSymsCallback, %s, Flags:0x%x, Tag:0x%x, Type:%d, Addr:0x%x...\n",
557                    pSymInfo->Name,
558            pSymInfo->Flags,
559            pSymInfo->Tag,
560            pSymInfo->TypeIndex,
561            pSymInfo->Address);
562 #endif
563
564    if (isGlobalSymbol(pSymInfo))
565    {
566       obj->ParseGlobalSymbol(pSymInfo);
567    }
568    else if ((pSymInfo->Flags & SYMFLAG_LOCAL) ||
569             (pSymInfo->Flags & SYMFLAG_PARAMETER)) {
570       //parsing_printf("Is a local variable\n");
571       //obj->ParseLocalSymbol(pSymInfo);
572    }
573    else {
574       //parsing_printf(" skipping\n");
575    }
576    // keep enumerating symbols
577    return TRUE;
578 }
579
580 /*
581  * This function finds all the global symbols
582  * in a module and all of the source files. (i.e. so this function would find
583  * the 'main' symbol and find the starting point of 'foo.c'
584  *
585  */
586 void Object::ParseSymbolInfo( bool alloc_syms )
587 {
588    // build a Module object for the current module (EXE or DLL)
589    // Note that the CurrentModuleScoper object ensures that the
590    // curModule member will be reset when we leave the scope of
591    // this function.
592    // curModule = new Object::Module( file_, desc.code() );
593    string file_ = mf->filename();
594    static unsigned count = 1;
595    hProc = (HANDLE) count++;
596    if(!SymInitialize(hProc, NULL, false)){
597       DWORD dwErr = GetLastError();
598       if(dwErr) {
599          fprintf( stderr, "SymInitialize failed for %s\n",
600                ((file_.length() > 0) ? file_.c_str() 
601                 : "<no name available>"));
602          goto done;
603       }
604    }
605    assert( hProc != NULL );
606    assert( hProc != INVALID_HANDLE_VALUE );
607
608    // grab load address
609    if (peHdr) imageBase = peHdr->OptionalHeader.ImageBase;
610    else imageBase = 0; 
611
612    // load symbols for this module
613    //DWORD64 dw64BaseAddr = (DWORD64)desc.loadAddr();
614    HANDLE mapAddr = mf->base_addr();
615    DWORD64 dw64BaseAddr = (DWORD64)mapAddr;
616    //load address is always same(fake address space)
617    HANDLE hFile = mf->getFileHandle();
618    DWORD64 loadRet = SymLoadModule64( hProc,                    // proc handle
619          hFile,         // file handle
620          NULL,          // image name
621          NULL,          // shortcut name
622          dw64BaseAddr,  // load address
623          0 );           // size of DLL    
624    if(!loadRet) {
625       DWORD dwErr = GetLastError();
626       if(dwErr) {
627          string file_ = mf->filename();
628          fprintf( stderr, "SymLoadModule64 failed for %s\n",
629                ((file_.length() > 0) ? file_.c_str() 
630                 : "<no name available>"));
631          //printSysError(dwErr);
632          goto done;
633       }
634    }
635    // parse symbols for the module
636    if( !SymEnumSymbols(hProc,                      // process handle
637             dw64BaseAddr,                   // load address
638             "",                 // symbol mask (we use none)
639             SymEnumSymbolsCallback, // called for each symbol
640             this ) )            // client data
641    {
642       int lasterr = GetLastError();
643       fprintf( stderr, "Failed to enumerate symbols\n");
644       //printSysError(lasterr);
645    }
646
647    // We have a module object, with one or more files,
648    // each with one or more symbols.  However, the symbols
649    // are not necessarily in order, nor do they necessarily have valid sizes.
650    assert( curModule != NULL );
651    curModule->BuildSymbolMap( this );
652    if (alloc_syms)
653       curModule->DefineSymbols( this, symbols_, symsToModules_ );
654    no_of_symbols_ = symbols_.size();
655
656    //fprintf(stderr, "%s[%d]:  removed call to parseFileLineInfo here\n", FILE__, __LINE__);
657
658    // Since PE-COFF is very similar to COFF (in that it's not like ELF),
659    // the .text and .data sections are perfectly mapped to code/data segments
660    code_vldS_ = code_off_;
661    code_vldE_ = code_off_ + code_len_;
662    data_vldS_ = data_off_;
663    data_vldE_ = data_off_ + data_len_;
664
665 done:
666    delete curModule;
667 }
668
669 // Ensure that the optional header has a TLS directory entry
670 // calculate the TLS directory address and make sure it's valid
671 // calculate the address of the TLS callback array and make sure it's valid
672 // for each TLS callback, add a function symbol
673 void Object::AddTLSFunctions()
674 {
675    // ensure that the optional header has a TLS directory entry
676    if (!peHdr || peHdr->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_TLS) {
677       return;
678    }
679
680    // calculate the TLS directory address and make sure it's valid
681    unsigned long tlsSize = peHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size;
682    if (!tlsSize) {
683       return;
684    }
685    Address imgBase = peHdr->OptionalHeader.ImageBase;
686    Offset tlsMemOff = peHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress;
687    Region *secn = findEnclosingRegion(tlsMemOff);
688    if (!secn || (tlsMemOff - secn->getMemOffset()) > secn->getDiskSize()) {
689       return;
690    }
691    Offset tlsDiskOff = tlsMemOff 
692       + (Offset)secn->getDiskOffset() 
693       - (Offset)secn->getMemOffset();
694    IMAGE_TLS_DIRECTORY *tlsDir = (IMAGE_TLS_DIRECTORY*) 
695       ( tlsDiskOff + (Offset)mf->base_addr() );
696
697    // calculate the address of the TLS callback array and make sure it's valid
698    secn = findEnclosingRegion(tlsDir->AddressOfCallBacks - imgBase);
699    Offset cbOffSec = tlsDir->AddressOfCallBacks 
700       - secn->getMemOffset() 
701       - imgBase;
702    if (!secn || cbOffSec > secn->getDiskSize()) {
703       return;
704    }
705    Offset cbOffDisk = cbOffSec + secn->getDiskOffset();
706    PIMAGE_TLS_CALLBACK *tlsCBs = (PIMAGE_TLS_CALLBACK*) 
707       ( cbOffDisk + (Offset)mf->base_addr() );
708    unsigned maxCBs = (secn->getDiskSize() - cbOffSec) / sizeof(PIMAGE_TLS_CALLBACK);
709
710    // for each TLS callback, add a function symbol
711    for (unsigned tidx=0; tidx < maxCBs && tlsCBs[tidx] != NULL ; tidx++) {
712       Offset funcOff = ((Address) tlsCBs[tidx]) - imgBase;
713       secn = findEnclosingRegion(funcOff);
714       if (!secn) {
715          continue;
716       }
717       Offset baseAddr = 0;
718       Object::File *pFile = curModule->GetDefaultFile();
719       char funcName [128];
720       snprintf(funcName, 128, "tls_cb_%d", tidx);
721       pFile->AddSymbol( new Object::intSymbol
722                        ( funcName,
723                          funcOff,
724                          Symbol::ST_FUNCTION,
725                          Symbol::SL_GLOBAL,
726                          0, // unknown size
727                          secn ));
728    }
729 }
730
731 Region::perm_t getRegionPerms(DWORD flags){
732     if((flags & IMAGE_SCN_MEM_EXECUTE) && (flags & IMAGE_SCN_MEM_WRITE))
733         return Region::RP_RWX;
734     else if(flags & IMAGE_SCN_MEM_EXECUTE)
735         return Region::RP_RX;
736     else if(flags & IMAGE_SCN_MEM_WRITE)
737         return Region::RP_RW;
738     else
739         return Region::RP_R;
740 }
741
742 Region::RegionType getRegionType(DWORD flags){
743     if((flags & IMAGE_SCN_CNT_CODE) && (flags & IMAGE_SCN_CNT_INITIALIZED_DATA))
744         return Region::RT_TEXTDATA;
745     else if(flags & IMAGE_SCN_CNT_CODE)
746         return Region::RT_TEXT;
747     else if((flags & IMAGE_SCN_CNT_INITIALIZED_DATA) || (flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
748         return Region::RT_DATA;
749     else
750         return Region::RT_OTHER;
751 }
752
753 std::vector<std::pair<string, IMAGE_IMPORT_DESCRIPTOR> > & Object::getImportDescriptorTable()
754 {
755    if (!idt_.empty()) {
756       return idt_;
757    }
758
759    if (peHdr->OptionalHeader.NumberOfRvaAndSizes <= IMAGE_DIRECTORY_ENTRY_IMPORT)
760       assert(0 && "PE header doesn't specify the IDT address");
761
762    //1. get the RVA of import table from Data directory
763    DWORD dwITrva = peHdr->OptionalHeader.
764       DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
765    //printf("Import Table RVA: %lx\n", dwITrva);
766
767    //2. get the offset in disk file
768    DWORD dwIToffset = RVA2Offset(dwITrva);
769    //printf("import table disk offset: %lx\n", dwIToffset);
770
771    PIMAGE_IMPORT_DESCRIPTOR import_d = (PIMAGE_IMPORT_DESCRIPTOR)
772       (((char*)mf->base_addr())+dwIToffset);
773
774    while(import_d ->Name != NULL && import_d->FirstThunk !=NULL){
775       IMAGE_IMPORT_DESCRIPTOR ie;
776       memcpy(&ie, import_d, sizeof(IMAGE_IMPORT_DESCRIPTOR));
777       string str((char*)(((char*)mf->base_addr())+RVA2Offset(import_d->Name)));
778       idt_.push_back(pair<string,IMAGE_IMPORT_DESCRIPTOR>(str,ie));
779       //printf("%s\n",ie.name);
780       import_d ++;
781    }
782    return idt_;
783    //cout<<"size of import table"<<image_import_descriptor.size()<<endl;
784 }
785
786 map<string, map<string, WORD> > & Object::getHintNameTable()
787 {
788    if (!hnt_.empty()) {
789       return hnt_;
790    }
791
792    vector<pair<string, IMAGE_IMPORT_DESCRIPTOR> > idt = getImportDescriptorTable();
793    for (vector<pair<string, IMAGE_IMPORT_DESCRIPTOR> >::iterator dit = idt.begin();
794         dit != idt.end();
795         dit++) 
796    {
797       assert(sizeof(Offset) == getAddressWidth());
798       Offset * iat = (Offset*)((char*)mf->base_addr() + RVA2Offset(dit->second.FirstThunk));
799
800       for (unsigned idx=0; iat[idx] != 0; idx++) {
801          assert (0 == (0x80000000 & iat[idx])); //ensure IAT is not ordinal-based
802          IMAGE_IMPORT_BY_NAME *hintName = (IMAGE_IMPORT_BY_NAME *)
803             ((char*)mf->base_addr() + RVA2Offset(iat[idx]));
804          hnt_[dit->first][string((char*)hintName->Name)] = hintName->Hint;
805       }
806    }
807    
808    return hnt_;
809 }
810
811 void Object::FindInterestingSections(bool alloc_syms, bool defensive)
812 {
813    // now that we have the file mapped, look for 
814    // the .text and .data sections
815    assert( peHdr == NULL );
816    HANDLE mapAddr = mf->base_addr();
817    peHdr = ImageNtHeader( mapAddr );
818
819    if (peHdr == NULL) {
820       code_ptr_ = (char*)mapAddr;
821       code_off_ = 0;
822       HANDLE hFile = mf->getFileHandle();
823       code_len_ = mf->size();
824       is_aout_ = false;
825       fprintf(stderr,"Adding Symtab object with no program header, will " 
826               "designate it as code, code_ptr_=%lx code_len_=%lx\n",
827               code_ptr_,code_len_);
828       if (alloc_syms) {
829           Region *bufReg = new Region
830                     (0, //region number
831                      ".text", 
832                      code_off_, // disk offset
833                      code_len_, // disk size
834                      code_off_, // mem offset
835                      code_len_, // mem size
836                      code_ptr_, // raw data ptr
837                      Region::RP_RWX, 
838                      Region::RT_TEXT,
839                      true);// is loadable
840           regions_.push_back(bufReg);
841       }
842       return;
843    }
844
845    assert( peHdr->FileHeader.SizeOfOptionalHeader > 0 ); 
846
847    string file_ = mf->filename();
848    curModule = new Object::Module( file_, 0 );
849    assert( curModule != NULL );
850
851    curModule->SetIsDll( (peHdr->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0 );
852    if(curModule->IsDll())
853       is_aout_ = false;
854    else
855       is_aout_ = true;
856
857    getImportDescriptorTable(); //save the binary's original table, we may change it later
858    
859
860
861    //get exported functions
862    // note: there is an error in the PE specification regarding the export 
863    //       table Base.  The spec claims that you are supposed to subtract 
864    //       the Base to get correct ordinal indices into the Export Address 
865    //       table, but this is false, at least in the typical case for which 
866    //       Base=1, I haven't observed any binaries with different bases
867         if (!is_aout_ && peHdr->OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXPORT) {
868                 assert(sizeof(Offset) == getAddressWidth());
869                 unsigned long size;
870                 IMAGE_EXPORT_DIRECTORY *eT2 = (IMAGE_EXPORT_DIRECTORY *)::ImageDirectoryEntryToData(mapAddr, false, IMAGE_DIRECTORY_ENTRY_EXPORT, &size);
871                 if (eT2) {
872                         DWORD *funcNamePtrs = (DWORD *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, ULONG(eT2->AddressOfNames), NULL);
873                         DWORD *funcAddrs = (DWORD *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, ULONG(eT2->AddressOfFunctions), NULL);
874                         WORD *funcAddrNameMap = (WORD *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, ULONG(eT2->AddressOfNameOrdinals), NULL);
875                         if (funcNamePtrs && funcAddrs && funcAddrNameMap) {
876                                 for (unsigned i = 0; i < eT2->NumberOfNames; ++i) {
877                                         char *name = (char *) ::ImageRvaToVa(ImageNtHeader(mapAddr), mapAddr, funcNamePtrs[i], NULL);
878                                         
879                                         if (!strcmp(name,"??_7__non_rtti_object@@6B@") || !strcmp(name,"??_7bad_cast@@6B@") || !strcmp(name,"??_7bad_typeid@@6B@") || !strcmp(name,"??_7exception@@6B@") || !strcmp(name,"sys_errlist"))
880                                         {
881                                         continue;
882                                         }
883                                         if (!strcmp(name,"??_7__non_rtti_object@std@@6B@") || !strcmp(name,"??_7bad_cast@std@@6B@") || !strcmp(name,"??_7bad_typeid@std@@6B@") || !strcmp(name,"??_7exception@std@@6B@"))
884                                         {
885                                         continue;
886                                         }
887                                         int funcIndx = funcAddrNameMap[i];
888                                         Address funcAddr = funcAddrs[funcIndx];
889                                         if ((funcAddr >= (Address) eT2) &&
890                                                 (funcAddr < ((Address) eT2 + size))) continue;
891                                         Symbol *sym = new Symbol(name,
892                                                 Symbol::ST_FUNCTION, 
893                                         Symbol::SL_GLOBAL, 
894                                     Symbol::SV_DEFAULT,
895                                         funcAddr);
896                                         sym->setDynamic(true); // it's exported, equivalent to ELF dynamic syms
897                                         symbols_[name].push_back(sym);
898                                         symsToModules_[sym] = curModule->GetName();
899                                 }
900                         }
901                 }
902         }
903
904    SecAlignment = peHdr ->OptionalHeader.SectionAlignment;
905    unsigned int nSections = peHdr->FileHeader.NumberOfSections;
906    no_of_sections_ = nSections;
907    Address prov_begin = (Address)-1;
908    Address prov_end = (Address)-1;
909    code_off_ = (Address)-1;
910    code_len_ = (Address)-1;
911
912    if (defensive) {
913        // add section for peHdr, determine the size taken up by the section 
914        // in the program's address space.  
915        unsigned long secSize = ( peHdr->OptionalHeader.SizeOfHeaders 
916                                  / peHdr->OptionalHeader.SectionAlignment ) 
917                               * peHdr->OptionalHeader.SectionAlignment;
918        if (  peHdr->OptionalHeader.SizeOfHeaders 
919            % peHdr->OptionalHeader.SectionAlignment ) 
920        {
921           secSize += peHdr->OptionalHeader.SectionAlignment;
922        }
923        prov_begin = 0;
924        prov_end = prov_begin + secSize;
925        regions_.push_back(
926            new Region(
927             0, "PROGRAM_HEADER", 0, peHdr->OptionalHeader.SizeOfHeaders, 
928             0, secSize, (char*)mapAddr,
929             getRegionPerms(IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_WRITE), 
930             getRegionType(IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA),
931             true));
932    }
933
934    PIMAGE_SECTION_HEADER pScnHdr = (PIMAGE_SECTION_HEADER)(((char*)peHdr) + 
935                                  sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) +
936                                  peHdr->FileHeader.SizeOfOptionalHeader);
937    bool foundText = false;
938    for( unsigned int i = 0; i < nSections; i++ ) {
939       // rawDataPtr should be set to be zero if the amount of raw data
940       // for the section is zero
941
942       Offset diskOffset = 0; 
943       if (pScnHdr->SizeOfRawData != 0) {
944          // the loader rounds PointerToRawData to the previous fileAlignment 
945          // boundary  (usually 512 bytes)
946          diskOffset = (Offset)
947              ((pScnHdr->PointerToRawData / peHdr->OptionalHeader.FileAlignment) 
948               * peHdr->OptionalHeader.FileAlignment);
949       }
950       Offset secSize = (pScnHdr->Misc.VirtualSize > pScnHdr->SizeOfRawData) ? 
951           pScnHdr->Misc.VirtualSize : pScnHdr->SizeOfRawData;
952       if (alloc_syms)
953           regions_.push_back
954               (new Region(i+1, 
955                           (const char *)pScnHdr->Name,
956                           diskOffset,
957                           pScnHdr->SizeOfRawData,
958                           pScnHdr->VirtualAddress, 
959                           secSize,
960                           (char *)(diskOffset + (Offset)mapAddr), 
961                           getRegionPerms(pScnHdr->Characteristics),
962                           getRegionType(pScnHdr->Characteristics)));
963 //        regions_.push_back(new Section(i, (const char*)pScnHdr->Name, 
964 //                                      pScnHdr->VirtualAddress, 
965 //                                      pScnHdr->Misc.VirtualSize, 
966 //                                      rawDataPtr));
967
968       if( strncmp( (const char*)pScnHdr->Name, ".text", 8 ) == 0 ) {
969          // note that section numbers are one-based
970          textSectionId = i + 1;
971          code_ptr_    = (char*)(((char*)mapAddr) +
972                                 pScnHdr->PointerToRawData);
973          code_off_    = pScnHdr->VirtualAddress;
974
975          // Since we're reporting the size of sections on the disk,
976          // we need to check whether the size of raw data is smaller.
977          //code_len_    = pScnHdr->Misc.VirtualSize;
978          code_len_ = ((pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize) ?
979                       pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize);
980
981          foundText = true;
982          if (prov_begin == -1) {
983              prov_begin = code_off_;
984              prov_end = code_off_ + code_len_;
985          } else {
986              if (prov_begin > code_off_) {
987                  prov_begin = code_off_;
988              }
989              if ( prov_end < (code_off_ + code_len_) ) {
990                   prov_end = (code_off_ + code_len_);
991              }
992          }
993       }
994       else if( strncmp( (const char*)pScnHdr->Name, ".data", 8 ) == 0 ) {
995          // note that section numbers are one-based
996          dataSectionId = i + 1;
997          data_ptr_    = (char *)(((char*)mapAddr) +
998                                  pScnHdr->PointerToRawData);
999          data_off_    = pScnHdr->VirtualAddress;
1000          data_len_ = (pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize ?
1001                       pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize);
1002          if (defensive) { // don't parse .data in a non-defensive binary
1003              if (prov_begin == -1) {
1004                 prov_begin = data_off_;
1005                 prov_end = data_off_ + data_len_;
1006              } else {
1007                  if (prov_begin > data_off_) {
1008                      prov_begin = data_off_;
1009                  }
1010                  if (prov_end < (data_off_ + data_len_)) {
1011                      prov_end = (data_off_ + data_len_);
1012                  }
1013              }
1014          }
1015       }
1016       else {
1017          Offset sec_len = (pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize) ?
1018                            pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize;
1019          if (-1 == prov_begin) {
1020             prov_begin = pScnHdr->VirtualAddress;
1021             prov_end = prov_begin + sec_len;
1022          } else {
1023              if (prov_begin > pScnHdr->VirtualAddress) {
1024                  prov_begin = pScnHdr->VirtualAddress;
1025              }
1026              if (prov_end < (pScnHdr->VirtualAddress + sec_len)) {
1027                  prov_end = (pScnHdr->VirtualAddress + sec_len);
1028              }
1029          }
1030       }
1031       pScnHdr += 1;
1032    } // end section for loop
1033
1034    if (-1 == code_len_ || defensive) {
1035        // choose the smaller/larger of the two offsets/lengths, 
1036        // if both are initialized (i.e., are not equal to -1)
1037        if (code_off_ == -1)
1038            code_off_ = prov_begin;
1039        else if (prov_begin != -1 && 
1040                 code_off_ > prov_begin) 
1041            code_off_ = prov_begin;
1042
1043        if (code_len_ == -1)
1044            code_len_ = prov_end - code_off_;
1045        else if (prov_end != -1 &&
1046                 code_len_ < (prov_end - code_off_))
1047            code_len_ = (prov_end - code_off_);
1048
1049        assert(code_off_ != -1 && code_len_ != -1); // no sections in binary? 
1050    }
1051 }
1052
1053 // Assumes region list is sorted and regions don't overlap
1054 Region *Object::findEnclosingRegion(const Offset where)
1055 {
1056     // search for "where" in regions (regions must not overlap)
1057     int first = 0; 
1058     int last = regions_.size() - 1;
1059     while (last >= first) {
1060         Region *curreg = regions_[(first + last) / 2];
1061         if (where >= curreg->getMemOffset()
1062             && where < (curreg->getMemOffset()
1063                         + curreg->getMemSize())) {
1064             return curreg;
1065         }
1066         else if (where < curreg->getMemOffset()) {
1067             last = ((first + last) / 2) - 1;
1068         }
1069         else {/* where >= (cursec->getSecAddr()
1070                            + cursec->getSecSize()) */
1071             first = ((first + last) / 2) + 1;
1072         }
1073     }
1074     return NULL;
1075 }
1076
1077 bool Object::isForwarded( Offset addr )
1078 {
1079         //calls to forwarded symbols are routed to another dll and 
1080     //are not in the current dll's code space
1081         //we MUST NOT try to parse these - bad things happen
1082         
1083         //we detect forwarded symbols by checking if the relative 
1084         //virtual address of the symbol falls within the dll's exports section
1085         if(peHdr && peHdr->FileHeader.Characteristics & IMAGE_FILE_DLL )
1086         {
1087                 PIMAGE_DATA_DIRECTORY dataDir = peHdr->OptionalHeader.DataDirectory;
1088                 Offset exportStart = dataDir->VirtualAddress;
1089                 Offset exportEnd = exportStart + dataDir->Size;
1090                 if( addr >= exportStart && addr < exportEnd )
1091                         return true;  //this sym is forwarded
1092         }
1093         return false;
1094 }
1095
1096 bool Object::getCatchBlock(ExceptionBlock &b, Offset addr, 
1097                            unsigned size) const 
1098
1099    return false; 
1100 }
1101
1102 bool Object::isText( const Offset addr ) const 
1103 {
1104    return( addr >= code_off_ && addr < code_off_ + code_len_ );
1105 }
1106
1107 void fixup_filename(std::string &filename)
1108 {
1109         if (filename.substr(0,22) == "\\Device\\HarddiskVolume") {
1110                 TCHAR volumePath[1024];
1111                 if (GetVolumePathName(filename.c_str(), volumePath, 1024)) {
1112                         std::string::size_type filePathIndex = filename.find_first_of("\\/", 22);
1113                         if (filePathIndex != std::string::npos)
1114                                 filename = volumePath + filename.substr(++filePathIndex);
1115                         else
1116                                 filename = volumePath + filename.substr(23);
1117                 } else {
1118                         filename = "c:"+filename.substr(23);
1119                 }
1120         }
1121 }
1122
1123 Object::Object(MappedFile *mf_,
1124                bool defensive, 
1125                void (*err_func)(const char *), bool alloc_syms) :
1126     AObject(mf_, err_func),
1127     curModule( NULL ),
1128     baseAddr( 0 ),
1129     imageBase( 0 ),
1130         preferedBase( 0 ),
1131     peHdr( NULL ),
1132     trapHeaderPtr_( 0 ),
1133     SecAlignment( 0 ),
1134     textSectionId( 0 ),
1135     dataSectionId( 0 ),
1136     hProc( NULL )
1137 {
1138    FindInterestingSections(alloc_syms, defensive);
1139    if (alloc_syms && defensive) {
1140       AddTLSFunctions();
1141    }
1142    ParseSymbolInfo(alloc_syms);
1143    preferedBase = imageBase;
1144    rebase(0);
1145 }
1146
1147 SYMTAB_EXPORT ObjectType Object::objType() const 
1148 {
1149         return is_aout() ? obj_Executable : obj_SharedLib;
1150 }
1151
1152
1153 void Object::getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *mod_langs)
1154 {
1155         return;
1156 }
1157
1158 struct line_info_tmp_t {
1159         line_info_tmp_t(unsigned long a, unsigned int l) {addr = a; line_no = l;}
1160         unsigned long addr;
1161         unsigned int line_no;
1162 };
1163
1164 struct line_info_tmp_lt {
1165         bool operator()(const line_info_tmp_t &a, const line_info_tmp_t &b) {
1166       return a.addr < b.addr;
1167         };
1168 };
1169
1170 typedef std::multiset<line_info_tmp_t, line_info_tmp_lt> info_for_file_t;
1171 typedef std::map<std::string, info_for_file_t*> info_for_all_files_t;
1172
1173 static BOOL CALLBACK add_line_info(SRCCODEINFO *srcinfo, void *param)
1174 {
1175         info_for_all_files_t *all_info = (info_for_all_files_t *) param;
1176         info_for_all_files_t::iterator iter = all_info->find(std::string(srcinfo->FileName));
1177         info_for_file_t *finfo = NULL;
1178         if (iter == all_info->end()) {
1179                 finfo = new info_for_file_t();
1180                 (*all_info)[std::string(srcinfo->FileName)] = finfo;
1181         }
1182         else {
1183                 finfo = (*iter).second;
1184         }
1185         finfo->insert(line_info_tmp_t((unsigned long) srcinfo->Address, srcinfo->LineNumber));
1186         return true;
1187 }
1188
1189 static bool store_line_info(Symtab* st, info_for_all_files_t *baseInfo)
1190 {
1191    for (info_for_all_files_t::iterator i = baseInfo->begin(); i != baseInfo->end(); i++)
1192    {
1193            const char *filename = (*i).first.c_str();
1194            Module* mod;
1195            
1196            if(!st->findModuleByName(mod, filename)) 
1197            {
1198              mod = st->getDefaultModule();
1199            }    
1200            LineInformation* li_for_module = mod->getLineInformation();
1201            if(!li_for_module) 
1202            {
1203              li_for_module = new LineInformation;
1204              mod->setLineInfo(li_for_module);
1205            }
1206
1207            for (info_for_file_t::iterator j = (*i).second->begin(); j != (*i).second->end(); j++) {
1208                    info_for_file_t::iterator next = j;
1209                    next++;
1210                    if (next != (*i).second->end())
1211                            li_for_module->addLine(filename, j->line_no, 0, j->addr, next->addr);
1212                    else
1213                            li_for_module->addLine(filename, j->line_no, 0, j->addr, j->addr);
1214            }
1215            delete (*i).second;
1216    }
1217    return true;
1218 }
1219
1220 void Object::parseFileLineInfo(Symtab *st)
1221 {   
1222   if(parsedAllLineInfo) return;
1223   
1224   int result;
1225   static Offset last_file = 0x0;
1226
1227   Offset baseAddr = get_base_addr();
1228   if (last_file == baseAddr)
1229     return;
1230   last_file = baseAddr;
1231   info_for_all_files_t inf;
1232   result = SymEnumLines(hProc, 
1233                               baseAddr,
1234                               NULL, 
1235                               NULL,
1236                               add_line_info, 
1237                               &inf); 
1238   // Set to true once we know we've done as much as we can
1239   parsedAllLineInfo = true;
1240   if (!result) {
1241     //Not a big deal. The module probably didn't have any debug information.
1242     DWORD dwErr = GetLastError();
1243     //printf("[%s:%u] - Couldn't SymEnumLines on %s in %s\n", 
1244         //         __FILE__, __LINE__, src_file_name, libname);
1245     return;
1246   }
1247   store_line_info(st, &inf);
1248   
1249 }
1250
1251 typedef struct localsStruct {
1252     Function *func;
1253     Offset base;
1254     HANDLE p;
1255     map<unsigned, unsigned> foundSyms;
1256     localsStruct() : foundSyms() {}
1257 } localsStruct;
1258
1259 Dyninst::MachRegister WinConvert(Register reg) {
1260         //  Info from CV_HREG_e structure; from comments online this is correct
1261         switch(reg) {
1262         case CV_REG_EAX:
1263                 return x86::eax;
1264         case CV_REG_EBX:
1265                 return x86::ebx;
1266         case CV_REG_ECX:
1267                 return x86::ecx;
1268         case CV_REG_EDX:
1269                 return x86::edx;
1270         case CV_REG_ESP:
1271                 return x86::esp;
1272         case CV_REG_EBP:
1273                 return x86::ebp;
1274         case CV_REG_ESI:
1275                 return x86::esi;
1276         case CV_REG_EDI:
1277                 return x86::edi;
1278         default:
1279                 return Dyninst::InvalidReg;
1280         }
1281 }
1282
1283 BOOL CALLBACK enumLocalSymbols(PSYMBOL_INFO pSymInfo, unsigned long symSize,
1284                                void *userContext)
1285 {
1286     Type *type;
1287     Function *func;
1288     storageClass storage;
1289     localVar *newvar;
1290     MachRegister reg;
1291     signed long frameOffset;
1292     Offset base;
1293     HANDLE p;
1294  
1295     char *storageName;
1296     char *paramType;
1297
1298     //
1299     //Skip this variable if it's already been found.
1300     //
1301     localsStruct *locals = (localsStruct *) userContext;
1302     if (locals->foundSyms.find(pSymInfo->Index) != locals->foundSyms.end())
1303         return true;
1304     locals->foundSyms[pSymInfo->Index] = 1;
1305     base = locals->base;
1306     func = locals->func;
1307     p = locals->p;
1308
1309     //Get type
1310     type = getType(p, base, pSymInfo->TypeIndex, func->getModule());
1311     
1312     //Get variable storage location information
1313     if ((pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE) ||
1314         ((pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) && 
1315          (pSymInfo->Register = CV_REG_EBP)))
1316     {
1317                 reg = x86::ebp;
1318                 frameOffset = (signed) pSymInfo->Address;
1319         storage = storageRegOffset;
1320         storageName = "Frame Relative";
1321     }
1322     else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE)
1323     {
1324         reg = WinConvert(pSymInfo->Register);
1325         frameOffset = (signed) pSymInfo->Address;
1326         storage = storageRegOffset;
1327         storageName = "Register Relative";
1328     }
1329     else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) {
1330         reg = WinConvert(pSymInfo->Register);
1331         frameOffset = 0;
1332         storage = storageReg;
1333         storageName = "Register";
1334     }
1335     else {
1336         frameOffset = (signed) pSymInfo->Address;
1337         storage = storageAddr;
1338         storageName = "Absolute";
1339     }
1340         
1341         VariableLocation loc;
1342         loc.stClass = storage;
1343         loc.refClass = storageNoRef;
1344         loc.frameOffset = frameOffset;
1345         loc.lowPC = 0;
1346         loc.hiPC = (Address) -1;
1347         loc.mr_reg = reg;
1348         
1349         std::string vName = convertCharToString(pSymInfo->Name);
1350         std::string fName = convertCharToString(func->getModule()->fileName().c_str());
1351    newvar = new localVar(vName, type, fName, -1, func);
1352         newvar->addLocation(loc);
1353
1354     //Store the variable as a local or parameter appropriately
1355    if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) {
1356       assert(func);
1357       if (!func->addParam(newvar)) {
1358          fprintf(stderr, "%s[%d]:  addParam failed\n", FILE__, __LINE__);
1359          return false;
1360       }
1361       paramType = "parameter";
1362    }
1363    else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) {
1364           assert(func);
1365       if (!func->addLocalVar(newvar)) {
1366          fprintf(stderr, "%s[%d]:  addLocalVar failed\n", FILE__, __LINE__);
1367          return false;
1368       }
1369       paramType = "local";
1370    }
1371    else {
1372            
1373       fprintf(stderr, "[%s:%u] - Local variable of unknown type.  %s in %s\n",
1374               __FILE__, __LINE__, pSymInfo->Name, func->pretty_names_begin()->c_str());
1375       paramType = "unknown";
1376    }
1377
1378     
1379    const char *typeName;
1380    if (type) {
1381       typeName = type->getName().c_str();
1382    }
1383    else {
1384       typeName = "unknown";
1385    }
1386    
1387    return true;
1388 }
1389
1390
1391 static void enumLocalVars(Function *func, 
1392                           localsStruct *locals) 
1393 {
1394     IMAGEHLP_STACK_FRAME frame;
1395     memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
1396
1397     frame.InstructionOffset = locals->base + func->getOffset();
1398     int result = SymSetContext(locals->p, &frame, NULL);
1399         /*if (!result) {            
1400                 fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
1401         printSysError(GetLastError());
1402     }*/
1403     result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1404         /*if (!result) {
1405         fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
1406         printSysError(GetLastError());
1407     }*/
1408         
1409         if(func->getSize())
1410         {
1411                 memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
1412
1413                 frame.InstructionOffset = locals->base +
1414                     func->getOffset() + 
1415                     func->getSize();
1416                 result = SymSetContext(locals->p, &frame, NULL);
1417                 result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1418         }
1419
1420 //TODO?? replace this with??
1421 #if 0
1422     for (unsigned i=0; i<points.size(); i++) {
1423         frame.InstructionOffset = points[i]->addr();
1424         bool result = SymSetContext(locals->p, &frame, NULL);
1425         /*if (!result) {            
1426             fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
1427             printSysError(GetLastError());
1428         }*/
1429         result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1430         /*if (!result) {
1431             fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
1432             printSysError(GetLastError());
1433         }*/
1434     }
1435 #endif
1436
1437 }
1438
1439 static int variantValue(VARIANT *v) {
1440     switch(v->vt) {    
1441        case VT_I8:
1442            return (int) v->llVal;
1443        case VT_I4:
1444            return (int) v->lVal;
1445        case VT_UI1:
1446            return (int) v->bVal;
1447        case VT_I2:
1448            return (int) v->iVal;
1449        case VT_I1:
1450            return (int) v->cVal;
1451        case VT_UI2:
1452            return (int) v->uiVal;
1453        case VT_UI4:
1454            return (int) v->ulVal;
1455        case VT_UI8:
1456            return (int) v->ullVal;
1457        case VT_INT:
1458            return (int) v->intVal;
1459        case VT_UINT:
1460            return (int) v->uintVal;
1461        default:
1462            return 0;
1463     }
1464 }
1465
1466 // Changed. Not adding to stdTypes now
1467 static void addTypeToCollection(Type *type, Module *mod) 
1468 {
1469         typeCollection *tc = typeCollection::getModTypeCollection(mod);
1470         assert(tc);
1471         tc->addType(type);
1472 /*         
1473    typeCollection *collection;
1474
1475    collection = mod ? tc : Symtab::stdTypes;
1476    assert(collection);
1477    assert(!collection->findType(type->getID()));
1478    collection->addType(type);
1479 */
1480 }
1481
1482 static char *getTypeName(HANDLE p, Offset base, int typeIndex) {
1483     int result, length;
1484     WCHAR *wname = NULL;
1485     char *name = NULL;
1486
1487     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMNAME, &wname);
1488     if (!result) 
1489         return NULL;
1490     length = wcslen(wname) + 1;
1491     name = (char *) malloc(length + 1);
1492     result = WideCharToMultiByte(CP_ACP, 0, wname, -1, name, length, NULL, NULL);
1493     LocalFree(wname); 
1494     if (!result) {
1495         int lasterror = GetLastError();
1496 //        printSysError(lasterror);
1497         return NULL;
1498     }
1499     return name;
1500 }
1501
1502 static dataClass getDataClass(HANDLE p, Offset base, int typeIndex) {
1503     enum SymTagEnum wintype;
1504     int result, basetype;
1505
1506     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &wintype);
1507     if (!result)
1508         return dataUnknownType;
1509     switch (wintype) {
1510         case SymTagFunction:
1511         case SymTagFunctionType:
1512             return dataFunction;
1513         case SymTagPointerType:
1514             return dataPointer;
1515         case SymTagArrayType:
1516             return dataArray;
1517         case SymTagBaseType:
1518             return dataScalar;
1519         case SymTagEnum:
1520             return dataEnum;
1521         case SymTagTypedef:
1522             return dataTypedef;
1523         case SymTagUDT:
1524             enum UdtKind udtType;
1525             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
1526             if (!result)
1527                 return dataUnknownType;
1528             switch (udtType) {
1529                 case UdtUnion:
1530                     return dataUnion;
1531                 case UdtStruct:
1532                 case UdtClass:
1533                     return dataStructure;
1534                 default:
1535                     return dataUnknownType;
1536             }
1537         case SymTagFunctionArgType:
1538             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &basetype);
1539             if (!result)
1540                 return dataUnknownType;
1541             return getDataClass(p, base, basetype);
1542         default:
1543             return dataUnknownType;
1544     }
1545 }
1546
1547 static Type *getEnumType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1548     unsigned i;
1549     char *name = NULL;
1550     char *entryName = NULL;
1551     VARIANT entryValue;
1552     typeEnum *type;
1553     int result;
1554     unsigned numEntries, entriesSize;
1555     TI_FINDCHILDREN_PARAMS *entries = NULL;
1556
1557     name = getTypeName(p, base, typeIndex);
1558         std::string tName = convertCharToString(name);
1559     type = new typeEnum(typeIndex, tName);
1560     addTypeToCollection(type, mod);
1561     free(name);
1562     name = NULL;
1563
1564     //
1565     //Get the number of entries in this enum, and store them in the entries structure
1566     //
1567     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numEntries);
1568     if (!result)
1569         numEntries = 0;
1570     if (numEntries) {
1571         entriesSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numEntries + 1) * sizeof(ULONG);
1572         entries = (TI_FINDCHILDREN_PARAMS *) malloc(entriesSize);
1573         memset(entries, 0, entriesSize);
1574         entries->Count = numEntries;
1575         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, entries);
1576         if (!result)
1577             numEntries = 0;
1578     }
1579
1580     for (i=0; i<numEntries; i++) {
1581         entryName = getTypeName(p, base, entries->ChildId[i]);
1582         VariantInit(&entryValue);
1583         result = SymGetTypeInfo(p, base, entries->ChildId[i], TI_GET_VALUE, &entryValue);
1584         if (!result)
1585             continue;
1586         type->addConstant(entryName, variantValue(&entryValue));
1587     }
1588   
1589     if (entries)
1590         free(entries);
1591     return type;    
1592 }
1593
1594 static Type *getPointerType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1595     int baseTypeIndex, result;
1596     Type *baseType;
1597     typePointer *newType;
1598
1599     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
1600     if (!result) {
1601         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1602         return NULL;
1603     }
1604
1605     //
1606     // Add a place-holder for the pointer type first and fill in it's 
1607     //  base type latter.  This prevents recursion that may happen beneath 
1608     //  the getType function call below.
1609     //
1610     newType = new typePointer(typeIndex, NULL);
1611     addTypeToCollection(newType, mod);
1612
1613     baseType = getType(p, base, baseTypeIndex, mod);
1614     if (!baseType) {
1615         fprintf(stderr, "[%s:%u] - getType failed\n", __FILE__, __LINE__);
1616         return NULL;
1617     }
1618
1619     newType->setPtr(baseType);
1620     return newType;
1621 }
1622
1623 static Type *getArrayType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1624     int result, baseIndex, index;
1625     Type *indexType, *newType, *baseType;
1626     unsigned size, num_elements;
1627     ULONG64 size64;
1628     std::string bname;
1629     std::string name;
1630
1631     //Get the index type (usually an int of some kind).  Currently not used.
1632     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_ARRAYINDEXTYPEID, &index);
1633     if (!result) {
1634         fprintf(stderr, "[%s:%u] - TI_GET_ARRAYINDEXTYPEID failed\n", 
1635                 __FILE__, __LINE__);
1636         return NULL;
1637     }
1638     indexType = getType(p, base, index, mod);
1639
1640     //Get the base type (the type of the elements in the array)
1641     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseIndex);
1642     if (!result) {
1643         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1644         return NULL;
1645     }
1646     baseType = getType(p, base, baseIndex, mod);
1647
1648     bname = baseType->getName();
1649     name = bname + "[]";
1650         
1651     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1652     if (!result) {
1653         num_elements = 0;
1654     }
1655     else {
1656       size = (unsigned) size64;
1657       num_elements = size / baseType->getSize();
1658     }
1659
1660     newType = new typeArray(typeIndex, baseType, 0, num_elements-1, name);
1661     newType->getSize();
1662     addTypeToCollection(newType, mod);
1663     assert(newType->getID() == typeIndex);
1664
1665     return newType;
1666 }
1667
1668
1669 static Type *getTypedefType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1670     int result, baseTypeIndex;
1671     Type *baseType, *newType;
1672     char *name;
1673
1674     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
1675     if (!result) {
1676         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1677         return NULL;
1678     }
1679     baseType = getType(p, base, baseTypeIndex, mod);
1680     if (!baseType) {
1681         return NULL;
1682     }
1683  
1684     name = getTypeName(p, base, typeIndex);
1685         std::string tName = convertCharToString(name);
1686     newType = new typeTypedef(typeIndex, baseType, tName);
1687     addTypeToCollection(newType, mod);
1688     return newType;
1689 }
1690
1691 static Type *getUDTType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1692     int result, symtag;
1693     unsigned size, numChildren, childrenSize, child_offset, i, child_size;
1694     fieldListType *newType;
1695     UINT64 size64;
1696     const char *name, *childName;
1697     enum UdtKind udtType;
1698     TI_FINDCHILDREN_PARAMS *children = NULL;
1699
1700     //
1701     // Get name for structure
1702     //
1703     name = getTypeName(p, base, typeIndex);
1704         std::string tName = convertCharToString(name);
1705         result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1706     if (!result) {
1707         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
1708         return NULL;
1709     }
1710     size = (unsigned) size64;
1711
1712     //
1713     // Determine whether it's a class, struct, or union and create the 
1714     //  new_type appropriately
1715     //
1716     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
1717     if (!result) {
1718         fprintf(stderr, "[%s:%u] - TI_GET_UDTKIND returned error\n");
1719         return NULL;
1720     }
1721     switch (udtType) {
1722         case UdtUnion:
1723             newType = new typeUnion(typeIndex, tName);
1724             break;
1725         case UdtStruct:
1726         case UdtClass:
1727         default:
1728             newType = new typeStruct(typeIndex, tName);
1729             break;
1730     }
1731     addTypeToCollection(newType, mod);
1732     if (name)
1733        free((void *) name);
1734     name = NULL;
1735
1736
1737     //
1738     // Store the number of member variables/functions/stuff in numChildren
1739     //
1740     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numChildren);
1741     if (!result)
1742         numChildren = 0;
1743     //
1744     // Get the list of variables/functions/stuff
1745     //
1746     if (numChildren) {
1747         childrenSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numChildren + 1) * sizeof(ULONG);
1748         children = (TI_FINDCHILDREN_PARAMS *) malloc(childrenSize);
1749         memset(children, 0, childrenSize);
1750         children->Count = numChildren;
1751         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, children);
1752         if (!result)
1753             numChildren = 0;
1754     }
1755
1756     //
1757     // Create/Find the type of each child and add it to newType appropriately
1758     //
1759     for (i=0; i<numChildren; i++) {
1760         // Create/Get child type
1761         Type *child_type = getType(p, base, children->ChildId[i], mod);
1762         if (!child_type)
1763             continue;
1764
1765         // Figure out a name of this object
1766         childName = NULL;
1767         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_SYMTAG, &symtag);
1768         if (result && symtag == SymTagBaseClass) {
1769             childName = P_strdup("{superclass}");
1770         }
1771         if (!childName)
1772             childName = getTypeName(p, base, children->ChildId[i]);
1773         if (!childName) 
1774             childName = P_strdup(child_type->getName().c_str());
1775
1776         // Find the offset of this member in the structure
1777         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_OFFSET, &child_offset);
1778         if (!result) {
1779             child_offset = 0; //Probably a member function
1780             child_size = 0;
1781         }
1782         else {
1783             child_offset *= 8; //Internally measured in bits
1784             child_size = child_type->getSize();
1785         }
1786
1787                 std::string fName = convertCharToString(childName);
1788         newType->addField(fName, child_type, child_offset);
1789         if (childName)
1790             free((void *) childName);
1791         childName = NULL;
1792     }
1793
1794     if (children)
1795         free(children);
1796
1797     return newType;
1798 }
1799
1800 static Type *getLayeredType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1801     int result, newTypeIndex;
1802     Type *newType;
1803
1804     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &newTypeIndex);
1805     if (!result) {
1806         fprintf(stderr, "TI_GET_TYPEID failed\n");
1807         return NULL;
1808     }
1809
1810     newType = getType(p, base, newTypeIndex, mod);
1811     return newType;
1812 }
1813
1814 static Type *getFunctionType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1815     int result, retTypeIndex;
1816     typeFunction *newType;
1817     Type *retType;
1818     unsigned num_params, args_size, i;
1819     std::vector<Type *> params;
1820     TI_FINDCHILDREN_PARAMS *args = NULL;
1821     std::string name;
1822
1823     //Create the function early to avoid recursive references
1824         std::string tName = "";
1825     newType = new typeFunction(typeIndex, NULL, tName);
1826     addTypeToCollection(newType, mod);
1827
1828     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &retTypeIndex);
1829     if (!result) {
1830         fprintf(stderr, "[%s:%u] - Couldn't TI_GET_TYPEID\n", __FILE__, __LINE__);
1831         return NULL;
1832     }
1833
1834     retType = getType(p, base, retTypeIndex, mod);
1835     if (!retType) {
1836         return NULL;
1837     }
1838     newType->setRetType(retType);
1839
1840     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_COUNT, &num_params);
1841     if (!result)
1842         goto done_params;
1843
1844     args_size = sizeof(TI_FINDCHILDREN_PARAMS) + (num_params + 1) * sizeof(ULONG);
1845     args = (TI_FINDCHILDREN_PARAMS *) malloc(args_size);
1846     memset(args, 0, args_size);
1847     args->Count = num_params;
1848     result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, args);
1849     if (!result)
1850         goto done_params;
1851     
1852     for (i=0; i<num_params; i++) {
1853         Type *arg_type = getType(p, base, args->ChildId[i], mod);
1854         if (!arg_type) {
1855             continue;
1856         }
1857         params.push_back(arg_type);
1858     }
1859
1860 done_params:
1861
1862     //
1863     // Build a type name that looks like the following:
1864     //   (return_type)(param1_type, param2_type, ...)
1865     name = "(";
1866     name += retType->getName();
1867     name += ")(";
1868     for (i=0; i<params.size(); i++) {
1869         if (i != 0)
1870             name += ", ";
1871         name += params[i]->getName();
1872     }
1873     name += "()";
1874         
1875         std::string newName = name;
1876     newType->setName(newName);
1877
1878     for (i=0; i<params.size(); i++) {
1879         //TODO?? have a name for the parameter. Required??
1880         newType->addParam(params[i]);
1881     }
1882
1883     if (args)
1884         free(args);
1885
1886     return newType;
1887 }
1888
1889 static Type *getBaseType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1890     BasicType baseType;
1891     int result;
1892     ULONG64 size64;
1893     unsigned size;
1894     Type *newType;
1895
1896     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_BASETYPE, &baseType);
1897     if (!result) {
1898         fprintf(stderr, "[%s:%u] - TI_GET_BASETYPE return error\n");
1899         return NULL;
1900     }
1901
1902     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1903     if (!result) {
1904         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
1905         return NULL;
1906     }
1907     size = (unsigned) size64;
1908     switch(baseType) {
1909          case btNoType:
1910                  newType = NULL;
1911                  break;
1912          case btVoid:
1913          newType = new typeScalar(typeIndex, size, "void");
1914                  break;
1915          case btChar:
1916          newType = new typeScalar(typeIndex, size, "char");
1917                  break;
1918          case btWChar:
1919          newType = new typeScalar(typeIndex, size, "wchar");
1920                  break;
1921          case btInt:
1922          if (size == 8)
1923            newType = new typeScalar(typeIndex, size, "long long int");
1924          else if (size == 4)
1925            newType = new typeScalar(typeIndex, size, "int");
1926          else if (size == 2)
1927            newType = new typeScalar(typeIndex, size, "short");
1928          else if (size == 1)
1929            newType = new typeScalar(typeIndex, size, "char");
1930          else
1931            newType = new typeScalar(typeIndex, size, "");
1932                  break;
1933          case btUInt:
1934          if (size == 8)
1935            newType = new typeScalar(typeIndex, size, "unsigned long long int");
1936          else if (size == 4)
1937            newType = new typeScalar(typeIndex, size, "unsigned int");
1938          else if (size == 2)
1939            newType = new typeScalar(typeIndex, size, "unsigned short");
1940          else if (size == 1)
1941            newType = new typeScalar(typeIndex, size, "unsigned char");
1942          else
1943            newType = new typeScalar(typeIndex, size, "");
1944                  break;
1945          case btFloat:
1946          if (size == 8)
1947              newType = new typeScalar(typeIndex, size, "double");
1948          else
1949              newType = new typeScalar(typeIndex, size, "float");
1950                  break;
1951          case btBCD:
1952          newType = new typeScalar(typeIndex, size, "BCD");
1953                  break;
1954          case btBool:
1955          newType = new typeScalar(typeIndex, size, "bool");
1956                  break;
1957          case btLong:
1958          newType = new typeScalar(typeIndex, size, "long");
1959                  break;
1960          case btULong:
1961          newType = new typeScalar(typeIndex, size, "unsigned long");
1962                  break;
1963          case btCurrency:
1964          newType = new typeScalar(typeIndex, size, "currency");
1965                  break;
1966          case btDate:
1967          newType = new typeScalar(typeIndex, size, "Date");
1968                  break;
1969          case btVariant:
1970          newType = new typeScalar(typeIndex, size, "variant");
1971                  break;
1972          case btComplex:
1973          newType = new typeScalar(typeIndex, size, "complex");
1974                  break;
1975          case btBit:
1976          newType = new typeScalar(typeIndex, size, "bit");
1977                  break;
1978          case btBSTR:
1979          newType = new typeScalar(typeIndex, size, "bstr");
1980                  break;
1981          case btHresult:
1982          newType = new typeScalar(typeIndex, size, "Hresult");
1983                  break;
1984          default:
1985                  fprintf(stderr, "Couldn't parse baseType %d for %d\n", baseType, typeIndex);
1986          assert(0);
1987                  break;
1988    }
1989    if (newType)
1990        addTypeToCollection(newType, mod);
1991    return newType;
1992 }
1993
1994 static Type *getType(HANDLE p, Offset base, int typeIndex, Module *mod) 
1995 {
1996    static unsigned depth = 0;
1997    BOOL result;
1998    Type *foundType = NULL;
1999    typeCollection *collection;
2000    enum SymTagEnum symtag;
2001
2002    if (!typeIndex)
2003        return NULL;
2004
2005    //
2006    // Check if this type has already been created (they're indexed by typeIndex).
2007    // If it has, go ahead and return the existing one.
2008    // If not, then start creating a new type.
2009    //
2010    if (mod)
2011        collection = typeCollection::getModTypeCollection(mod);
2012    else
2013            collection = (typeCollection*)Symtab::stdTypes;
2014    assert(collection);
2015
2016
2017    //
2018    // Check to see if we've already parsed this type
2019    //
2020    foundType = collection->findType(typeIndex);
2021    if (foundType) {
2022        return foundType;
2023    }
2024
2025    //
2026    // Types on Windows are stored as part of a special type of symbol.  TI_GET_SYMTAG 
2027    // Gets the meta information about the type.
2028    //
2029    result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &symtag);
2030    if (!result) {
2031        depth--;
2032        return NULL;
2033    }
2034    switch (symtag) {
2035        case SymTagBaseType:
2036            foundType = getBaseType(p, base, typeIndex, mod);
2037            break;
2038        case SymTagEnum:
2039            foundType = getEnumType(p, base, typeIndex, mod);
2040            break;
2041        case SymTagFunctionType:
2042            foundType = getFunctionType(p, base, typeIndex, mod);
2043            break;
2044        case SymTagPointerType:
2045            foundType = getPointerType(p, base, typeIndex, mod);
2046            break;
2047        case SymTagArrayType:
2048            foundType = getArrayType(p, base, typeIndex, mod);
2049            break;
2050        case SymTagTypedef:
2051            foundType = getTypedefType(p, base, typeIndex, mod);
2052            break;
2053        case SymTagUDT:
2054            foundType = getUDTType(p, base, typeIndex, mod);
2055            break;
2056        case SymTagFunctionArgType:
2057        case SymTagData:
2058        case SymTagFunction:
2059        case SymTagBaseClass:
2060            foundType = getLayeredType(p, base, typeIndex, mod);
2061            if (foundType)
2062              typeIndex = foundType->getID();
2063            break;
2064        case SymTagThunk:
2065            foundType = NULL;
2066            break;
2067        case SymTagVTableShape:
2068        case SymTagVTable:
2069            break;
2070        default:
2071            fprintf(stderr, "Unknown type %d\n", symtag);
2072            assert(0);
2073            foundType = NULL;
2074            break;
2075    }
2076
2077    return foundType;
2078 }
2079
2080 typedef struct proc_mod_pair {
2081         HANDLE handle;
2082         Symtab *obj;
2083     Offset base_addr;
2084 } proc_mod_pair;
2085
2086 static void findLocalVars(Function *func, proc_mod_pair base) {
2087     Module *mod = func->getModule();
2088     localsStruct locals;
2089     HANDLE p = base.handle;
2090
2091     locals.func = func;
2092     locals.base = base.base_addr;
2093     locals.p = p;
2094
2095         enumLocalVars(func, &locals);
2096     //
2097     // The windows debugging interface allows us to get local variables
2098     // at specific points, which makes it hard to enumerate all locals (as we want).
2099     // Instead we'll get the local variables at the most common points below.
2100     //
2101     //TODO?
2102         //=const std::vector<instPoint*> &points = ifunc->funcEntries();
2103     //=enumLocalVars(func, ifunc->funcEntries(), &locals);
2104     //=enumLocalVars(func, ifunc->funcExits(), &locals);
2105     //=enumLocalVars(func, ifunc->funcCalls(), &locals);
2106     //=enumLocalVars(func, ifunc->funcArbitraryPoints(), &locals);
2107 }
2108
2109 BOOL CALLBACK add_type_info(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, void *info)
2110 {
2111    HANDLE p;
2112    Offset obj_base;
2113    proc_mod_pair *pair;
2114    Symtab *obj;
2115    Type *type;
2116    char *name;
2117    Address addr;
2118
2119    if (!isGlobalSymbol(pSymInfo)) {
2120        //We do local symbols elsewhere
2121        return TRUE;
2122    }
2123
2124    pair = (proc_mod_pair *) info;
2125    p = pair->handle;
2126    obj_base = pair->base_addr;
2127    obj = pair->obj;
2128    name = pSymInfo->Name;
2129    addr = (Address) pSymInfo->Address - obj_base;
2130
2131    std::vector<Module *> mods;
2132    Module *mod;
2133    //TODO?? change later
2134    if(!obj->getAllModules(mods))
2135    {
2136            return true;
2137    }
2138    else
2139            mod = mods[0];
2140    
2141    if (obj->isExec()) {
2142       //When parsing the a.out, sort the type information into specific modules.  This doesn't matter
2143       // for libraries, because there is a 1:1 mapping between modules and objects.
2144       //
2145       //A module is a collection of functions, but doesn't include global data types.  Global variables
2146       // will go into the DEFAULT_MODULE
2147                 Function *f = NULL;
2148            if(obj->findFuncByEntryOffset(f, (Offset) pSymInfo->Address))
2149            {
2150              //No containing module.  Only insert this into DEFAULT_MODULE
2151           if (strcmp(f->getModule()->fileName().c_str(), "DEFAULT_MODULE"))
2152               return true;
2153       }
2154    }
2155
2156    type = getType(p, obj_base, pSymInfo->TypeIndex, mod);
2157
2158    
2159 //   fprintf(stderr, "[%s:%u] - Variable %s had type %s\n", __FILE__, __LINE__,
2160 //       name, type ? type->getName().c_str() : "{NO TYPE}");
2161    
2162    if (type)
2163    {
2164       Variable *var = NULL;
2165       bool result = obj->findVariableByOffset(var, addr);
2166       if (result) {
2167          var->setType(type);
2168       }
2169       if (name) {
2170          std::string vName = name;
2171                  typeCollection *tc = typeCollection::getModTypeCollection(mod);
2172                  assert(tc);
2173          tc->addGlobalVariable(vName, type);
2174       }
2175    }
2176    return TRUE;
2177 }
2178
2179 void Object::parseTypeInfo(Symtab *obj) {
2180     proc_mod_pair pair;
2181     BOOL result;
2182     //
2183     //Parse global variable type information
2184     //
2185
2186     pair.handle = hProc;
2187     pair.obj = obj;
2188     pair.base_addr = getBaseAddress();
2189     
2190     if (!pair.base_addr) {
2191         pair.base_addr = getLoadAddress();
2192     }
2193   
2194    HANDLE mapAddr = mf->base_addr();
2195     result = SymEnumSymbols(hProc, (DWORD64)mapAddr, NULL, 
2196                             add_type_info, &pair);
2197         if (!result){
2198                 printSysError(GetLastError());
2199 //        parsing_printf("SymEnumSymbols was unsuccessful.  Type info may be incomplete\n");
2200     }
2201
2202     //
2203     // Parse local variables and local type information
2204     //
2205     std::vector<Function *> funcs;
2206         obj->getAllFunctions(funcs);
2207     for (unsigned i=0; i < funcs.size(); i++) {
2208         findLocalVars(funcs[i], pair);
2209     }
2210 }
2211
2212 bool AObject::getSegments(vector<Segment> &segs) const
2213 {
2214         for(unsigned int i=0; i<regions_.size(); i++){
2215                 Segment seg;
2216                 seg.data = regions_[i]->getPtrToRawData();
2217                 //seg.loadaddr = regions_[i] -> getDiskOffset();
2218                 seg.loadaddr = regions_[i] -> getMemOffset();
2219                 seg.size = regions_[i] -> getDiskSize();
2220                 seg.name = regions_[i] -> getRegionName();
2221                 //seg.segFlags = 
2222                 segs.push_back(seg);
2223         }
2224     return true;
2225 }
2226
2227 bool Object::emitDriver(Symtab *obj, string fName, std::vector<Symbol *>&allSymbols, 
2228                                                 unsigned flag) 
2229 {
2230         emitWin *em = new emitWin((PCHAR)GetMapAddr(), this, err_func_);
2231         return em -> driver(obj, fName);
2232 }
2233
2234 // automatically discards duplicates
2235 void Object::addReference(Offset off, std::string lib, std::string fun){
2236    ref[lib][off] = fun;
2237 }
2238                                                 
2239 // retrieve Section Number for an image offset
2240 // dwRO - the image offset to calculate
2241 // returns -1 if an error occurred else returns the corresponding section number
2242 DWORD Object::ImageOffset2SectionNum(DWORD dwRO)
2243 {
2244    PIMAGE_SECTION_HEADER sectionHeader = 
2245       (PIMAGE_SECTION_HEADER)((DWORD)peHdr 
2246                               + sizeof(DWORD) // PE signature
2247                               + sizeof(IMAGE_FILE_HEADER) 
2248                               + peHdr->FileHeader.SizeOfOptionalHeader);
2249         unsigned int SecCount = peHdr ->FileHeader.NumberOfSections;
2250         for(unsigned int i=0;i < SecCount; i++)
2251         {
2252                 if((dwRO>=sectionHeader->PointerToRawData) && (dwRO<(sectionHeader->PointerToRawData+sectionHeader->SizeOfRawData)))
2253                 {
2254                         return (i);
2255                 }
2256                 sectionHeader++;
2257         }
2258         return(-1);
2259 }
2260
2261 PIMAGE_SECTION_HEADER Object::ImageOffset2Section(DWORD dwRO)
2262 {
2263    PIMAGE_SECTION_HEADER sectionHeader = 
2264       (PIMAGE_SECTION_HEADER)((DWORD)peHdr 
2265                               + sizeof(DWORD) // PE signature
2266                               + sizeof(IMAGE_FILE_HEADER) 
2267                               + peHdr->FileHeader.SizeOfOptionalHeader);
2268         unsigned int SecCount = peHdr ->FileHeader.NumberOfSections;
2269
2270         for(unsigned int i=0;i<SecCount;i++)
2271         {
2272                 if((dwRO >= sectionHeader->PointerToRawData) && 
2273            (dwRO < (sectionHeader->PointerToRawData + sectionHeader->SizeOfRawData)))
2274                 {
2275                         return sectionHeader;
2276                 }
2277                 sectionHeader++;
2278         }
2279         return(NULL);
2280 }
2281
2282 PIMAGE_SECTION_HEADER Object::ImageRVA2Section(DWORD dwRVA)
2283 {
2284    PIMAGE_SECTION_HEADER sectionHeader = 
2285       (PIMAGE_SECTION_HEADER)((DWORD)peHdr 
2286                               + sizeof(DWORD) // PE signature
2287                               + sizeof(IMAGE_FILE_HEADER) 
2288                               + peHdr->FileHeader.SizeOfOptionalHeader);
2289         unsigned int SecCount = peHdr ->FileHeader.NumberOfSections;
2290
2291         for(unsigned int i=0;i<SecCount;i++)
2292         {
2293                 if((dwRVA>=sectionHeader->VirtualAddress) && (dwRVA<=(sectionHeader->VirtualAddress+sectionHeader->SizeOfRawData)))
2294                 {
2295                         return sectionHeader;
2296                 }
2297                 sectionHeader++;
2298         }
2299         return(NULL);
2300 }
2301
2302 DWORD Object::RVA2Offset(DWORD dwRVA)
2303 {
2304         DWORD offset;
2305         PIMAGE_SECTION_HEADER section = ImageRVA2Section(dwRVA);
2306         if(section==NULL)
2307         {
2308                 return(0);
2309         }
2310         offset=dwRVA+section->PointerToRawData-section->VirtualAddress;
2311         return offset;
2312 }
2313
2314 DWORD Object::Offset2RVA(DWORD dwRO)
2315 {
2316         PIMAGE_SECTION_HEADER section = ImageOffset2Section(dwRO);
2317         if(section==NULL)
2318         {
2319                 return(0);
2320         }
2321         return(dwRO+section->VirtualAddress-section->PointerToRawData);
2322 }
2323
2324 void Object::setTrapHeader(Offset addr)
2325 {
2326    trapHeaderPtr_ = addr;
2327 }
2328 Offset Object::trapHeader()
2329 {
2330    return trapHeaderPtr_;
2331 }
2332
2333 void Object::insertPrereqLibrary(std::string lib)
2334 {
2335    // must include some function from the library for Windows to load it
2336    ref[lib] = std::map<Offset, std::string>();
2337 }
2338
2339  bool Region::isStandardCode()
2340 {
2341    return (getRegionPermissions() == RP_RX ||
2342            getRegionPermissions() == RP_RWX);
2343 }
2344
2345 Dyninst::Architecture Object::getArch()
2346 {
2347    return Dyninst::Arch_x86;
2348 }
2349
2350 /*
2351         for(it=ref.begin(); it!=ref.end(); it++){
2352                 IMAGE_IMPORT_DESCRIPTOR newID;
2353                 newID.ForwarderChain=0;
2354                 newID.TimeDateStamp=0;
2355                 newID.OriginalFirstThunk = 0;
2356                 newID.FirstThunk = (*it).first;
2357                 //printf("IAT address: %x\n", newID.FirstThunk);
2358
2359                 //look through the old import table to check if the library has been there
2360                 bool isExisting = false;
2361                 for(unsigned int i=0; i<oldImp.size(); i++){
2362
2363                         //if already been there, use the same of RVA of name
2364                         if(strcmp(oldImp[i].name, (*it).second.first.c_str()) == 0){
2365                                 isExisting = true;
2366                                 newID.Name = oldImp[i].id.Name;
2367                                 break;
2368                         }
2369                 }       
2370
2371                 char* ptrLib;
2372                 unsigned long strLen;
2373                 //otherwise, it's a new library
2374                 if(!isExisting){
2375                         newID.Name = strOff;
2376                         strLen =(*it).second.first.size();
2377                         //library name must be '\0' terminated, so len plus one
2378                         ptrLib = (char*) GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, strLen+1);
2379                         memcpy(ptrLib,(*it).second.first.c_str(), strLen);
2380                         info.push_back(std::pair<char*,unsigned long> (ptrLib, strLen+1));
2381                         strOff+=(strLen+1);
2382                 }
2383
2384                 memcpy(newIT+pos*sizeof(IMAGE_IMPORT_DESCRIPTOR),(char*)&newID, sizeof(IMAGE_IMPORT_DESCRIPTOR));
2385
2386                 //write the pointer to function name into (*it).first
2387                 Offset o = (Offset)((char*)dynSec->getPtrToRawData())+(*it).first-dynSec->getMemOffset();
2388                 printf("Offset to write the pointer to function name: %x\n", o);
2389                 memcpy(((char*)dynSec->getPtrToRawData())+(*it).first-dynSec->getMemOffset(), (char*)&strOff, 4);
2390                 strLen = (*it).second.second.size();
2391         
2392                 //functin name must start with a two byte hint
2393                 //function name also '0\' terminated
2394                 ptrLib = (char*)GlobalAlloc(GMEM_FIXED|GMEM_ZEROINIT, 2+strLen+1);
2395                 memcpy(ptrLib+2, (*it).second.second.c_str(), strLen);
2396                 info.push_back(std::pair<char*, unsigned long> (ptrLib, strLen+3));
2397                 strOff+=(2+strLen+1);
2398
2399                 pos++;
2400         }
2401 */
2402
2403 DWORD* Object::get_dword_ptr(Offset rva)
2404 {
2405         Offset off = RVA2Offset(rva);
2406         int sectionNum = ImageOffset2SectionNum(off);
2407         Region* r = regions_[sectionNum];
2408         char* region_buf = (char*)(r->getPtrToRawData());
2409         return (DWORD*)(region_buf + (off - r->getDiskOffset()));
2410 }
2411
2412 Region* Object::findRegionByName(const std::string& name) const
2413 {
2414         for(auto reg = regions_.begin();
2415                 reg != regions_.end();
2416                 ++reg)
2417         {
2418                 if((*reg)->getRegionName() == name)
2419                 {
2420                         return *reg;
2421                 }
2422         }
2423         return NULL;
2424 }
2425 void Object::applyRelocs(Region* relocs, Offset delta)
2426 {
2427         unsigned char* section_pointer = (unsigned char*)relocs->getPtrToRawData();
2428         unsigned char* section_end = section_pointer+relocs->getMemSize();
2429         while(section_pointer < section_end)
2430         {
2431                 PIMAGE_BASE_RELOCATION curRelocPage = (PIMAGE_BASE_RELOCATION)(section_pointer);
2432                 section_pointer += sizeof(IMAGE_BASE_RELOCATION);
2433                 Offset pageBase = curRelocPage->VirtualAddress;
2434                 if(pageBase == 0) break;
2435                 int numRelocs = (curRelocPage->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(WORD);
2436                 for(int i = 0; i < numRelocs; ++i)
2437                 {
2438                         WORD curReloc = *(WORD*)(section_pointer);
2439                         section_pointer += sizeof(WORD);
2440                         Offset addr = (curReloc & 0x0FFF) + pageBase;
2441                         WORD type = curReloc >> 12;
2442                         switch(type)
2443                         {
2444                         case IMAGE_REL_BASED_ABSOLUTE:
2445                                 // These are placeholders only
2446                                 break;
2447                         case IMAGE_REL_BASED_HIGHLOW:
2448                                 {
2449                                         // These should be the only things we deal with on Win32; revisit when we hit 64-bit windows
2450                                         DWORD* loc_to_fix = get_dword_ptr(addr);
2451                                         *(loc_to_fix) += delta;
2452                                 }
2453                                 break;
2454                         default:
2455                                 fprintf(stderr, "Unknown relocation type 0x%x for addr %p\n", type, addr);
2456                                 break;
2457                         }
2458                 }
2459         }
2460 }
2461 void Object::rebase(Offset off)
2462 {
2463         if(off == imageBase) return;
2464         Region* relocs = findRegionByName(".reloc");
2465         if(!relocs) {
2466                 fprintf(stderr, "rebase found no .reloc section, bailing\n");
2467                 return;
2468         }
2469         Offset delta = off - imageBase;
2470         applyRelocs(relocs, delta);
2471         imageBase = off;
2472 }