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