Update copyright to LGPL on all files
[dyninst.git] / symtabAPI / src / Object-nt.C
1 /*
2  * Copyright (c) 1996-2009 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as "Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31                              
32 #define WIN32_LEAN_AND_MEAN
33
34 #include <windows.h>
35 #include <cvconst.h>
36 #include <oleauto.h>
37 #if !defined __out_ecount_opt
38 #define __out_ecount_opt(x)
39 #endif
40 #include <dbghelp.h>
41
42 #include <iostream>
43 #include <iomanip>
44 #include <limits.h>
45 #include <crtdbg.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/h/headers.h"
59
60 using namespace Dyninst;
61 using namespace Dyninst::SymtabAPI;
62
63 Type *getType(HANDLE p, Offset mod_base, int typeIndex, Module *mod = NULL);
64 bool pd_debug_export_symbols = false;
65 using namespace std;
66
67 std::string convertCharToString(const char *ptr){
68     std::string str;
69     if(ptr)
70         str = ptr;
71     else
72         str = "";
73     return str;
74 }
75
76 static void printSysError(unsigned errNo) {
77     char buf[1000];
78         
79         int result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNo,
80                                                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
81                                                                 buf, 1000, NULL);
82     if (!result) {
83         fprintf(stderr, "Couldn't print error message\n");
84                 printSysError(GetLastError());
85     }
86     fprintf(stderr, "*** System error [%d]: %s\n", errNo, buf);
87     fflush(stderr);
88 }
89
90 //---------------------------------------------------------------------------
91 // prototypes of functions used in this file
92 //---------------------------------------------------------------------------
93 BOOL CALLBACK SymEnumSymbolsCallback( PSYMBOL_INFO pSymInfo,
94                                                                                 ULONG symSize,
95                                                                                 PVOID userContext );
96 /*
97  * stripAtSuffix 
98  *
99  * Strips off of a string any suffix that consists of an @ sign followed by
100  * decimal digits.
101  *
102  * str  The string to strip the suffix from.  The string is altered in place.
103  */
104  static void stripAtSuffix(char *str)
105  {
106     // many symbols have a name like foo@4, we must remove the @4
107     // just searching for an @ is not enough,
108     // as it may occur on other positions. We search for the last one
109     // and check that it is followed only by digits.
110     char *p = strrchr(str, '@');
111     if (p) {
112       char *q = p+1;
113       strtoul(p+1, &q, 10);
114       if (q > p+1 && *q == '\0') {
115                 *p = '\0';
116       }
117     }
118 }
119
120 char *cplus_demangle(char *c, int, bool includeTypes) { 
121     
122     char buf[1000];
123     if (c[0]=='_') {
124         // VC++ 5.0 seems to decorate C symbols differently to C++ symbols
125         // and the UnDecorateSymbolName() function provided by imagehlp.lib
126         // doesn't manage (or want) to undecorate them, so it has to be done
127         // manually, removing a leading underscore from functions & variables
128         // and the trailing "$stuff" from variables (actually "$Sstuff")
129         unsigned i;
130         for (i=1; i<sizeof(buf) && c[i]!='$' && c[i]!='\0'; i++)
131             buf[i-1]=c[i];
132         buf[i-1]='\0';
133         stripAtSuffix(buf);
134         if (buf[0] == '\0') 
135                 return 0; // avoid null names which seem to annoy Paradyn
136         return P_strdup(buf);
137     }
138     else {
139        if (includeTypes) {
140           if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE| UNDNAME_NO_ACCESS_SPECIFIERS|UNDNAME_NO_MEMBER_TYPE|UNDNAME_NO_MS_KEYWORDS)) {
141             //   printf("Undecorate with types: %s = %s\n", c, buf);
142             stripAtSuffix(buf);
143             return P_strdup(buf);
144           }
145        }
146        else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_NAME_ONLY)) {
147          //else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE|UNDNAME_32_BIT_DECODE)) {
148          //printf("Undecorate: %s = %s\n", c, buf);
149          stripAtSuffix(buf);          
150          return P_strdup(buf);
151        }
152     }
153     return 0;
154 }
155
156 //---------------------------------------------------------------------------
157 // Object method implementation
158 //---------------------------------------------------------------------------
159 struct  CompareSymAddresses: public binary_function<const Object::intSymbol*, const Object::intSymbol*, bool> 
160 {
161         bool operator()(const Object::intSymbol *s1, const Object::intSymbol* s2) {
162                 bool ret = false;
163                 // first try comparing by address
164                 if( s1->GetAddr() < s2->GetAddr() ) 
165                 {
166                         ret = true;
167                 }
168                 else if( s1->GetAddr() > s2->GetAddr() )
169                 {
170                         ret = false;
171                 }
172                 else
173                 {
174                         // the two symbols have the same address
175                         // use our next criteria (the existence of a size)
176                         // for a given address, we want symbols with a size
177                         // to occur before those without so that we can
178                         // use the size if we wish
179                         if( (s1->GetSize() != 0) && (s2->GetSize() == 0) )
180                         {
181                                 ret = true;
182                         }
183                         else if( (s1->GetSize() == 0) && (s2->GetSize() != 0) )
184                         {
185                                 ret = false;
186                         }
187                 }
188                 return ret;
189         }
190 };
191
192 Object::Module::Module( std::string _name, DWORD64 _baseAddr, DWORD64 _extent )  :
193                                                 name(_name),
194                                                 baseAddr(_baseAddr),
195                                                 extent(_extent),
196                                                 isDll( false )
197 {
198         defFile = new Object::File();
199         files.push_back( defFile );
200 }
201
202 Object::File*
203 Object::Module::FindFile( std::string name )
204 {
205         File* ret = NULL;
206         for( std::vector<File *>::iterator iter = files.begin();
207                         iter != files.end();
208                         iter++ )
209         {
210                 if( (*iter)->GetName() == name )
211                 {
212                         ret = *iter;
213                         break;
214                 }
215         }
216         return ret;
217 }
218
219 void
220 Object::File::DefineSymbols( dyn_hash_map<std::string, std::vector< Symbol *> >& allSyms,
221                              map<Symbol *, std::string> &symsToMods,
222                              const std::string& modName ) const
223 {
224     for( std::vector<Object::intSymbol*>::const_iterator iter = syms.begin(); iter != syms.end(); iter++ ) {
225         const Object::intSymbol* curSym = * iter;
226         assert( curSym != NULL );
227         curSym->DefineSymbol( allSyms, symsToMods, modName );
228     }
229 }
230
231 void
232 Object::intSymbol::DefineSymbol(dyn_hash_map<std::string,std::vector<Symbol *> >&allSyms,
233                                 map<Symbol *, std::string> &symsToMods,
234                                 const std::string& modName ) const
235 {
236     Symbol *sym = new Symbol(GetName(), 
237                              (Symbol::SymbolType) GetType(),
238                              (Symbol::SymbolLinkage) GetLinkage(),
239                              Symbol::SV_UNKNOWN,
240                              (Offset)GetAddr(),
241                              NULL,
242                              GetRegion(),
243                              GetSize());
244     allSyms[GetName()].push_back(sym);
245     symsToMods[sym] = modName;
246 }
247
248 void
249 Object::Module::DefineSymbols( const Object* obj,
250                                dyn_hash_map<std::string, std::vector< Symbol *> > & syms,
251                                map<Symbol *, std::string> &symsToMods ) const
252 {
253     // define Paradyn/dyninst modules and symbols
254     if( !isDll )
255         {
256         // this is an EXE
257         for( std::vector<Object::File*>::const_iterator iter = files.begin();
258                 iter != files.end();
259              iter++ ) {
260             const File* curFile = *iter;
261             assert( curFile != NULL );
262             
263             //fprintf(stderr, "ObjMod::DefineSymbols for %s\n", curFile->GetName().c_str());
264             // add a Symbol for the file
265             Symbol *sym = new Symbol( curFile->GetName(), 
266                                       Symbol::ST_MODULE,
267                                       Symbol::SL_GLOBAL,
268                                       Symbol::SV_UNKNOWN,
269                                       obj->code_off(),  // TODO use real base of symbols for file
270                                       NULL,
271                                       NULL, 0 );        // TODO Pass Section pointer also
272             // TODO also pass size
273             // add symbols for each of the file's symbols
274             syms[curFile->GetName()].push_back(sym);
275             symsToMods[sym] = curFile->GetName();
276
277             curFile->DefineSymbols( syms, symsToMods, curFile->GetName() );
278         }
279     }
280     else
281     {
282         // we represent a DLL
283         // add one Symbol for the entire module
284
285         Symbol *sym = new Symbol(name,
286                                  Symbol::ST_MODULE,
287                                  Symbol::SL_GLOBAL,
288                                  Symbol::SV_UNKNOWN,
289                                  obj->code_off(),
290                                  NULL,
291                                  NULL,                                  //TODO pass Sections pointer
292                                  obj->code_len());
293     
294         syms[name].push_back(sym); 
295         symsToMods[sym] = name;
296
297         // add symbols for each of the module's symbols
298         for( std::vector<Object::File*>::const_iterator iter = files.begin();
299                 iter != files.end();
300                 iter++ )
301         {
302             const File* curFile = *iter;
303             assert( curFile != NULL );
304             // add symbols for each of the file's symbols
305             curFile->DefineSymbols( syms, symsToMods, name );
306         }
307     }
308 }
309
310 void
311 Object::Module::PatchSymbolSizes( const Object* obj,
312                                                                   const std::vector<Object::intSymbol*>& allSyms ) const
313 {
314         DWORD64 lastFuncAddr = NULL;
315         unsigned int i;
316         
317         for( i = 0; i < allSyms.size(); i++ )
318     {
319                 Object::intSymbol* sym = allSyms[i];
320                 assert( sym != NULL );
321                 if( (sym->GetName() != "") && (sym->GetSize() == 0) &&
322             ((sym->GetType() == Symbol::ST_FUNCTION) ||
323              (sym->GetType() == Symbol::ST_OBJECT)))
324         {
325             // check for function aliases
326             // note that this check depends on the allSymbols
327             // array being sorted so that aliases are considered
328             // after the "real" function symbol
329             bool isAlias = false;
330             if( (sym->GetType() == Symbol::ST_FUNCTION) &&
331                 (sym->GetAddr() == lastFuncAddr) &&
332                 (sym->GetSize() == 0) )
333             {
334                 // this function is an alias
335                                 // we currently leave their size as zero to indicate 
336                                 // that they are uninstrumentable.  Ideally, this will
337                                 // change once a mechanism becomes available to identify
338                                 // these as function aliases.
339                                 isAlias = true;
340                         }
341             if( !isAlias )
342                         {
343                                 //
344                                 // patch the symbol's size
345                                 //
346                                 // We consider the symbol's size to be the distance
347                                 // to the next symbol.  (Sometimes this causes us to
348                                 // overestimate, because compilers sometimes leave some
349                                 // "padding" between the end of a function and the beginning
350                                 // of the next.)
351                                 //
352                                 // Note that we have to use the next symbol whose
353                                 // address is different from the current one, to handle
354                                 // cases where aliases are included in the symbol table
355                 //
356                 DWORD64 cb;
357                 
358                                 //
359                                 // find next function or object symbol in our section with
360                                 // an address different from ours
361                                 //
362                                 // the while test looks complicated -
363                                 // all we're trying to do is skip to the next
364                                 // function or object symbol within the array whose
365                                 // address is not the same as allSymbols[i].
366                                 unsigned int j = i + 1;
367                                 while((j < allSyms.size()) &&
368                                 (((allSyms[j]->GetType() != Symbol::ST_FUNCTION) &&
369                                                                 (allSyms[j]->GetType() != Symbol::ST_OBJECT)) ||
370                                                                 (allSyms[j]->GetAddr() == sym->GetAddr())))
371                                 {
372                                         j++;
373                                 }
374                                 if( j < allSyms.size() &&
375                                         (allSyms[j]->GetType() == sym->GetType()) )
376                                 {
377                                         // we found a symbol from the same section
378                                         // with a different address -
379                                         // size is just the delta between symbols
380                                         cb = allSyms[j]->GetAddr() - sym->GetAddr();
381                                 }
382                                 else
383                                 {
384                                         // we couldn't find another symbol in our section
385                                         // with a different address -
386                                         // size is the remainder of the current section
387                                         if( sym->GetType() == Symbol::ST_FUNCTION )
388                                         {
389                                                 // size is remainder of the .text section
390                                                 cb = (obj->code_off() + obj->code_len()) - 
391                                                         sym->GetAddr();
392                                         }
393                                         else
394                                         {
395                                                 // size is remainder of the .data section
396                                                 cb = (obj->data_off() + obj->data_len()) - 
397                                                         sym->GetAddr();
398                                         }
399                                 }
400                                 sym->SetSize( (unsigned int) cb );
401                         }
402                         // update the last known function symbol
403                         if( sym->GetType() == Symbol::ST_FUNCTION )
404                         {
405                                 lastFuncAddr = sym->GetAddr();
406                         }
407                 }
408     }
409 }
410
411 void
412 Object::Module::BuildSymbolMap( const Object* obj ) const
413 {
414         std::vector<Object::intSymbol*> allSyms;
415         // add all symbols to our allSyms std::vector
416         std::vector<Object::File*>::const_iterator iter = files.begin();
417         for(;   iter != files.end();    iter++ )
418         {
419                 assert( *iter != NULL );
420                 const std::vector<Object::intSymbol*>& curSyms = (*iter)->GetSymbols();
421                 for( std::vector<Object::intSymbol*>::const_iterator symIter = curSyms.begin(); symIter != curSyms.end();symIter++ )
422                 {
423                         assert( *symIter != NULL );
424                         allSyms.push_back( *symIter );
425                 }
426         }
427         // sort the symbols by address
428         sort( allSyms.begin(), allSyms.end(), CompareSymAddresses());
429         for( unsigned int i = 1; i < allSyms.size(); i++ )
430         {
431                 if( allSyms[i-1]->GetAddr() > allSyms[i]->GetAddr() )
432                 {
433                         cout << "WARNING - sort failed" << endl;
434                         assert( false );
435                 }
436         }
437         // patch up any symbol sizes which weren't given to us
438         PatchSymbolSizes( obj, allSyms );
439 }
440
441 Object::~Object( void )
442 {
443 }
444
445 #define SymTagFunction 0x5
446 #define SymTagData 0x7
447 #define SymTagPublicSymbol 0xa
448 #define SymTagMisc 0x3808               // Seen with NB11, VC++6-produced executables
449 //
450 // Our recognition of interesting symbols (functions and global data)
451 // is complicated due to lack of consistency in how they are
452 // presented to us in the pSymInfo struct.  For example,
453 // Microsoft's own system DLLs like kernel32.dll only seem to provide
454 // us their exports - these have the SYMFLAG_EXPORT bit set in
455 // pSymInfo->Flags.  In contrast, EXEs with full debug information
456 // may have pSymInfo->Flags == 0, with pSymInfo->Tag indicating the
457 // type of symbol.
458 //
459 static BOOL isGlobalSymbol(PSYMBOL_INFO pSymInfo) {
460  return ((pSymInfo->Flags & SYMFLAG_EXPORT) ||
461          (pSymInfo->Flags & SYMFLAG_FUNCTION) ||
462          ((!pSymInfo->Flags) && 
463           ((pSymInfo->Tag == SymTagFunction) ||
464            (pSymInfo->Tag == SymTagData) ||
465            (pSymInfo->Tag == SymTagPublicSymbol) ||
466            (pSymInfo->Tag == SymTagMisc))) );
467 }
468
469 void Object::ParseGlobalSymbol(PSYMBOL_INFO pSymInfo)
470 {
471         Object::Module* curMod = GetCurrentModule();
472         assert( curMod != NULL );
473         
474         IMAGEHLP_LINE64 lineInfo;
475         DWORD dwDisplacement = 0;
476         ZeroMemory( &lineInfo, sizeof(lineInfo) );
477         lineInfo.SizeOfStruct = sizeof(lineInfo);
478         Object::File* pFile = NULL;
479         if( SymGetLineFromAddr64( hProc,
480                                                                 pSymInfo->Address,
481                                                                 &dwDisplacement,
482                                                                 &lineInfo ) ) {
483                 // ensure we have a file for this object
484                 pFile = curMod->FindFile( lineInfo.FileName );
485                 if( pFile == NULL ) {
486                         pFile = new Object::File( lineInfo.FileName );
487                         curMod->AddFile( pFile );
488                 }
489         }
490         else {
491                 pFile = curMod->GetDefaultFile();
492         }
493         assert( pFile != NULL );
494         // is it a function or not?
495         // TODO why is there a discrepancy between code base addr for
496         // EXEs and DLLs?
497         DWORD symType = Symbol::ST_UNKNOWN;
498         DWORD symLinkage = Symbol::SL_UNKNOWN;
499         DWORD64 codeLen = code_len();
500         DWORD64 codeBase = code_off();
501         symType = Symbol::ST_FUNCTION;
502         //codeBase += get_base_addr();
503         if ((pSymInfo->Flags & SYMFLAG_FUNCTION) ||
504                 (pSymInfo->Tag == SymTagFunction && !pSymInfo->Flags))
505         {
506                 symLinkage = Symbol::SL_UNKNOWN;
507         }
508         else if ((pSymInfo->Flags == SYMFLAG_EXPORT && 
509             isText((Offset) pSymInfo->Address - (Offset)mf->base_addr())) ||
510             !strcmp(pSymInfo->Name, "_loadsnstores"))
511         {
512                 symType = Symbol::ST_FUNCTION;
513                 symLinkage = Symbol::SL_UNKNOWN;
514         }
515         else
516         {
517                 symType = Symbol::ST_OBJECT;
518                 symLinkage = Symbol::SL_GLOBAL;
519         }
520     // register the symbol
521     Offset baseAddr = 0;
522     //  if (desc.isSharedObject())
523     //if(curModule->IsDll())
524     //   baseAddr = get_base_addr();
525     if( !isForwarded( ((Offset) pSymInfo->Address) - baseAddr ) )
526     {
527         pFile->AddSymbol( new Object::intSymbol
528                           ( pSymInfo->Name,
529                             pSymInfo->Address - get_base_addr(),
530                             symType,
531                             symLinkage,
532                             pSymInfo->Size,
533                             findEnclosingRegion((Offset)(pSymInfo->Address - get_base_addr())) ));
534     } 
535 }
536    
537 BOOL CALLBACK SymEnumSymbolsCallback( PSYMBOL_INFO pSymInfo,
538                                                                                 ULONG symSize,
539                                                                                 PVOID userContext )
540 {
541         assert( pSymInfo != NULL );
542         Object* obj = (Object*) userContext;
543         assert( obj != NULL );
544
545 #if 0
546         fprintf(stderr, "symEnumSymsCallback, %s, Flags:0x%x, Tag:0x%x, Type:%d, Addr:0x%x...\n",
547                    pSymInfo->Name,
548            pSymInfo->Flags,
549            pSymInfo->Tag,
550            pSymInfo->TypeIndex,
551            pSymInfo->Address);
552 #endif
553
554    if (isGlobalSymbol(pSymInfo))
555    {
556       obj->ParseGlobalSymbol(pSymInfo);
557    }
558    else if ((pSymInfo->Flags & SYMFLAG_LOCAL) ||
559             (pSymInfo->Flags & SYMFLAG_PARAMETER)) {
560       //parsing_printf("Is a local variable\n");
561       //obj->ParseLocalSymbol(pSymInfo);
562    }
563    else {
564       //parsing_printf(" skipping\n");
565    }
566    // keep enumerating symbols
567    return TRUE;
568 }
569
570 /*
571  * This function finds all the global symbols
572  * in a module and all of the source files. (i.e. so this function would find
573  * the 'main' symbol and find the starting point of 'foo.c'
574  *
575  */
576 void Object::ParseSymbolInfo( bool alloc_syms )
577 {
578    // build a Module object for the current module (EXE or DLL)
579    // Note that the CurrentModuleScoper object ensures that the
580    // curModule member will be reset when we leave the scope of
581    // this function.
582    // curModule = new Object::Module( file_, desc.code() );
583    string file_ = mf->filename();
584    static unsigned count = 1;
585    hProc = (HANDLE) count++;
586    if(!SymInitialize(hProc, NULL, false)){
587       DWORD dwErr = GetLastError();
588       if(dwErr) {
589          fprintf( stderr, "SymInitialize failed for %s\n",
590                ((file_.length() > 0) ? file_.c_str() 
591                 : "<no name available>"));
592          goto done;
593       }
594    }
595    assert( hProc != NULL );
596    assert( hProc != INVALID_HANDLE_VALUE );
597
598    // grab load address
599    if (peHdr) imageBase = peHdr->OptionalHeader.ImageBase;
600    else imageBase = 0; 
601
602    // load symbols for this module
603    //DWORD64 dw64BaseAddr = (DWORD64)desc.loadAddr();
604    HANDLE mapAddr = mf->base_addr();
605    DWORD64 dw64BaseAddr = (DWORD64)mapAddr;
606    //load address is always same(fake address space)
607    HANDLE hFile = mf->getFileHandle();
608    DWORD64 loadRet = SymLoadModule64( hProc,                    // proc handle
609          hFile,         // file handle
610          NULL,          // image name
611          NULL,          // shortcut name
612          dw64BaseAddr,  // load address
613          0 );           // size of DLL    
614    if(!loadRet) {
615       DWORD dwErr = GetLastError();
616       if(dwErr) {
617          string file_ = mf->filename();
618          fprintf( stderr, "SymLoadModule64 failed for %s\n",
619                ((file_.length() > 0) ? file_.c_str() 
620                 : "<no name available>"));
621          //printSysError(dwErr);
622          goto done;
623       }
624    }
625    // parse symbols for the module
626    if( !SymEnumSymbols(hProc,                      // process handle
627             dw64BaseAddr,                   // load address
628             "",                 // symbol mask (we use none)
629             SymEnumSymbolsCallback, // called for each symbol
630             this ) )            // client data
631    {
632       int lasterr = GetLastError();
633       fprintf( stderr, "Failed to enumerate symbols\n");
634       //printSysError(lasterr);
635    }
636
637    // We have a module object, with one or more files,
638    // each with one or more symbols.  However, the symbols
639    // are not necessarily in order, nor do they necessarily have valid sizes.
640    assert( curModule != NULL );
641    curModule->BuildSymbolMap( this );
642    if (alloc_syms)
643       curModule->DefineSymbols( this, symbols_, symsToModules_ );
644    no_of_symbols_ = symbols_.size();
645
646    //fprintf(stderr, "%s[%d]:  removed call to parseFileLineInfo here\n", FILE__, __LINE__);
647
648    // Since PE-COFF is very similar to COFF (in that it's not like ELF),
649    // the .text and .data sections are perfectly mapped to code/data segments
650    code_vldS_ = code_off_;
651    code_vldE_ = code_off_ + code_len_;
652    data_vldS_ = data_off_;
653    data_vldE_ = data_off_ + data_len_;
654
655 done:
656    delete curModule;
657 }
658
659 Region::perm_t getRegionPerms(DWORD flags){
660     if((flags & IMAGE_SCN_MEM_EXECUTE) && (flags & IMAGE_SCN_MEM_WRITE))
661         return Region::RP_RWX;
662     else if(flags & IMAGE_SCN_MEM_EXECUTE)
663         return Region::RP_RX;
664     else if(flags & IMAGE_SCN_MEM_WRITE)
665         return Region::RP_RW;
666     else
667         return Region::RP_R;
668 }
669
670 Region::RegionType getRegionType(DWORD flags){
671     if((flags & IMAGE_SCN_CNT_CODE) && (flags & IMAGE_SCN_CNT_INITIALIZED_DATA))
672         return Region::RT_TEXTDATA;
673     else if(flags & IMAGE_SCN_CNT_CODE)
674         return Region::RT_TEXT;
675     else if((flags & IMAGE_SCN_CNT_INITIALIZED_DATA) || (flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA))
676         return Region::RT_DATA;
677     else
678         return Region::RT_OTHER;
679 }
680
681 void Object::FindInterestingSections(bool alloc_syms)
682 {
683    // now that we have the file mapped, look for 
684    // the .text and .data sections
685    assert( peHdr == NULL );
686    HANDLE mapAddr = mf->base_addr();
687    peHdr = ImageNtHeader( mapAddr );
688
689    if (peHdr == NULL) {
690       code_ptr_ = (char*)mapAddr;
691       code_off_ = 0;
692       HANDLE hFile = mf->getFileHandle();
693       code_len_ = (Offset) GetFileSize(hFile, NULL);
694       is_aout_ = false;
695       fprintf(stderr,"Adding Symtab object with no program header, will " 
696               "designate it as code\n");
697       if (alloc_syms)
698           regions_.push_back(new Region(0, ".text", code_off_, code_len_, code_off_, code_len_, 0, Region::RP_RX, Region::RT_TEXT));
699       return;
700    }
701
702    assert( peHdr->FileHeader.SizeOfOptionalHeader > 0 ); 
703
704    string file_ = mf->filename();
705    curModule = new Object::Module( file_, 0 );
706    assert( curModule != NULL );
707
708    curModule->SetIsDll( (peHdr->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0 );
709    if(curModule->IsDll())
710       is_aout_ = false;
711    else
712       is_aout_ = true;
713
714    SecAlignment = peHdr ->OptionalHeader.SectionAlignment;
715    unsigned int nSections = peHdr->FileHeader.NumberOfSections;
716    no_of_sections_ = nSections;
717    PIMAGE_SECTION_HEADER pScnHdr = (PIMAGE_SECTION_HEADER)(((char*)peHdr) + 
718                                  sizeof(DWORD) + sizeof(IMAGE_FILE_HEADER) +
719                                  peHdr->FileHeader.SizeOfOptionalHeader);
720    bool foundText = false;
721    for( unsigned int i = 0; i < nSections; i++ ) {
722       // rawDataPtr should be set to be zero if the amount of raw data
723       // for the section is zero
724       void *rawDataPtr = 0;
725       if (pScnHdr->SizeOfRawData != 0) {
726          rawDataPtr = (void*)((unsigned int)pScnHdr->PointerToRawData +
727                               (unsigned int)mapAddr);
728       }
729       unsigned long secSize = (pScnHdr->Misc.VirtualSize >= pScnHdr->SizeOfRawData) ? 
730           pScnHdr->Misc.VirtualSize : pScnHdr->SizeOfRawData ;
731       if (alloc_syms)
732           regions_.push_back(new Region(i, (const char *)pScnHdr->Name, 
733                                         pScnHdr->Misc.PhysicalAddress, pScnHdr->SizeOfRawData,
734                                         pScnHdr->VirtualAddress, secSize,
735                                         (char *)rawDataPtr, getRegionPerms(pScnHdr->Characteristics),
736                                         getRegionType(pScnHdr->Characteristics)));
737 //        regions_.push_back(new Section(i, (const char*)pScnHdr->Name, 
738 //                                      pScnHdr->VirtualAddress, 
739 //                                      pScnHdr->Misc.VirtualSize, 
740 //                                      rawDataPtr));
741
742       if( strncmp( (const char*)pScnHdr->Name, ".text", 8 ) == 0 ) {
743          // note that section numbers are one-based
744          textSectionId = i + 1;
745          code_ptr_    = (char*)(((char*)mapAddr) +
746                                 pScnHdr->PointerToRawData);
747          code_off_    = pScnHdr->VirtualAddress;
748
749          // Since we're reporting the size of sections on the disk,
750          // we need to check whether the size of raw data is smaller.
751          //code_len_    = pScnHdr->Misc.VirtualSize;
752          code_len_ = ((pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize) ?
753                       pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize);
754          foundText = true;
755       }
756       else if( strncmp( (const char*)pScnHdr->Name, ".data", 8 ) == 0 ) {
757          // note that section numbers are one-based
758          dataSectionId = i + 1;
759          data_ptr_    = (char *)(((char*)mapAddr) +
760                                  pScnHdr->PointerToRawData);
761          data_off_    = pScnHdr->VirtualAddress;
762          data_len_ = (pScnHdr->SizeOfRawData < pScnHdr->Misc.VirtualSize ?
763                       pScnHdr->SizeOfRawData : pScnHdr->Misc.VirtualSize);
764       }
765       pScnHdr += 1;
766    }
767 }
768
769 // Assumes region list is sorted and regions don't overlap
770 Region *Object::findEnclosingRegion(const Offset where)
771 {
772     // search for "where" in regions (regions must not overlap)
773     int first = 0; 
774     int last = regions_.size() - 1;
775     while (last >= first) {
776         Region *curreg = regions_[(first + last) / 2];
777         if (where >= curreg->getRegionAddr()
778             && where < (curreg->getRegionAddr()
779                         + curreg->getRegionSize())) {
780             return curreg;
781         }
782         else if (where < curreg->getRegionAddr()) {
783             last = ((first + last) / 2) - 1;
784         }
785         else {/* where >= (cursec->getSecAddr()
786                            + cursec->getSecSize()) */
787             first = ((first + last) / 2) + 1;
788         }
789     }
790     return NULL;
791 }
792
793 bool Object::isForwarded( Offset addr )
794 {
795         //calls to forwarded symbols are routed to another dll and 
796     //are not in the current dll's code space
797         //we MUST NOT try to parse these - bad things happen
798         
799         //we detect forwarded symbols by checking if the relative 
800         //virtual address of the symbol falls within the dll's exports section
801         if(peHdr && peHdr->FileHeader.Characteristics & IMAGE_FILE_DLL )
802         {
803                 PIMAGE_DATA_DIRECTORY dataDir = peHdr->OptionalHeader.DataDirectory;
804                 Offset exportStart = dataDir->VirtualAddress;
805                 Offset exportEnd = exportStart + dataDir->Size;
806                 if( addr >= exportStart && addr < exportEnd )
807                         return true;  //this sym is forwarded
808         }
809         return false;
810 }
811
812 bool Object::getCatchBlock(ExceptionBlock &b, Offset addr, 
813                            unsigned size) const 
814
815    return false; 
816 }
817
818 bool Object::isText( const Offset addr ) const 
819 {
820    return( addr >= code_off_ && addr <= code_len_ );
821 }
822
823 void fixup_filename(std::string &filename)
824 {
825         if (strcmp(filename.c_str(), "ntdll.dll") == 0)
826                 filename = "c:\\windows\\system32\\ntdll.dll";
827
828         if (filename.substr(0,22) == "\\Device\\HarddiskVolume") {
829                 TCHAR volumePath[1024];
830                 if (GetVolumePathName(filename.c_str(), volumePath, 1024)) {
831                         std::string::size_type filePathIndex = filename.find_first_of("\\/", 22);
832                         if (filePathIndex != std::string::npos)
833                                 filename = volumePath + filename.substr(++filePathIndex);
834                         else
835                                 filename = volumePath + filename.substr(23);
836                 } else {
837                         filename = "c:"+filename.substr(23);
838                 }
839         }
840 }
841
842 Object::Object(MappedFile *mf_,
843                MappedFile *mfd,
844                void (*err_func)(const char *), bool alloc_syms) :
845     AObject(mf_, mfd, err_func),
846     curModule( NULL ),
847     peHdr( NULL )
848 {
849    FindInterestingSections(alloc_syms);
850    ParseSymbolInfo(alloc_syms);
851 }
852
853 SYMTAB_EXPORT ObjectType Object::objType() const 
854 {
855         return is_aout() ? obj_Executable : obj_SharedLib;
856 }
857
858
859 void Object::getModuleLanguageInfo(dyn_hash_map<std::string, supportedLanguages> *mod_langs)
860 {
861         return;
862 }
863
864 static SRCCODEINFO *last_srcinfo;
865 BOOL CALLBACK add_line_info(SRCCODEINFO *srcinfo, void *param)
866 {
867    dyn_hash_map< std::string, LineInformation> *lineInfo = (dyn_hash_map< std::string, LineInformation> *)param;
868    
869    if (last_srcinfo && srcinfo) {
870       //All the middle iterations.  Use the previous line information with the 
871       // current line info to build LineInformation structure.
872       assert(last_srcinfo->Address <= srcinfo->Address);
873       (*lineInfo)[last_srcinfo->FileName].addLine(last_srcinfo->FileName, last_srcinfo->LineNumber, 0 /* no col info for windows*/,
874                                                   (Offset) last_srcinfo->Address, (Offset) srcinfo->Address);
875       return TRUE;
876    }
877    else if (!last_srcinfo && srcinfo) {
878       //First iteration.  Don't add anything until the next
879     last_srcinfo = srcinfo;
880     return TRUE;
881   }
882   else if (last_srcinfo && !srcinfo) {
883     //Last iteration.  Add current srcinfo up to end of module.
884     (*lineInfo)[last_srcinfo->FileName].addLine(last_srcinfo->FileName, last_srcinfo->LineNumber, 0 /*no col info for windows*/,
885                 (Offset) last_srcinfo->Address, (Offset) last_srcinfo->Address);
886     return TRUE;
887   }
888   return TRUE;
889 }
890
891 void Object::parseFileLineInfo(Symtab *, dyn_hash_map<std::string, LineInformation> &li)
892 {   
893   int result;
894   static Offset last_file = 0x0;
895
896   string file_ = mf->filename();
897   const char *src_file_name = NULL;
898   const char *libname = NULL;
899
900   if (is_aout_) 
901     src_file_name = file_.c_str();
902   else 
903     libname = file_.c_str();
904
905   Offset baseAddr = get_base_addr();
906   if (last_file == baseAddr)
907     return;
908   last_file = baseAddr;
909
910   last_srcinfo = NULL;
911   result = SymEnumSourceLines(hProc, 
912                               baseAddr,
913                               libname, 
914                               src_file_name,
915                               0,
916                               0,
917                               add_line_info, 
918                               &li); 
919   if (!result) {
920     //Not a big deal. The module probably didn't have any debug information.
921     DWORD dwErr = GetLastError();
922     //parsing_printf("[%s:%u] - Couldn't SymEnumLines on %s in %s\n", 
923         //         __FILE__, __LINE__, src_file_name, libname);
924     return;
925   }
926   add_line_info(NULL, &li);
927 }
928
929 typedef struct localsStruct {
930     Function *func;
931     Offset base;
932     HANDLE p;
933     map<unsigned, unsigned> foundSyms;
934     localsStruct() : foundSyms() {}
935 } localsStruct;
936
937 BOOL CALLBACK enumLocalSymbols(PSYMBOL_INFO pSymInfo, unsigned long symSize,
938                                void *userContext)
939 {
940     Type *type;
941     Function *func;
942     storageClass storage;
943     localVar *newvar;
944     int reg;
945     signed long frameOffset;
946     Offset base;
947     HANDLE p;
948  
949     char *storageName;
950     char *paramType;
951
952     //
953     //Skip this variable if it's already been found.
954     //
955     localsStruct *locals = (localsStruct *) userContext;
956     if (locals->foundSyms.find(pSymInfo->Index) != locals->foundSyms.end())
957         return true;
958     locals->foundSyms[pSymInfo->Index] = 1;
959     base = locals->base;
960     func = locals->func;
961     p = locals->p;
962
963     //Get type
964     type = getType(p, base, pSymInfo->TypeIndex, func->getModule());
965     
966     //Get variable storage location information
967     if ((pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE) ||
968         ((pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) && 
969          (pSymInfo->Register = CV_REG_EBP)))
970     {
971         reg = -1;
972         frameOffset = (signed) pSymInfo->Address;
973         storage = storageRegOffset;
974         storageName = "Frame Relative";
975     }
976     else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE)
977     {
978         reg = pSymInfo->Register;
979         frameOffset = (signed) pSymInfo->Address;
980         storage = storageRegOffset;
981         storageName = "Register Relative";
982     }
983     else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) {
984         reg = pSymInfo->Register;
985         frameOffset = 0;
986         storage = storageReg;
987         storageName = "Register";
988     }
989     else {
990         reg = 0;
991         frameOffset = (signed) pSymInfo->Address;
992         storage = storageAddr;
993         storageName = "Absolute";
994     }
995         VariableLocation loc;
996         loc.stClass = storage;
997         loc.refClass = storageNoRef;
998         loc.frameOffset = frameOffset;
999         loc.reg = reg;
1000         
1001         std::string vName = convertCharToString(pSymInfo->Name);
1002         std::string fName = convertCharToString(func->getModule()->fileName().c_str());
1003    newvar = new localVar(vName, type, fName, -1, func);
1004         newvar->addLocation(loc);
1005
1006     //Store the variable as a local or parameter appropriately
1007    if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) {
1008       assert(func);
1009       if (!func->addParam(newvar)) {
1010          fprintf(stderr, "%s[%d]:  addParam failed\n", FILE__, __LINE__);
1011          return false;
1012       }
1013       paramType = "parameter";
1014    }
1015    else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) {
1016           assert(func);
1017       if (!func->addLocalVar(newvar)) {
1018          fprintf(stderr, "%s[%d]:  addLocalVar failed\n", FILE__, __LINE__);
1019          return false;
1020       }
1021       paramType = "local";
1022    }
1023    else {
1024            
1025       fprintf(stderr, "[%s:%u] - Local variable of unknown type.  %s in %s\n",
1026               __FILE__, __LINE__, pSymInfo->Name, func->getAllPrettyNames()[0].c_str());
1027       paramType = "unknown";
1028    }
1029
1030     
1031    const char *typeName;
1032    if (type) {
1033       typeName = type->getName().c_str();
1034    }
1035    else {
1036       typeName = "unknown";
1037    }
1038    
1039    return true;
1040 }
1041
1042
1043 static void enumLocalVars(Function *func, 
1044                           localsStruct *locals) 
1045 {
1046     IMAGEHLP_STACK_FRAME frame;
1047     memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
1048
1049     frame.InstructionOffset = locals->base + func->getOffset();
1050     int result = SymSetContext(locals->p, &frame, NULL);
1051         /*if (!result) {            
1052                 fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
1053         printSysError(GetLastError());
1054     }*/
1055     result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1056         /*if (!result) {
1057         fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
1058         printSysError(GetLastError());
1059     }*/
1060         
1061         if(func->getSize())
1062         {
1063                 memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
1064
1065                 frame.InstructionOffset = locals->base +
1066                     func->getOffset() + 
1067                     func->getSize();
1068                 result = SymSetContext(locals->p, &frame, NULL);
1069                 result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1070         }
1071
1072 //TODO?? replace this with??
1073 #if 0
1074     for (unsigned i=0; i<points.size(); i++) {
1075         frame.InstructionOffset = points[i]->addr();
1076         bool result = SymSetContext(locals->p, &frame, NULL);
1077         /*if (!result) {            
1078             fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
1079             printSysError(GetLastError());
1080         }*/
1081         result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1082         /*if (!result) {
1083             fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
1084             printSysError(GetLastError());
1085         }*/
1086     }
1087 #endif
1088
1089 }
1090
1091 static int variantValue(VARIANT *v) {
1092     switch(v->vt) {    
1093        case VT_I8:
1094            return (int) v->llVal;
1095        case VT_I4:
1096            return (int) v->lVal;
1097        case VT_UI1:
1098            return (int) v->bVal;
1099        case VT_I2:
1100            return (int) v->iVal;
1101        case VT_I1:
1102            return (int) v->cVal;
1103        case VT_UI2:
1104            return (int) v->uiVal;
1105        case VT_UI4:
1106            return (int) v->ulVal;
1107        case VT_UI8:
1108            return (int) v->ullVal;
1109        case VT_INT:
1110            return (int) v->intVal;
1111        case VT_UINT:
1112            return (int) v->uintVal;
1113        default:
1114            return 0;
1115     }
1116 }
1117
1118 // Changed. Not adding to stdTypes now
1119 static void addTypeToCollection(Type *type, Module *mod) 
1120 {
1121         typeCollection *tc = typeCollection::getModTypeCollection(mod);
1122         assert(tc);
1123         tc->addType(type);
1124 /*         
1125    typeCollection *collection;
1126
1127    collection = mod ? tc : Symtab::stdTypes;
1128    assert(collection);
1129    assert(!collection->findType(type->getID()));
1130    collection->addType(type);
1131 */
1132 }
1133
1134 static char *getTypeName(HANDLE p, Offset base, int typeIndex) {
1135     int result, length;
1136     WCHAR *wname = NULL;
1137     char *name = NULL;
1138
1139     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMNAME, &wname);
1140     if (!result) 
1141         return NULL;
1142     length = wcslen(wname) + 1;
1143     name = (char *) malloc(length + 1);
1144     result = WideCharToMultiByte(CP_ACP, 0, wname, -1, name, length, NULL, NULL);
1145     LocalFree(wname); 
1146     if (!result) {
1147         int lasterror = GetLastError();
1148 //        printSysError(lasterror);
1149         return NULL;
1150     }
1151     return name;
1152 }
1153
1154 static dataClass getDataClass(HANDLE p, Offset base, int typeIndex) {
1155     enum SymTagEnum wintype;
1156     int result, basetype;
1157
1158     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &wintype);
1159     if (!result)
1160         return dataUnknownType;
1161     switch (wintype) {
1162         case SymTagFunction:
1163         case SymTagFunctionType:
1164             return dataFunction;
1165         case SymTagPointerType:
1166             return dataPointer;
1167         case SymTagArrayType:
1168             return dataArray;
1169         case SymTagBaseType:
1170             return dataScalar;
1171         case SymTagEnum:
1172             return dataEnum;
1173         case SymTagTypedef:
1174             return dataTypedef;
1175         case SymTagUDT:
1176             enum UdtKind udtType;
1177             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
1178             if (!result)
1179                 return dataUnknownType;
1180             switch (udtType) {
1181                 case UdtUnion:
1182                     return dataUnion;
1183                 case UdtStruct:
1184                 case UdtClass:
1185                     return dataStructure;
1186                 default:
1187                     return dataUnknownType;
1188             }
1189         case SymTagFunctionArgType:
1190             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &basetype);
1191             if (!result)
1192                 return dataUnknownType;
1193             return getDataClass(p, base, basetype);
1194         default:
1195             return dataUnknownType;
1196     }
1197 }
1198
1199 static Type *getEnumType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1200     unsigned i;
1201     char *name = NULL;
1202     char *entryName = NULL;
1203     VARIANT entryValue;
1204     typeEnum *type;
1205     int result;
1206     unsigned numEntries, entriesSize;
1207     TI_FINDCHILDREN_PARAMS *entries = NULL;
1208
1209     name = getTypeName(p, base, typeIndex);
1210         std::string tName = convertCharToString(name);
1211     type = new typeEnum(typeIndex, tName);
1212     addTypeToCollection(type, mod);
1213     free(name);
1214     name = NULL;
1215
1216     //
1217     //Get the number of entries in this enum, and store them in the entries structure
1218     //
1219     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numEntries);
1220     if (!result)
1221         numEntries = 0;
1222     if (numEntries) {
1223         entriesSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numEntries + 1) * sizeof(ULONG);
1224         entries = (TI_FINDCHILDREN_PARAMS *) malloc(entriesSize);
1225         memset(entries, 0, entriesSize);
1226         entries->Count = numEntries;
1227         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, entries);
1228         if (!result)
1229             numEntries = 0;
1230     }
1231
1232     for (i=0; i<numEntries; i++) {
1233         entryName = getTypeName(p, base, entries->ChildId[i]);
1234         VariantInit(&entryValue);
1235         result = SymGetTypeInfo(p, base, entries->ChildId[i], TI_GET_VALUE, &entryValue);
1236         if (!result)
1237             continue;
1238         type->addConstant(entryName, variantValue(&entryValue));
1239     }
1240   
1241     if (entries)
1242         free(entries);
1243     return type;    
1244 }
1245
1246 static Type *getPointerType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1247     int baseTypeIndex, result;
1248     Type *baseType;
1249     typePointer *newType;
1250
1251     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
1252     if (!result) {
1253         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1254         return NULL;
1255     }
1256
1257     //
1258     // Add a place-holder for the pointer type first and fill in it's 
1259     //  base type latter.  This prevents recursion that may happen beneath 
1260     //  the getType function call below.
1261     //
1262     newType = new typePointer(typeIndex, NULL);
1263     addTypeToCollection(newType, mod);
1264
1265     baseType = getType(p, base, baseTypeIndex, mod);
1266     if (!baseType) {
1267         fprintf(stderr, "[%s:%u] - getType failed\n", __FILE__, __LINE__);
1268         return NULL;
1269     }
1270
1271     newType->setPtr(baseType);
1272     return newType;
1273 }
1274
1275 static Type *getArrayType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1276     int result, baseIndex, index;
1277     Type *indexType, *newType, *baseType;
1278     unsigned size, num_elements;
1279     ULONG64 size64;
1280     std::string bname;
1281     std::string name;
1282
1283     //Get the index type (usually an int of some kind).  Currently not used.
1284     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_ARRAYINDEXTYPEID, &index);
1285     if (!result) {
1286         fprintf(stderr, "[%s:%u] - TI_GET_ARRAYINDEXTYPEID failed\n", 
1287                 __FILE__, __LINE__);
1288         return NULL;
1289     }
1290     indexType = getType(p, base, index, mod);
1291
1292     //Get the base type (the type of the elements in the array)
1293     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseIndex);
1294     if (!result) {
1295         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1296         return NULL;
1297     }
1298     baseType = getType(p, base, baseIndex, mod);
1299
1300     bname = baseType->getName();
1301     name = bname + "[]";
1302         
1303     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1304     if (!result) {
1305         num_elements = 0;
1306     }
1307     else {
1308       size = (unsigned) size64;
1309       num_elements = size / baseType->getSize();
1310     }
1311
1312     newType = new typeArray(typeIndex, baseType, 0, num_elements-1, name);
1313     newType->getSize();
1314     addTypeToCollection(newType, mod);
1315     assert(newType->getID() == typeIndex);
1316
1317     return newType;
1318 }
1319
1320
1321 static Type *getTypedefType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1322     int result, baseTypeIndex;
1323     Type *baseType, *newType;
1324     char *name;
1325
1326     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
1327     if (!result) {
1328         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1329         return NULL;
1330     }
1331     baseType = getType(p, base, baseTypeIndex, mod);
1332     if (!baseType) {
1333         return NULL;
1334     }
1335  
1336     name = getTypeName(p, base, typeIndex);
1337         std::string tName = convertCharToString(name);
1338     newType = new typeTypedef(typeIndex, baseType, tName);
1339     addTypeToCollection(newType, mod);
1340     return newType;
1341 }
1342
1343 static Type *getUDTType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1344     int result, symtag;
1345     unsigned size, numChildren, childrenSize, child_offset, i, child_size;
1346     fieldListType *newType;
1347     UINT64 size64;
1348     const char *name, *childName;
1349     enum UdtKind udtType;
1350     TI_FINDCHILDREN_PARAMS *children = NULL;
1351
1352     //
1353     // Get name for structure
1354     //
1355     name = getTypeName(p, base, typeIndex);
1356         std::string tName = convertCharToString(name);
1357         result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1358     if (!result) {
1359         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
1360         return NULL;
1361     }
1362     size = (unsigned) size64;
1363
1364     //
1365     // Determine whether it's a class, struct, or union and create the 
1366     //  new_type appropriately
1367     //
1368     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
1369     if (!result) {
1370         fprintf(stderr, "[%s:%u] - TI_GET_UDTKIND returned error\n");
1371         return NULL;
1372     }
1373     switch (udtType) {
1374         case UdtUnion:
1375             newType = new typeUnion(typeIndex, tName);
1376             break;
1377         case UdtStruct:
1378         case UdtClass:
1379         default:
1380             newType = new typeStruct(typeIndex, tName);
1381             break;
1382     }
1383     addTypeToCollection(newType, mod);
1384     if (name)
1385        free((void *) name);
1386     name = NULL;
1387
1388
1389     //
1390     // Store the number of member variables/functions/stuff in numChildren
1391     //
1392     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numChildren);
1393     if (!result)
1394         numChildren = 0;
1395     //
1396     // Get the list of variables/functions/stuff
1397     //
1398     if (numChildren) {
1399         childrenSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numChildren + 1) * sizeof(ULONG);
1400         children = (TI_FINDCHILDREN_PARAMS *) malloc(childrenSize);
1401         memset(children, 0, childrenSize);
1402         children->Count = numChildren;
1403         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, children);
1404         if (!result)
1405             numChildren = 0;
1406     }
1407
1408     //
1409     // Create/Find the type of each child and add it to newType appropriately
1410     //
1411     for (i=0; i<numChildren; i++) {
1412         // Create/Get child type
1413         Type *child_type = getType(p, base, children->ChildId[i], mod);
1414         if (!child_type)
1415             continue;
1416
1417         // Figure out a name of this object
1418         childName = NULL;
1419         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_SYMTAG, &symtag);
1420         if (result && symtag == SymTagBaseClass) {
1421             childName = P_strdup("{superclass}");
1422         }
1423         if (!childName)
1424             childName = getTypeName(p, base, children->ChildId[i]);
1425         if (!childName) 
1426             childName = P_strdup(child_type->getName().c_str());
1427
1428         // Find the offset of this member in the structure
1429         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_OFFSET, &child_offset);
1430         if (!result) {
1431             child_offset = 0; //Probably a member function
1432             child_size = 0;
1433         }
1434         else {
1435             child_offset *= 8; //Internally measured in bits
1436             child_size = child_type->getSize();
1437         }
1438
1439                 std::string fName = convertCharToString(childName);
1440         newType->addField(fName, child_type, child_offset);
1441         if (childName)
1442             free((void *) childName);
1443         childName = NULL;
1444     }
1445
1446     if (children)
1447         free(children);
1448
1449     return newType;
1450 }
1451
1452 static Type *getLayeredType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1453     int result, newTypeIndex;
1454     Type *newType;
1455
1456     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &newTypeIndex);
1457     if (!result) {
1458         fprintf(stderr, "TI_GET_TYPEID failed\n");
1459         return NULL;
1460     }
1461
1462     newType = getType(p, base, newTypeIndex, mod);
1463     return newType;
1464 }
1465
1466 static Type *getFunctionType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1467     int result, retTypeIndex;
1468     typeFunction *newType;
1469     Type *retType;
1470     unsigned num_params, args_size, i;
1471     std::vector<Type *> params;
1472     TI_FINDCHILDREN_PARAMS *args = NULL;
1473     std::string name;
1474
1475     //Create the function early to avoid recursive references
1476         std::string tName = "";
1477     newType = new typeFunction(typeIndex, NULL, tName);
1478     addTypeToCollection(newType, mod);
1479
1480     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &retTypeIndex);
1481     if (!result) {
1482         fprintf(stderr, "[%s:%u] - Couldn't TI_GET_TYPEID\n", __FILE__, __LINE__);
1483         return NULL;
1484     }
1485
1486     retType = getType(p, base, retTypeIndex, mod);
1487     if (!retType) {
1488         return NULL;
1489     }
1490     newType->setRetType(retType);
1491
1492     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_COUNT, &num_params);
1493     if (!result)
1494         goto done_params;
1495
1496     args_size = sizeof(TI_FINDCHILDREN_PARAMS) + (num_params + 1) * sizeof(ULONG);
1497     args = (TI_FINDCHILDREN_PARAMS *) malloc(args_size);
1498     memset(args, 0, args_size);
1499     args->Count = num_params;
1500     result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, args);
1501     if (!result)
1502         goto done_params;
1503     
1504     for (i=0; i<num_params; i++) {
1505         Type *arg_type = getType(p, base, args->ChildId[i], mod);
1506         if (!arg_type) {
1507             continue;
1508         }
1509         params.push_back(arg_type);
1510     }
1511
1512 done_params:
1513
1514     //
1515     // Build a type name that looks like the following:
1516     //   (return_type)(param1_type, param2_type, ...)
1517     name = "(";
1518     name += retType->getName();
1519     name += ")(";
1520     for (i=0; i<params.size(); i++) {
1521         if (i != 0)
1522             name += ", ";
1523         name += params[i]->getName();
1524     }
1525     name += "()";
1526         
1527         std::string newName = name;
1528     newType->setName(newName);
1529
1530     for (i=0; i<params.size(); i++) {
1531         //TODO?? have a name for the parameter. Required??
1532         newType->addParam(params[i]);
1533     }
1534
1535     if (args)
1536         free(args);
1537
1538     return newType;
1539 }
1540
1541 static Type *getBaseType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1542     BasicType baseType;
1543     int result;
1544     ULONG64 size64;
1545     unsigned size;
1546     Type *newType;
1547
1548     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_BASETYPE, &baseType);
1549     if (!result) {
1550         fprintf(stderr, "[%s:%u] - TI_GET_BASETYPE return error\n");
1551         return NULL;
1552     }
1553
1554     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1555     if (!result) {
1556         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
1557         return NULL;
1558     }
1559     size = (unsigned) size64;
1560     switch(baseType) {
1561          case btNoType:
1562                  newType = NULL;
1563                  break;
1564          case btVoid:
1565          newType = new typeScalar(typeIndex, size, "void");
1566                  break;
1567          case btChar:
1568          newType = new typeScalar(typeIndex, size, "char");
1569                  break;
1570          case btWChar:
1571          newType = new typeScalar(typeIndex, size, "wchar");
1572                  break;
1573          case btInt:
1574          if (size == 8)
1575            newType = new typeScalar(typeIndex, size, "long long int");
1576          else if (size == 4)
1577            newType = new typeScalar(typeIndex, size, "int");
1578          else if (size == 2)
1579            newType = new typeScalar(typeIndex, size, "short");
1580          else if (size == 1)
1581            newType = new typeScalar(typeIndex, size, "char");
1582          else
1583            newType = new typeScalar(typeIndex, size, "");
1584                  break;
1585          case btUInt:
1586          if (size == 8)
1587            newType = new typeScalar(typeIndex, size, "unsigned long long int");
1588          else if (size == 4)
1589            newType = new typeScalar(typeIndex, size, "unsigned int");
1590          else if (size == 2)
1591            newType = new typeScalar(typeIndex, size, "unsigned short");
1592          else if (size == 1)
1593            newType = new typeScalar(typeIndex, size, "unsigned char");
1594          else
1595            newType = new typeScalar(typeIndex, size, "");
1596                  break;
1597          case btFloat:
1598          if (size == 8)
1599              newType = new typeScalar(typeIndex, size, "double");
1600          else
1601              newType = new typeScalar(typeIndex, size, "float");
1602                  break;
1603          case btBCD:
1604          newType = new typeScalar(typeIndex, size, "BCD");
1605                  break;
1606          case btBool:
1607          newType = new typeScalar(typeIndex, size, "bool");
1608                  break;
1609          case btLong:
1610          newType = new typeScalar(typeIndex, size, "long");
1611                  break;
1612          case btULong:
1613          newType = new typeScalar(typeIndex, size, "unsigned long");
1614                  break;
1615          case btCurrency:
1616          newType = new typeScalar(typeIndex, size, "currency");
1617                  break;
1618          case btDate:
1619          newType = new typeScalar(typeIndex, size, "Date");
1620                  break;
1621          case btVariant:
1622          newType = new typeScalar(typeIndex, size, "variant");
1623                  break;
1624          case btComplex:
1625          newType = new typeScalar(typeIndex, size, "complex");
1626                  break;
1627          case btBit:
1628          newType = new typeScalar(typeIndex, size, "bit");
1629                  break;
1630          case btBSTR:
1631          newType = new typeScalar(typeIndex, size, "bstr");
1632                  break;
1633          case btHresult:
1634          newType = new typeScalar(typeIndex, size, "Hresult");
1635                  break;
1636          default:
1637                  fprintf(stderr, "Couldn't parse baseType %d for %d\n", baseType, typeIndex);
1638          assert(0);
1639                  break;
1640    }
1641    if (newType)
1642        addTypeToCollection(newType, mod);
1643    return newType;
1644 }
1645
1646 static Type *getType(HANDLE p, Offset base, int typeIndex, Module *mod) 
1647 {
1648    static unsigned depth = 0;
1649    BOOL result;
1650    Type *foundType = NULL;
1651    typeCollection *collection;
1652    enum SymTagEnum symtag;
1653
1654    if (!typeIndex)
1655        return NULL;
1656
1657    //
1658    // Check if this type has already been created (they're indexed by typeIndex).
1659    // If it has, go ahead and return the existing one.
1660    // If not, then start creating a new type.
1661    //
1662    if (mod)
1663        collection = typeCollection::getModTypeCollection(mod);
1664    else
1665            collection = Symtab::stdTypes;
1666    assert(collection);
1667
1668
1669    //
1670    // Check to see if we've already parsed this type
1671    //
1672    foundType = collection->findType(typeIndex);
1673    if (foundType) {
1674        return foundType;
1675    }
1676
1677    //
1678    // Types on Windows are stored as part of a special type of symbol.  TI_GET_SYMTAG 
1679    // Gets the meta information about the type.
1680    //
1681    result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &symtag);
1682    if (!result) {
1683        depth--;
1684        return NULL;
1685    }
1686    switch (symtag) {
1687        case SymTagBaseType:
1688            foundType = getBaseType(p, base, typeIndex, mod);
1689            break;
1690        case SymTagEnum:
1691            foundType = getEnumType(p, base, typeIndex, mod);
1692            break;
1693        case SymTagFunctionType:
1694            foundType = getFunctionType(p, base, typeIndex, mod);
1695            break;
1696        case SymTagPointerType:
1697            foundType = getPointerType(p, base, typeIndex, mod);
1698            break;
1699        case SymTagArrayType:
1700            foundType = getArrayType(p, base, typeIndex, mod);
1701            break;
1702        case SymTagTypedef:
1703            foundType = getTypedefType(p, base, typeIndex, mod);
1704            break;
1705        case SymTagUDT:
1706            foundType = getUDTType(p, base, typeIndex, mod);
1707            break;
1708        case SymTagFunctionArgType:
1709        case SymTagData:
1710        case SymTagFunction:
1711        case SymTagBaseClass:
1712            foundType = getLayeredType(p, base, typeIndex, mod);
1713            if (foundType)
1714              typeIndex = foundType->getID();
1715            break;
1716        case SymTagThunk:
1717            foundType = NULL;
1718            break;
1719        case SymTagVTableShape:
1720        case SymTagVTable:
1721            break;
1722        default:
1723            fprintf(stderr, "Unknown type %d\n", symtag);
1724            assert(0);
1725            foundType = NULL;
1726            break;
1727    }
1728
1729    return foundType;
1730 }
1731
1732 typedef struct proc_mod_pair {
1733         HANDLE handle;
1734         Symtab *obj;
1735     Offset base_addr;
1736 } proc_mod_pair;
1737
1738 static void findLocalVars(Function *func, proc_mod_pair base) {
1739     Module *mod = func->getModule();
1740     localsStruct locals;
1741     HANDLE p = base.handle;
1742
1743     locals.func = func;
1744     locals.base = base.base_addr;
1745     locals.p = p;
1746
1747         enumLocalVars(func, &locals);
1748     //
1749     // The windows debugging interface allows us to get local variables
1750     // at specific points, which makes it hard to enumerate all locals (as we want).
1751     // Instead we'll get the local variables at the most common points below.
1752     //
1753     //TODO?
1754         //=const std::vector<instPoint*> &points = ifunc->funcEntries();
1755     //=enumLocalVars(func, ifunc->funcEntries(), &locals);
1756     //=enumLocalVars(func, ifunc->funcExits(), &locals);
1757     //=enumLocalVars(func, ifunc->funcCalls(), &locals);
1758     //=enumLocalVars(func, ifunc->funcArbitraryPoints(), &locals);
1759 }
1760
1761 BOOL CALLBACK add_type_info(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, void *info)
1762 {
1763    HANDLE p;
1764    Offset obj_base;
1765    proc_mod_pair *pair;
1766    Symtab *obj;
1767    Type *type;
1768    char *name;
1769    Address addr;
1770
1771    if (!isGlobalSymbol(pSymInfo)) {
1772        //We do local symbols elsewhere
1773        return TRUE;
1774    }
1775
1776    pair = (proc_mod_pair *) info;
1777    p = pair->handle;
1778    obj_base = pair->base_addr;
1779    obj = pair->obj;
1780    name = pSymInfo->Name;
1781    addr = (Address) pSymInfo->Address - obj_base;
1782
1783    std::vector<Module *> mods;
1784    Module *mod;
1785    //TODO?? change later
1786    if(!obj->getAllModules(mods))
1787    {
1788            return true;
1789    }
1790    else
1791            mod = mods[0];
1792    
1793    if (obj->isExec()) {
1794       //When parsing the a.out, sort the type information into specific modules.  This doesn't matter
1795       // for libraries, because there is a 1:1 mapping between modules and objects.
1796       //
1797       //A module is a collection of functions, but doesn't include global data types.  Global variables
1798       // will go into the DEFAULT_MODULE
1799           std::vector<Symbol *> syms;
1800           if(obj->findFuncByEntryOffset(syms, (Offset) pSymInfo->Address))
1801           {
1802                   Symbol *f = syms[0];
1803              //No containing module.  Only insert this into DEFAULT_MODULE
1804           if (strcmp(f->getModule()->fileName().c_str(), "DEFAULT_MODULE"))
1805               return true;
1806       }
1807    }
1808
1809    type = getType(p, obj_base, pSymInfo->TypeIndex, mod);
1810
1811    
1812 //   fprintf(stderr, "[%s:%u] - Variable %s had type %s\n", __FILE__, __LINE__,
1813 //       name, type ? type->getName().c_str() : "{NO TYPE}");
1814    
1815    if (type)
1816    {
1817       Variable *var = NULL;
1818       bool result = obj->findVariableByOffset(var, addr);
1819       if (result) {
1820          var->setType(type);
1821       }
1822       if (name) {
1823          std::string vName = name;
1824                  typeCollection *tc = typeCollection::getModTypeCollection(mod);
1825                  assert(tc);
1826          tc->addGlobalVariable(vName, type);
1827       }
1828    }
1829    return TRUE;
1830 }
1831
1832 void Object::parseTypeInfo(Symtab *obj) {
1833     proc_mod_pair pair;
1834     BOOL result;
1835     //
1836     //Parse global variable type information
1837     //
1838
1839     pair.handle = hProc;
1840     pair.obj = obj;
1841     pair.base_addr = getBaseAddress();
1842     
1843     if (!pair.base_addr) {
1844         pair.base_addr = getLoadAddress();
1845     }
1846   
1847    HANDLE mapAddr = mf->base_addr();
1848     result = SymEnumSymbols(hProc, (DWORD64)mapAddr, NULL, 
1849                             add_type_info, &pair);
1850         if (!result){
1851                 printSysError(GetLastError());
1852 //        parsing_printf("SymEnumSymbols was unsuccessful.  Type info may be incomplete\n");
1853     }
1854
1855     //
1856     // Parse local variables and local type information
1857     //
1858     std::vector<Function *> funcs;
1859         obj->getAllFunctions(funcs);
1860     for (unsigned i=0; i < funcs.size(); i++) {
1861         findLocalVars(funcs[i], pair);
1862     }
1863 }
1864
1865 bool AObject::getSegments(vector<Segment> &segs) const
1866 {
1867         for(unsigned int i=0; i<regions_.size(); i++){
1868                 Segment seg;
1869                 seg.data = regions_[i]->getPtrToRawData();
1870                 //seg.loadaddr = regions_[i] -> getDiskOffset();
1871                 seg.loadaddr = regions_[i] -> getRegionAddr();
1872                 seg.size = regions_[i] -> getDiskSize();
1873                 seg.name = regions_[i] -> getRegionName();
1874                 //seg.segFlags = 
1875                 segs.push_back(seg);
1876         }
1877     return true;
1878 }
1879
1880 bool Object::emitDriver(Symtab *obj, string fName, std::vector<Symbol *>&allSymbols, 
1881                                                 unsigned flag) {
1882         emitWin *em = new emitWin((PCHAR)GetMapAddr(), this, err_func_);
1883         return em -> driver(obj, fName);
1884 }