windows build fixes and some more work on symtab serialization
[dyninst.git] / symtabAPI / src / Object-nt.C
1 /*
2  * Copyright (c) 1996-2007 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 = true;
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 = (VariableLocation *)malloc(sizeof(VariableLocation));
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);
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 #if 0
1014                 if(!func->params_)
1015                         func->params_ = new localVarCollection();
1016       func->params_->addLocalVar(newvar);
1017 #endif
1018       paramType = "parameter";
1019    }
1020    else if (pSymInfo->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) {
1021           assert(func);
1022       if (!func->addLocalVar(newvar)) {
1023          fprintf(stderr, "%s[%d]:  addLocalVar failed\n", FILE__, __LINE__);
1024          return false;
1025       }
1026 #if 0
1027       if(!func->vars_)
1028          func->vars_ = new localVarCollection();
1029       func->vars_->addLocalVar(newvar);
1030 #endif
1031       paramType = "local";
1032    }
1033    else {
1034            
1035       fprintf(stderr, "[%s:%u] - Local variable of unknown type.  %s in %s\n",
1036               __FILE__, __LINE__, pSymInfo->Name, func->getAllPrettyNames()[0].c_str());
1037       paramType = "unknown";
1038    }
1039
1040     
1041    const char *typeName;
1042    if (type) {
1043       typeName = type->getName().c_str();
1044    }
1045    else {
1046       typeName = "unknown";
1047    }
1048    
1049    return true;
1050 }
1051
1052
1053 static void enumLocalVars(Function *func, 
1054                           localsStruct *locals) 
1055 {
1056     IMAGEHLP_STACK_FRAME frame;
1057     memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
1058
1059     frame.InstructionOffset = locals->base + func->getOffset();
1060     int result = SymSetContext(locals->p, &frame, NULL);
1061         /*if (!result) {            
1062                 fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
1063         printSysError(GetLastError());
1064     }*/
1065     result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1066         /*if (!result) {
1067         fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
1068         printSysError(GetLastError());
1069     }*/
1070         
1071         if(func->getSize())
1072         {
1073                 memset(&frame, 0, sizeof(IMAGEHLP_STACK_FRAME));
1074
1075                 frame.InstructionOffset = locals->base +
1076                     func->getOffset() + 
1077                     func->getSize();
1078                 result = SymSetContext(locals->p, &frame, NULL);
1079                 result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1080         }
1081
1082 //TODO?? replace this with??
1083 #if 0
1084     for (unsigned i=0; i<points.size(); i++) {
1085         frame.InstructionOffset = points[i]->addr();
1086         bool result = SymSetContext(locals->p, &frame, NULL);
1087         /*if (!result) {            
1088             fprintf(stderr, "[%s:%u] - Couldn't SymSetContext\n", __FILE__, __LINE__);
1089             printSysError(GetLastError());
1090         }*/
1091         result = SymEnumSymbols(locals->p, 0, NULL, enumLocalSymbols, locals);
1092         /*if (!result) {
1093             fprintf(stderr, "[%s:%u] - Couldn't SymEnumSymbols\n", __FILE__, __LINE__);
1094             printSysError(GetLastError());
1095         }*/
1096     }
1097 #endif
1098
1099 }
1100
1101 static int variantValue(VARIANT *v) {
1102     switch(v->vt) {    
1103        case VT_I8:
1104            return (int) v->llVal;
1105        case VT_I4:
1106            return (int) v->lVal;
1107        case VT_UI1:
1108            return (int) v->bVal;
1109        case VT_I2:
1110            return (int) v->iVal;
1111        case VT_I1:
1112            return (int) v->cVal;
1113        case VT_UI2:
1114            return (int) v->uiVal;
1115        case VT_UI4:
1116            return (int) v->ulVal;
1117        case VT_UI8:
1118            return (int) v->ullVal;
1119        case VT_INT:
1120            return (int) v->intVal;
1121        case VT_UINT:
1122            return (int) v->uintVal;
1123        default:
1124            return 0;
1125     }
1126 }
1127
1128 // Changed. Not adding to stdTypes now
1129 static void addTypeToCollection(Type *type, Module *mod) {
1130    mod->getModuleTypes()->addType(type);
1131 /*         
1132    typeCollection *collection;
1133
1134    collection = mod ? mod->getModuleTypes() : Symtab::stdTypes;
1135    assert(collection);
1136    assert(!collection->findType(type->getID()));
1137    collection->addType(type);
1138 */
1139 }
1140
1141 static char *getTypeName(HANDLE p, Offset base, int typeIndex) {
1142     int result, length;
1143     WCHAR *wname = NULL;
1144     char *name = NULL;
1145
1146     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMNAME, &wname);
1147     if (!result) 
1148         return NULL;
1149     length = wcslen(wname) + 1;
1150     name = (char *) malloc(length + 1);
1151     result = WideCharToMultiByte(CP_ACP, 0, wname, -1, name, length, NULL, NULL);
1152     LocalFree(wname); 
1153     if (!result) {
1154         int lasterror = GetLastError();
1155 //        printSysError(lasterror);
1156         return NULL;
1157     }
1158     return name;
1159 }
1160
1161 static dataClass getDataClass(HANDLE p, Offset base, int typeIndex) {
1162     enum SymTagEnum wintype;
1163     int result, basetype;
1164
1165     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &wintype);
1166     if (!result)
1167         return dataUnknownType;
1168     switch (wintype) {
1169         case SymTagFunction:
1170         case SymTagFunctionType:
1171             return dataFunction;
1172         case SymTagPointerType:
1173             return dataPointer;
1174         case SymTagArrayType:
1175             return dataArray;
1176         case SymTagBaseType:
1177             return dataScalar;
1178         case SymTagEnum:
1179             return dataEnum;
1180         case SymTagTypedef:
1181             return dataTypedef;
1182         case SymTagUDT:
1183             enum UdtKind udtType;
1184             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
1185             if (!result)
1186                 return dataUnknownType;
1187             switch (udtType) {
1188                 case UdtUnion:
1189                     return dataUnion;
1190                 case UdtStruct:
1191                 case UdtClass:
1192                     return dataStructure;
1193                 default:
1194                     return dataUnknownType;
1195             }
1196         case SymTagFunctionArgType:
1197             result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &basetype);
1198             if (!result)
1199                 return dataUnknownType;
1200             return getDataClass(p, base, basetype);
1201         default:
1202             return dataUnknownType;
1203     }
1204 }
1205
1206 static Type *getEnumType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1207     unsigned i;
1208     char *name = NULL;
1209     char *entryName = NULL;
1210     VARIANT entryValue;
1211     typeEnum *type;
1212     int result;
1213     unsigned numEntries, entriesSize;
1214     TI_FINDCHILDREN_PARAMS *entries = NULL;
1215
1216     name = getTypeName(p, base, typeIndex);
1217         std::string tName = convertCharToString(name);
1218     type = new typeEnum(typeIndex, tName);
1219     addTypeToCollection(type, mod);
1220     free(name);
1221     name = NULL;
1222
1223     //
1224     //Get the number of entries in this enum, and store them in the entries structure
1225     //
1226     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numEntries);
1227     if (!result)
1228         numEntries = 0;
1229     if (numEntries) {
1230         entriesSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numEntries + 1) * sizeof(ULONG);
1231         entries = (TI_FINDCHILDREN_PARAMS *) malloc(entriesSize);
1232         memset(entries, 0, entriesSize);
1233         entries->Count = numEntries;
1234         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, entries);
1235         if (!result)
1236             numEntries = 0;
1237     }
1238
1239     for (i=0; i<numEntries; i++) {
1240         entryName = getTypeName(p, base, entries->ChildId[i]);
1241         VariantInit(&entryValue);
1242         result = SymGetTypeInfo(p, base, entries->ChildId[i], TI_GET_VALUE, &entryValue);
1243         if (!result)
1244             continue;
1245         type->addConstant(entryName, variantValue(&entryValue));
1246     }
1247   
1248     if (entries)
1249         free(entries);
1250     return type;    
1251 }
1252
1253 static Type *getPointerType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1254     int baseTypeIndex, result;
1255     Type *baseType;
1256     typePointer *newType;
1257
1258     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
1259     if (!result) {
1260         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1261         return NULL;
1262     }
1263
1264     //
1265     // Add a place-holder for the pointer type first and fill in it's 
1266     //  base type latter.  This prevents recursion that may happen beneath 
1267     //  the getType function call below.
1268     //
1269     newType = new typePointer(typeIndex, NULL);
1270     addTypeToCollection(newType, mod);
1271
1272     baseType = getType(p, base, baseTypeIndex, mod);
1273     if (!baseType) {
1274         fprintf(stderr, "[%s:%u] - getType failed\n", __FILE__, __LINE__);
1275         return NULL;
1276     }
1277
1278     newType->setPtr(baseType);
1279     return newType;
1280 }
1281
1282 static Type *getArrayType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1283     int result, baseIndex, index;
1284     Type *indexType, *newType, *baseType;
1285     unsigned size, num_elements;
1286     ULONG64 size64;
1287     std::string bname;
1288     std::string name;
1289
1290     //Get the index type (usually an int of some kind).  Currently not used.
1291     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_ARRAYINDEXTYPEID, &index);
1292     if (!result) {
1293         fprintf(stderr, "[%s:%u] - TI_GET_ARRAYINDEXTYPEID failed\n", 
1294                 __FILE__, __LINE__);
1295         return NULL;
1296     }
1297     indexType = getType(p, base, index, mod);
1298
1299     //Get the base type (the type of the elements in the array)
1300     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseIndex);
1301     if (!result) {
1302         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1303         return NULL;
1304     }
1305     baseType = getType(p, base, baseIndex, mod);
1306
1307     bname = baseType->getName();
1308     name = bname + "[]";
1309         
1310     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1311     if (!result) {
1312         num_elements = 0;
1313     }
1314     else {
1315       size = (unsigned) size64;
1316       num_elements = size / baseType->getSize();
1317     }
1318
1319     newType = new typeArray(typeIndex, baseType, 0, num_elements-1, name);
1320     newType->getSize();
1321     addTypeToCollection(newType, mod);
1322     assert(newType->getID() == typeIndex);
1323
1324     return newType;
1325 }
1326
1327
1328 static Type *getTypedefType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1329     int result, baseTypeIndex;
1330     Type *baseType, *newType;
1331     char *name;
1332
1333     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &baseTypeIndex);
1334     if (!result) {
1335         fprintf(stderr, "[%s:%u] - TI_GET_TYPEID failed\n", __FILE__, __LINE__);
1336         return NULL;
1337     }
1338     baseType = getType(p, base, baseTypeIndex, mod);
1339     if (!baseType) {
1340         return NULL;
1341     }
1342  
1343     name = getTypeName(p, base, typeIndex);
1344         std::string tName = convertCharToString(name);
1345     newType = new typeTypedef(typeIndex, baseType, tName);
1346     addTypeToCollection(newType, mod);
1347     return newType;
1348 }
1349
1350 static Type *getUDTType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1351     int result, symtag;
1352     unsigned size, numChildren, childrenSize, child_offset, i, child_size;
1353     fieldListType *newType;
1354     UINT64 size64;
1355     const char *name, *childName;
1356     enum UdtKind udtType;
1357     TI_FINDCHILDREN_PARAMS *children = NULL;
1358
1359     //
1360     // Get name for structure
1361     //
1362     name = getTypeName(p, base, typeIndex);
1363         std::string tName = convertCharToString(name);
1364         result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1365     if (!result) {
1366         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
1367         return NULL;
1368     }
1369     size = (unsigned) size64;
1370
1371     //
1372     // Determine whether it's a class, struct, or union and create the 
1373     //  new_type appropriately
1374     //
1375     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_UDTKIND, &udtType);
1376     if (!result) {
1377         fprintf(stderr, "[%s:%u] - TI_GET_UDTKIND returned error\n");
1378         return NULL;
1379     }
1380     switch (udtType) {
1381         case UdtUnion:
1382             newType = new typeUnion(typeIndex, tName);
1383             break;
1384         case UdtStruct:
1385         case UdtClass:
1386         default:
1387             newType = new typeStruct(typeIndex, tName);
1388             break;
1389     }
1390     addTypeToCollection(newType, mod);
1391     if (name)
1392        free((void *) name);
1393     name = NULL;
1394
1395
1396     //
1397     // Store the number of member variables/functions/stuff in numChildren
1398     //
1399     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_CHILDRENCOUNT, &numChildren);
1400     if (!result)
1401         numChildren = 0;
1402     //
1403     // Get the list of variables/functions/stuff
1404     //
1405     if (numChildren) {
1406         childrenSize = sizeof(TI_FINDCHILDREN_PARAMS) + (numChildren + 1) * sizeof(ULONG);
1407         children = (TI_FINDCHILDREN_PARAMS *) malloc(childrenSize);
1408         memset(children, 0, childrenSize);
1409         children->Count = numChildren;
1410         result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, children);
1411         if (!result)
1412             numChildren = 0;
1413     }
1414
1415     //
1416     // Create/Find the type of each child and add it to newType appropriately
1417     //
1418     for (i=0; i<numChildren; i++) {
1419         // Create/Get child type
1420         Type *child_type = getType(p, base, children->ChildId[i], mod);
1421         if (!child_type)
1422             continue;
1423
1424         // Figure out a name of this object
1425         childName = NULL;
1426         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_SYMTAG, &symtag);
1427         if (result && symtag == SymTagBaseClass) {
1428             childName = P_strdup("{superclass}");
1429         }
1430         if (!childName)
1431             childName = getTypeName(p, base, children->ChildId[i]);
1432         if (!childName) 
1433             childName = P_strdup(child_type->getName().c_str());
1434
1435         // Find the offset of this member in the structure
1436         result = SymGetTypeInfo(p, base, children->ChildId[i], TI_GET_OFFSET, &child_offset);
1437         if (!result) {
1438             child_offset = 0; //Probably a member function
1439             child_size = 0;
1440         }
1441         else {
1442             child_offset *= 8; //Internally measured in bits
1443             child_size = child_type->getSize();
1444         }
1445
1446                 std::string fName = convertCharToString(childName);
1447         newType->addField(fName, child_type, child_offset);
1448         if (childName)
1449             free((void *) childName);
1450         childName = NULL;
1451     }
1452
1453     if (children)
1454         free(children);
1455
1456     return newType;
1457 }
1458
1459 static Type *getLayeredType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1460     int result, newTypeIndex;
1461     Type *newType;
1462
1463     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &newTypeIndex);
1464     if (!result) {
1465         fprintf(stderr, "TI_GET_TYPEID failed\n");
1466         return NULL;
1467     }
1468
1469     newType = getType(p, base, newTypeIndex, mod);
1470     return newType;
1471 }
1472
1473 static Type *getFunctionType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1474     int result, retTypeIndex;
1475     typeFunction *newType;
1476     Type *retType;
1477     unsigned num_params, args_size, i;
1478     std::vector<Type *> params;
1479     TI_FINDCHILDREN_PARAMS *args = NULL;
1480     std::string name;
1481
1482     //Create the function early to avoid recursive references
1483         std::string tName = "";
1484     newType = new typeFunction(typeIndex, NULL, tName);
1485     addTypeToCollection(newType, mod);
1486
1487     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_TYPEID, &retTypeIndex);
1488     if (!result) {
1489         fprintf(stderr, "[%s:%u] - Couldn't TI_GET_TYPEID\n", __FILE__, __LINE__);
1490         return NULL;
1491     }
1492
1493     retType = getType(p, base, retTypeIndex, mod);
1494     if (!retType) {
1495         return NULL;
1496     }
1497     newType->setRetType(retType);
1498
1499     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_COUNT, &num_params);
1500     if (!result)
1501         goto done_params;
1502
1503     args_size = sizeof(TI_FINDCHILDREN_PARAMS) + (num_params + 1) * sizeof(ULONG);
1504     args = (TI_FINDCHILDREN_PARAMS *) malloc(args_size);
1505     memset(args, 0, args_size);
1506     args->Count = num_params;
1507     result = SymGetTypeInfo(p, base, typeIndex, TI_FINDCHILDREN, args);
1508     if (!result)
1509         goto done_params;
1510     
1511     for (i=0; i<num_params; i++) {
1512         Type *arg_type = getType(p, base, args->ChildId[i], mod);
1513         if (!arg_type) {
1514             continue;
1515         }
1516         params.push_back(arg_type);
1517     }
1518
1519 done_params:
1520
1521     //
1522     // Build a type name that looks like the following:
1523     //   (return_type)(param1_type, param2_type, ...)
1524     name = "(";
1525     name += retType->getName();
1526     name += ")(";
1527     for (i=0; i<params.size(); i++) {
1528         if (i != 0)
1529             name += ", ";
1530         name += params[i]->getName();
1531     }
1532     name += "()";
1533         
1534         std::string newName = name;
1535     newType->setName(newName);
1536
1537     for (i=0; i<params.size(); i++) {
1538         //TODO?? have a name for the parameter. Required??
1539         newType->addParam(params[i]);
1540     }
1541
1542     if (args)
1543         free(args);
1544
1545     return newType;
1546 }
1547
1548 static Type *getBaseType(HANDLE p, Offset base, int typeIndex, Module *mod) {
1549     BasicType baseType;
1550     int result;
1551     ULONG64 size64;
1552     unsigned size;
1553     Type *newType;
1554
1555     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_BASETYPE, &baseType);
1556     if (!result) {
1557         fprintf(stderr, "[%s:%u] - TI_GET_BASETYPE return error\n");
1558         return NULL;
1559     }
1560
1561     result = SymGetTypeInfo(p, base, typeIndex, TI_GET_LENGTH, &size64);
1562     if (!result) {
1563         fprintf(stderr, "[%s:%u] - TI_GET_LENGTH return error\n");
1564         return NULL;
1565     }
1566     size = (unsigned) size64;
1567     switch(baseType) {
1568          case btNoType:
1569                  newType = NULL;
1570                  break;
1571          case btVoid:
1572          newType = new typeScalar(typeIndex, size, "void");
1573                  break;
1574          case btChar:
1575          newType = new typeScalar(typeIndex, size, "char");
1576                  break;
1577          case btWChar:
1578          newType = new typeScalar(typeIndex, size, "wchar");
1579                  break;
1580          case btInt:
1581          if (size == 8)
1582            newType = new typeScalar(typeIndex, size, "long long int");
1583          else if (size == 4)
1584            newType = new typeScalar(typeIndex, size, "int");
1585          else if (size == 2)
1586            newType = new typeScalar(typeIndex, size, "short");
1587          else if (size == 1)
1588            newType = new typeScalar(typeIndex, size, "char");
1589          else
1590            newType = new typeScalar(typeIndex, size, "");
1591                  break;
1592          case btUInt:
1593          if (size == 8)
1594            newType = new typeScalar(typeIndex, size, "unsigned long long int");
1595          else if (size == 4)
1596            newType = new typeScalar(typeIndex, size, "unsigned int");
1597          else if (size == 2)
1598            newType = new typeScalar(typeIndex, size, "unsigned short");
1599          else if (size == 1)
1600            newType = new typeScalar(typeIndex, size, "unsigned char");
1601          else
1602            newType = new typeScalar(typeIndex, size, "");
1603                  break;
1604          case btFloat:
1605          if (size == 8)
1606              newType = new typeScalar(typeIndex, size, "double");
1607          else
1608              newType = new typeScalar(typeIndex, size, "float");
1609                  break;
1610          case btBCD:
1611          newType = new typeScalar(typeIndex, size, "BCD");
1612                  break;
1613          case btBool:
1614          newType = new typeScalar(typeIndex, size, "bool");
1615                  break;
1616          case btLong:
1617          newType = new typeScalar(typeIndex, size, "long");
1618                  break;
1619          case btULong:
1620          newType = new typeScalar(typeIndex, size, "unsigned long");
1621                  break;
1622          case btCurrency:
1623          newType = new typeScalar(typeIndex, size, "currency");
1624                  break;
1625          case btDate:
1626          newType = new typeScalar(typeIndex, size, "Date");
1627                  break;
1628          case btVariant:
1629          newType = new typeScalar(typeIndex, size, "variant");
1630                  break;
1631          case btComplex:
1632          newType = new typeScalar(typeIndex, size, "complex");
1633                  break;
1634          case btBit:
1635          newType = new typeScalar(typeIndex, size, "bit");
1636                  break;
1637          case btBSTR:
1638          newType = new typeScalar(typeIndex, size, "bstr");
1639                  break;
1640          case btHresult:
1641          newType = new typeScalar(typeIndex, size, "Hresult");
1642                  break;
1643          default:
1644                  fprintf(stderr, "Couldn't parse baseType %d for %d\n", baseType, typeIndex);
1645          assert(0);
1646                  break;
1647    }
1648    if (newType)
1649        addTypeToCollection(newType, mod);
1650    return newType;
1651 }
1652
1653 static Type *getType(HANDLE p, Offset base, int typeIndex, Module *mod) 
1654 {
1655    static unsigned depth = 0;
1656    BOOL result;
1657    Type *foundType = NULL;
1658    typeCollection *collection;
1659    enum SymTagEnum symtag;
1660
1661    if (!typeIndex)
1662        return NULL;
1663
1664    //
1665    // Check if this type has already been created (they're indexed by typeIndex).
1666    // If it has, go ahead and return the existing one.
1667    // If not, then start creating a new type.
1668    //
1669    if (mod)
1670        collection = mod->getModuleTypes();
1671    else
1672            collection = Symtab::stdTypes;
1673    assert(collection);
1674
1675
1676    //
1677    // Check to see if we've already parsed this type
1678    //
1679    foundType = collection->findType(typeIndex);
1680    if (foundType) {
1681        return foundType;
1682    }
1683
1684    //
1685    // Types on Windows are stored as part of a special type of symbol.  TI_GET_SYMTAG 
1686    // Gets the meta information about the type.
1687    //
1688    result = SymGetTypeInfo(p, base, typeIndex, TI_GET_SYMTAG, &symtag);
1689    if (!result) {
1690        depth--;
1691        return NULL;
1692    }
1693    switch (symtag) {
1694        case SymTagBaseType:
1695            foundType = getBaseType(p, base, typeIndex, mod);
1696            break;
1697        case SymTagEnum:
1698            foundType = getEnumType(p, base, typeIndex, mod);
1699            break;
1700        case SymTagFunctionType:
1701            foundType = getFunctionType(p, base, typeIndex, mod);
1702            break;
1703        case SymTagPointerType:
1704            foundType = getPointerType(p, base, typeIndex, mod);
1705            break;
1706        case SymTagArrayType:
1707            foundType = getArrayType(p, base, typeIndex, mod);
1708            break;
1709        case SymTagTypedef:
1710            foundType = getTypedefType(p, base, typeIndex, mod);
1711            break;
1712        case SymTagUDT:
1713            foundType = getUDTType(p, base, typeIndex, mod);
1714            break;
1715        case SymTagFunctionArgType:
1716        case SymTagData:
1717        case SymTagFunction:
1718        case SymTagBaseClass:
1719            foundType = getLayeredType(p, base, typeIndex, mod);
1720            if (foundType)
1721              typeIndex = foundType->getID();
1722            break;
1723        case SymTagThunk:
1724            foundType = NULL;
1725            break;
1726        case SymTagVTableShape:
1727        case SymTagVTable:
1728            break;
1729        default:
1730            fprintf(stderr, "Unknown type %d\n", symtag);
1731            assert(0);
1732            foundType = NULL;
1733            break;
1734    }
1735
1736    return foundType;
1737 }
1738
1739 typedef struct proc_mod_pair {
1740         HANDLE handle;
1741         Symtab *obj;
1742     Offset base_addr;
1743 } proc_mod_pair;
1744
1745 static void findLocalVars(Function *func, proc_mod_pair base) {
1746     Module *mod = func->getModule();
1747     localsStruct locals;
1748     HANDLE p = base.handle;
1749
1750     locals.func = func;
1751     locals.base = base.base_addr;
1752     locals.p = p;
1753
1754         enumLocalVars(func, &locals);
1755     //
1756     // The windows debugging interface allows us to get local variables
1757     // at specific points, which makes it hard to enumerate all locals (as we want).
1758     // Instead we'll get the local variables at the most common points below.
1759     //
1760     //TODO?
1761         //=const std::vector<instPoint*> &points = ifunc->funcEntries();
1762     //=enumLocalVars(func, ifunc->funcEntries(), &locals);
1763     //=enumLocalVars(func, ifunc->funcExits(), &locals);
1764     //=enumLocalVars(func, ifunc->funcCalls(), &locals);
1765     //=enumLocalVars(func, ifunc->funcArbitraryPoints(), &locals);
1766 }
1767
1768 BOOL CALLBACK add_type_info(PSYMBOL_INFO pSymInfo, ULONG SymbolSize, void *info)
1769 {
1770    HANDLE p;
1771    Offset obj_base;
1772    proc_mod_pair *pair;
1773    Symtab *obj;
1774    Type *type;
1775    char *name;
1776    Address addr;
1777
1778    if (!isGlobalSymbol(pSymInfo)) {
1779        //We do local symbols elsewhere
1780        return TRUE;
1781    }
1782
1783    pair = (proc_mod_pair *) info;
1784    p = pair->handle;
1785    obj_base = pair->base_addr;
1786    obj = pair->obj;
1787    name = pSymInfo->Name;
1788    addr = (Address) pSymInfo->Address - obj_base;
1789
1790    std::vector<Module *> mods;
1791    Module *mod;
1792    //TODO?? change later
1793    if(!obj->getAllModules(mods))
1794    {
1795            return true;
1796    }
1797    else
1798            mod = mods[0];
1799    
1800    if (obj->isExec()) {
1801       //When parsing the a.out, sort the type information into specific modules.  This doesn't matter
1802       // for libraries, because there is a 1:1 mapping between modules and objects.
1803       //
1804       //A module is a collection of functions, but doesn't include global data types.  Global variables
1805       // will go into the DEFAULT_MODULE
1806           std::vector<Symbol *> syms;
1807           if(obj->findFuncByEntryOffset(syms, (Offset) pSymInfo->Address))
1808           {
1809                   Symbol *f = syms[0];
1810              //No containing module.  Only insert this into DEFAULT_MODULE
1811           if (strcmp(f->getModule()->fileName().c_str(), "DEFAULT_MODULE"))
1812               return true;
1813       }
1814    }
1815
1816    type = getType(p, obj_base, pSymInfo->TypeIndex, mod);
1817
1818    
1819 //   fprintf(stderr, "[%s:%u] - Variable %s had type %s\n", __FILE__, __LINE__,
1820 //       name, type ? type->getName().c_str() : "{NO TYPE}");
1821    
1822    if (type)
1823    {
1824       Variable *var = NULL;
1825       bool result = obj->findVariableByOffset(var, addr);
1826       if (result) {
1827          var->setType(type);
1828       }
1829       if (name) {
1830          std::string vName = name;
1831          mod->getModuleTypes()->addGlobalVariable(vName, type);
1832       }
1833    }
1834    return TRUE;
1835 }
1836
1837 void Object::parseTypeInfo(Symtab *obj) {
1838     proc_mod_pair pair;
1839     BOOL result;
1840     //
1841     //Parse global variable type information
1842     //
1843
1844     pair.handle = hProc;
1845     pair.obj = obj;
1846     pair.base_addr = getBaseAddress();
1847     
1848     if (!pair.base_addr) {
1849         pair.base_addr = getLoadAddress();
1850     }
1851   
1852    HANDLE mapAddr = mf->base_addr();
1853     result = SymEnumSymbols(hProc, (DWORD64)mapAddr, NULL, 
1854                             add_type_info, &pair);
1855         if (!result){
1856                 printSysError(GetLastError());
1857 //        parsing_printf("SymEnumSymbols was unsuccessful.  Type info may be incomplete\n");
1858     }
1859
1860     //
1861     // Parse local variables and local type information
1862     //
1863     std::vector<Function *> funcs;
1864         obj->getAllFunctions(funcs);
1865     for (unsigned i=0; i < funcs.size(); i++) {
1866         findLocalVars(funcs[i], pair);
1867     }
1868 }
1869
1870 bool AObject::getSegments(vector<Segment> &segs) const
1871 {
1872         for(unsigned int i=0; i<regions_.size(); i++){
1873                 Segment seg;
1874                 seg.data = regions_[i]->getPtrToRawData();
1875                 //seg.loadaddr = regions_[i] -> getDiskOffset();
1876                 seg.loadaddr = regions_[i] -> getRegionAddr();
1877                 seg.size = regions_[i] -> getDiskSize();
1878                 seg.name = regions_[i] -> getRegionName();
1879                 //seg.segFlags = 
1880                 segs.push_back(seg);
1881         }
1882     return true;
1883 }
1884
1885 bool Object::emitDriver(Symtab *obj, string fName, std::vector<Symbol *>&allSymbols, 
1886                                                 unsigned flag) {
1887         emitWin *em = new emitWin((PCHAR)GetMapAddr(), this, err_func_);
1888         return em -> driver(obj, fName);
1889 }