Win32BinaryFile.cpp

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2000, The University of Queensland
00003  * Copyright (C) 2001, Sun Microsystems, Inc
00004  * Copyright (C) 2002, Trent Waddington
00005  *
00006  * See the file "LICENSE.TERMS" for information on usage and
00007  * redistribution of this file, and for a DISCLAIMER OF ALL
00008  * WARRANTIES.
00009  *
00010  */
00011 
00012 /* File: Win32BinaryFile.cc
00013  * $Revision: 1.37 $
00014  * Desc: This file contains the implementation of the class Win32BinaryFile.
00015  */
00016 
00017 /* Win32 binary file format.
00018  *  This file implements the class Win32BinaryFile, derived from class
00019  *  BinaryFile. See Win32BinaryFile.h and BinaryFile.h for details.
00020  * 25 Jun 02 - Mike: Added code to find WinMain by finding a call within 5
00021  *              instructions of a call to GetModuleHandleA
00022  * 07 Jul 02 - Mike: Added a LMMH() so code works on big-endian host
00023  * 08 Jul 02 - Mike: Changed algorithm to find main; now looks for ordinary
00024  *               call up to 10 instructions before an indirect call to exit
00025  * 24 Jul 05 - Mike: State machine to recognise main in Borland Builder files
00026  */
00027 
00028 #if defined(_MSC_VER) && _MSC_VER <= 1200
00029 #pragma warning(disable:4786)
00030 #endif
00031 #if defined(_MSC_VER) && _MSC_VER >= 1400
00032 #pragma warning(disable:4996)       // Warnings about e.g. _strdup deprecated in VS 2005
00033 #endif
00034 
00035 #ifdef _WIN32
00036 #include <windows.h>
00037 #ifndef __MINGW32__
00038 namespace dbghelp {
00039 #include <dbghelp.h>
00040 };
00041 #endif
00042 #endif
00043 
00044 #include "BinaryFile.h"
00045 #include "Win32BinaryFile.h"
00046 #include "config.h"
00047 #include <iostream>
00048 #include <sstream>
00049 #include <assert.h>
00050 
00051 extern "C" {
00052     int microX86Dis(void* p);           // From microX86dis.c
00053 }
00054 
00055 
00056 #ifndef IMAGE_SCN_CNT_CODE // Assume that if one is not defined, the rest isn't either.
00057 #define IMAGE_SCN_CNT_CODE               0x00000020
00058 #define IMAGE_SCN_CNT_INITIALIZED_DATA   0x00000040
00059 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080
00060 #define IMAGE_SCN_MEM_READ               0x40000000
00061 #define IMAGE_SCN_MEM_WRITE              0x80000000
00062 #endif
00063 
00064 
00065 namespace {
00066 
00067 // Due to the current rigid design, where BinaryFile holds a C-style array of
00068 // SectionInfo's, we can't extend a subclass of SectionInfo with the data required
00069 // to express the semantics of a PE section. We therefore need this external mapping
00070 // from SectionInfo's to PEObject's, that contain the info we need.
00071 // TODO: Refactor BinaryFile to not expose its private parts in public. Design both
00072 // a protected (for subclasses) and public (for users) interface.
00073 typedef std::map<const class PESectionInfo*, const PEObject*> SectionObjectMap;
00074 
00075 SectionObjectMap s_sectionObjects;
00076 
00077 
00078 // Note that PESectionInfo currently must be the exact same size as
00079 // SectionInfo due to the already mentioned array held by BinaryFile.
00080 class PESectionInfo : public SectionInfo
00081 {
00082     virtual bool isAddressBss(ADDRESS a) const
00083     {
00084         if (a < uNativeAddr || a >= uNativeAddr + uSectionSize) {
00085             return false; // not even within this section
00086         }
00087         if (bBss) {
00088             return true; // obvious
00089         }
00090         if (bReadOnly) {
00091             return false; // R/O BSS makes no sense.
00092         }
00093         // Don't check for bData here. So long as the section has slack at end, that space can contain BSS.
00094         const SectionObjectMap::iterator it = s_sectionObjects.find(this);
00095         assert(it != s_sectionObjects.end());
00096         assert(it->second);
00097         assert(this == it->first);
00098         const PEObject* sectionHeader = it->second;
00099         const bool has_slack = LMMH(sectionHeader->VirtualSize) > LMMH(sectionHeader->PhysicalSize);
00100         if (!has_slack) {
00101             return false; // BSS not possible.
00102         }
00103         if (a >= uNativeAddr + LMMH(sectionHeader->PhysicalSize)) {
00104             return true;
00105         }
00106         return false;
00107     }
00108 };
00109 
00110 // attempt at a compile-time assert for the size requirement.
00111 // If the sizes differs, this statement will try to define a zero-sized array, which is invalid.
00112 typedef char ct_failure[sizeof(SectionInfo) == sizeof(PESectionInfo)];
00113 
00114 }
00115 
00116 
00117 Win32BinaryFile::Win32BinaryFile() : m_pFileName(0), mingw_main(false)
00118 { }
00119 
00120 Win32BinaryFile::~Win32BinaryFile()
00121 {
00122     for (int i=0; i < m_iNumSections; i++) {
00123         if (m_pSections[i].pSectionName)
00124             delete [] m_pSections[i].pSectionName;
00125     }
00126     if (m_pSections) delete [] m_pSections;
00127 }
00128 
00129 bool Win32BinaryFile::Open(const char* sName) {
00130     //return Load(sName) != 0;
00131     return false;
00132 }
00133 
00134 void Win32BinaryFile::Close() {
00135     UnLoad();
00136 }
00137 
00138 std::list<SectionInfo*>& Win32BinaryFile::GetEntryPoints(
00139     const char* pEntry)
00140 {
00141     fprintf(stderr,"really don't know how to implement GetEntryPoints\n");
00142     exit(0);
00143     static std::list<SectionInfo*> l;
00144     return l;
00145 }
00146 
00147 ADDRESS Win32BinaryFile::GetEntryPoint()
00148 {
00149     return (ADDRESS)(LMMH(m_pPEHeader->EntrypointRVA) +
00150                      LMMH(m_pPEHeader->Imagebase));
00151 }
00152 
00153 // This is a bit of a hack, but no more than the rest of Windows :-O  The pattern is to look for an indirect call (FF 15
00154 // opcode) to exit; within 10 instructions before that should be the call to WinMain (with no other calls inbetween).
00155 // This pattern should work for "old style" and "new style" PE executables, as well as console mode PE files.
00156 ADDRESS Win32BinaryFile::GetMainEntryPoint() {
00157     ADDRESS aMain = GetAddressByName ("main", true);
00158     if (aMain != NO_ADDRESS)
00159         return aMain;
00160     aMain = GetAddressByName ("_main", true);       // Example: MinGW
00161     if (aMain != NO_ADDRESS)
00162         return aMain;
00163 
00164     // Start at program entry point
00165     unsigned p = LMMH(m_pPEHeader->EntrypointRVA);
00166     unsigned lim = p + 0x200;
00167     unsigned char op1, op2;
00168     unsigned addr, lastOrdCall = 0;
00169     int gap;                // Number of instructions from the last ordinary call
00170     int borlandState = 0;   // State machine for Borland
00171 
00172     SectionInfo* si = GetSectionInfoByName(".text");
00173     if (si == NULL) si = GetSectionInfoByName("CODE");
00174     assert(si);
00175     unsigned textSize = si->uSectionSize;
00176     if (textSize < 0x200)
00177         lim = p + textSize;
00178 
00179     if (m_pPEHeader->Subsystem == 1)    // native
00180         return LMMH(m_pPEHeader->EntrypointRVA) + LMMH(m_pPEHeader->Imagebase);
00181 
00182     gap = 0xF0000000;   // Large positive number (in case no ordinary calls)
00183     while (p < lim) {
00184         op1 = *(unsigned char*)(p + base);
00185         op2 = *(unsigned char*)(p + base + 1);
00186 //      std::cerr << std::hex << "At " << p << ", ops " << (unsigned)op1 << ", " << (unsigned)op2 << std::dec << "\n";
00187         switch (op1) {
00188             case 0xE8: {
00189                 // An ordinary call; this could be to winmain/main
00190                 lastOrdCall = p;
00191                 gap = 0;
00192                 if (borlandState == 1)
00193                     borlandState++;
00194                 else
00195                     borlandState = 0;
00196                 break;
00197             }
00198             case 0xFF:
00199                 if (op2 == 0x15) {          // Opcode FF 15 is indirect call
00200                     // Get the 4 byte address from the instruction
00201                     addr = LMMH(*(p + base + 2));
00202 //                  const char *c = dlprocptrs[addr].c_str();
00203 //                  printf("Checking %x finding %s\n", addr, c);
00204                     if (dlprocptrs[addr] == "exit") {
00205                         if (gap <= 10) {
00206                             // This is it. The instruction at lastOrdCall is (win)main
00207                             addr = LMMH(*(lastOrdCall + base + 1));
00208                             addr += lastOrdCall + 5;    // Addr is dest of call
00209 //                          printf("*** MAIN AT 0x%x ***\n", addr);
00210                             return addr + LMMH(m_pPEHeader->Imagebase);
00211                         }
00212                     }
00213                 } else
00214                     borlandState = 0;
00215                 break;
00216             case 0xEB:                  // Short relative jump, e.g. Borland
00217                 if (op2 >= 0x80)        // Branch backwards?
00218                     break;              // Yes, just ignore it
00219                 // Otherwise, actually follow the branch. May have to modify this some time...
00220                 p += op2+2;             // +2 for the instruction itself, and op2 for the displacement
00221                 gap++;
00222                 continue;
00223             case 0x6A:
00224                 if (op2 == 0) {         // Push 00
00225                     // Borland pattern: push 0 / call __ExceptInit / pop ecx / push offset mainInfo / push 0
00226                     // Borland state before: 0              1              2            3               4
00227                     if (borlandState == 0)
00228                         borlandState = 1;
00229                     else if (borlandState == 4) {
00230                         // Borland pattern succeeds. p-4 has the offset of mainInfo
00231                         ADDRESS mainInfo = LMMH(*(base + p-4));
00232                         ADDRESS main = readNative4(mainInfo+0x18);      // Address of main is at mainInfo+18
00233                         return main;
00234                     }
00235                 } else
00236                     borlandState = 0;
00237                 break;
00238             case 0x59:                  // Pop ecx
00239                 if (borlandState == 2)
00240                     borlandState = 3;
00241                 else
00242                     borlandState = 0;
00243                 break;
00244             case 0x68:                  // Push 4 byte immediate
00245                 if (borlandState == 3)
00246                     borlandState++;
00247                 else
00248                     borlandState = 0;
00249                 break;
00250             default:
00251                 borlandState = 0;
00252                 break;
00253         }
00254         int size = microX86Dis(p + base);
00255         if (size == 0x40) {
00256             fprintf(stderr, "Warning! Microdisassembler out of step at offset 0x%x\n", p);
00257             size = 1;
00258         }
00259         p += size;
00260         gap++;
00261     }
00262 
00263     // VS.NET release console mode pattern
00264     p = LMMH(m_pPEHeader->EntrypointRVA);
00265     if (*(unsigned char*)(p + base + 0x20) == 0xff && *(unsigned char*)(p + base + 0x21) == 0x15) {
00266         unsigned int desti = LMMH(*(p + base + 0x22));
00267         if (dlprocptrs.find(desti) != dlprocptrs.end() && dlprocptrs[desti] == "GetVersionExA") {
00268             if (*(unsigned char*)(p + base + 0x6d) == 0xff && *(unsigned char*)(p + base + 0x6e) == 0x15) {
00269                 desti = LMMH(*(p + base + 0x6f));
00270                 if (dlprocptrs.find(desti) != dlprocptrs.end() && dlprocptrs[desti] == "GetModuleHandleA") {
00271                     if (*(unsigned char*)(p + base + 0x16e) == 0xe8) {
00272                         unsigned int dest = p + 0x16e + 5 + LMMH(*(p + base + 0x16f));
00273                         return dest + LMMH(m_pPEHeader->Imagebase);
00274                     }
00275                 }
00276             }
00277         }
00278     }
00279 
00280     // For VS.NET, need an old favourite: find a call with three pushes in the first 100 instuctions
00281     int count = 100;
00282     int pushes = 0;
00283     p = LMMH(m_pPEHeader->EntrypointRVA);
00284     while (count > 0) {
00285         count--;
00286         op1 = *(unsigned char*)(p + base);
00287         if (op1 == 0xE8) {          // CALL opcode
00288             if (pushes == 3) {
00289                 // Get the offset
00290                 int off = LMMH(*(p + base + 1));
00291                 unsigned dest = (unsigned)p + 5 + off;
00292                 // Check for a jump there
00293                 op1 = *(unsigned char*)(dest + base);
00294                 if (op1 == 0xE9) {
00295                     // Follow that jump
00296                     off = LMMH(*(dest + base + 1));
00297                     dest = dest + 5 + off;
00298                 }
00299                 return dest + LMMH(m_pPEHeader->Imagebase);
00300             } else
00301                 pushes = 0;         // Assume pushes don't accumulate over calls
00302         }
00303         else if (op1 >= 0x50 && op1 <= 0x57)    // PUSH opcode
00304             pushes++;
00305         else if (op1 == 0xFF) {
00306             // FF 35 is push m[K]
00307             op2 = *(unsigned char*)(p + 1 + base);
00308             if (op2 == 0x35)
00309                 pushes++;
00310         }
00311         else if (op1 == 0xE9) {
00312             // Follow the jump
00313             int off = LMMH(*(p + base + 1));
00314             p += off+5;
00315             continue;
00316         }
00317 
00318 
00319         int size = microX86Dis(p + base);
00320         if (size == 0x40) {
00321             fprintf(stderr, "Warning! Microdisassembler out of step at offset 0x%x\n", p);
00322             size = 1;
00323         }
00324         p += size;
00325         if (p >= textSize)
00326             break;
00327     }
00328 
00329     // mingw pattern
00330     p = LMMH(m_pPEHeader->EntrypointRVA);
00331     bool in_mingw_CRTStartup = false;
00332     unsigned int lastcall = 0, lastlastcall = 0;
00333     while(1) {
00334         op1 = *(unsigned char*)(p + base);
00335         if (op1 == 0xE8) {          // CALL opcode
00336             unsigned int dest = p + 5 + LMMH(*(p + base + 1));
00337             if (in_mingw_CRTStartup) {
00338                 op2 = *(unsigned char*)(dest + base);
00339                 unsigned char op2a = *(unsigned char*)(dest + base + 1);
00340                 unsigned int desti = LMMH(*(dest + base + 2));
00341                 // skip all the call statements until we hit a call to an indirect call to ExitProcess
00342                 // main is the 2nd call before this one
00343                 if (op2 == 0xff && op2a == 0x25 && dlprocptrs.find(desti) != dlprocptrs.end() && dlprocptrs[desti] == "ExitProcess") {
00344                     mingw_main = true;
00345                     return lastlastcall + 5 + LMMH(*(lastlastcall + base + 1)) + LMMH(m_pPEHeader->Imagebase);
00346                 }               
00347                 lastlastcall = lastcall;
00348                 lastcall = p;
00349             } else {
00350                 p = dest;
00351                 in_mingw_CRTStartup = true;
00352                 continue;
00353             }
00354         }
00355 
00356         int size = microX86Dis(p + base);
00357         if (size == 0x40) {
00358             fprintf(stderr, "Warning! Microdisassembler out of step at offset 0x%x\n", p);
00359             size = 1;
00360         }
00361         p += size;
00362         if (p >= textSize)
00363             break;
00364     }
00365 
00366     // Microsoft VisualC 2-6/net runtime
00367     p = LMMH(m_pPEHeader->EntrypointRVA);
00368     bool gotGMHA = false;
00369     while(1) {
00370         op1 = *(unsigned char*)(p + base);
00371         op2 = *(unsigned char*)(p + base + 1);
00372         if (op1 == 0xFF && op2 == 0x15) { // indirect CALL opcode
00373             unsigned int desti = LMMH(*(p + base + 2));
00374             if (dlprocptrs.find(desti) != dlprocptrs.end() && dlprocptrs[desti] == "GetModuleHandleA") {
00375                 gotGMHA = true;
00376             }
00377         }
00378         if (op1 == 0xE8 && gotGMHA) {           // CALL opcode
00379             unsigned int dest = p + 5 + LMMH(*(p + base + 1));
00380             AddSymbol(dest + LMMH(m_pPEHeader->Imagebase), "WinMain");
00381             return dest + LMMH(m_pPEHeader->Imagebase);
00382         }
00383         if (op1 == 0xc3)   // ret ends search
00384             break;
00385 
00386         int size = microX86Dis(p + base);
00387         if (size == 0x40) {
00388             fprintf(stderr, "Warning! Microdisassembler out of step at offset 0x%x\n", p);
00389             size = 1;
00390         }
00391         p += size;
00392         if (p >= textSize)
00393             break;
00394     }
00395     
00396     return NO_ADDRESS;
00397 }
00398 
00399 #if defined(_WIN32) && !defined(__MINGW32__)
00400 BOOL CALLBACK lookforsource(
00401   dbghelp::PSOURCEFILE pSourceFile,
00402   PVOID UserContext
00403 )
00404 {
00405     *(bool*)UserContext = true;
00406     return FALSE;
00407 }
00408 #endif
00409 
00410 bool Win32BinaryFile::RealLoad(const char* sName)
00411 {
00412     m_pFileName = sName;
00413     FILE *fp = fopen(sName,"rb");
00414 
00415     DWord peoffLE, peoff;
00416     fseek(fp, 0x3c, SEEK_SET);
00417     fread(&peoffLE, 4, 1, fp);      // Note: peoffLE will be in Little Endian
00418     peoff = LMMH(peoffLE);
00419 
00420     PEHeader tmphdr;
00421 
00422     fseek(fp, peoff, SEEK_SET);
00423     fread(&tmphdr, sizeof(tmphdr), 1, fp);
00424     // Note: all tmphdr fields will be little endian
00425 
00426     base = (char *)malloc(LMMH(tmphdr.ImageSize));
00427 
00428     if (!base) {
00429         fprintf(stderr,"Cannot allocate memory for copy of image\n");
00430         return false;
00431     }
00432 
00433     fseek(fp, 0, SEEK_SET);
00434 
00435     fread(base, LMMH(tmphdr.HeaderSize), 1, fp);
00436 
00437     m_pHeader = (Header *)base;
00438     if (m_pHeader->sigLo!='M' || m_pHeader->sigHi!='Z') {
00439         fprintf(stderr,"error loading file %s, bad magic\n", sName);
00440         return false;
00441     }
00442 
00443     m_pPEHeader = (PEHeader *)(base+peoff);
00444     if (m_pPEHeader->sigLo!='P' || m_pPEHeader->sigHi!='E') {
00445         fprintf(stderr,"error loading file %s, bad PE magic\n", sName);
00446         return false;
00447     }
00448 
00449 //printf("Image Base %08X, real base %p\n", LMMH(m_pPEHeader->Imagebase), base);
00450 
00451     const PEObject *o = (PEObject *)(((char *)m_pPEHeader) + LH(&m_pPEHeader->NtHdrSize) + 24);
00452     m_iNumSections = LH(&m_pPEHeader->numObjects);
00453     m_pSections = new PESectionInfo[m_iNumSections];
00454 //  SectionInfo *reloc = NULL;
00455     for (int i=0; i<m_iNumSections; i++, o++) {
00456         SectionInfo& sect = m_pSections[i];
00457         //  printf("%.8s RVA=%08X Offset=%08X size=%08X\n", (char*)o->ObjectName, LMMH(o->RVA), LMMH(o->PhysicalOffset),
00458         //    LMMH(o->VirtualSize));
00459         sect.pSectionName = new char[9];
00460         strncpy(sect.pSectionName, o->ObjectName, 8);
00461 //      if (!strcmp(sect.pSectionName, ".reloc"))
00462 //          reloc = &sect;
00463         sect.uNativeAddr=(ADDRESS)(LMMH(o->RVA) + LMMH(m_pPEHeader->Imagebase));
00464         sect.uHostAddr=(ADDRESS)(LMMH(o->RVA) + base);
00465         sect.uSectionSize=LMMH(o->VirtualSize);
00466         DWord Flags = LMMH(o->Flags);
00467         sect.bBss      = (Flags&IMAGE_SCN_CNT_UNINITIALIZED_DATA)?1:0;
00468         sect.bCode     = (Flags&IMAGE_SCN_CNT_CODE)?1:0;
00469         sect.bData     = (Flags&IMAGE_SCN_CNT_INITIALIZED_DATA)?1:0;
00470         sect.bReadOnly = (Flags&IMAGE_SCN_MEM_WRITE)?0:1;
00471         // TODO: Check for unreadable sections (!IMAGE_SCN_MEM_READ)?
00472         fseek(fp, LMMH(o->PhysicalOffset), SEEK_SET);
00473         memset(base + LMMH(o->RVA), 0, LMMH(o->VirtualSize));
00474         fread(base + LMMH(o->RVA), LMMH(o->PhysicalSize), 1, fp);
00475         s_sectionObjects[static_cast<const PESectionInfo*>(&sect)] = o;
00476     }
00477 
00478     // Add the Import Address Table entries to the symbol table
00479     PEImportDtor* id = (PEImportDtor*) (LMMH(m_pPEHeader->ImportTableRVA) + base);
00480     if (m_pPEHeader->ImportTableRVA) {          // If any import table entry exists
00481         while (id->name != 0) {
00482             char* dllName = LMMH(id->name) + base;
00483             unsigned thunk = id->originalFirstThunk ? id->originalFirstThunk : id->firstThunk;
00484             unsigned* iat = (unsigned*)(LMMH(thunk) + base);
00485             unsigned iatEntry = LMMH(*iat);
00486             ADDRESS paddr = LMMH(id->firstThunk) + LMMH(m_pPEHeader->Imagebase);
00487             while (iatEntry) {
00488                 if (iatEntry >> 31) {
00489                     // This is an ordinal number (stupid idea)
00490                     std::ostringstream ost;
00491                     std::string nodots(dllName);
00492                     int len = nodots.size();
00493                     for (int j=0; j < len; j++)
00494                         if (nodots[j] == '.')
00495                             nodots[j] = '_';    // Dots can't be in identifiers
00496                     ost << nodots << "_" << (iatEntry & 0x7FFFFFFF);                
00497                     dlprocptrs[paddr] = ost.str();
00498                     // printf("Added symbol %s value %x\n", ost.str().c_str(), paddr);
00499                 } else {
00500                     // Normal case (IMAGE_IMPORT_BY_NAME). Skip the useless hint (2 bytes)
00501                     std::string name((const char*)(iatEntry+2+base));
00502                     dlprocptrs[paddr] = name;
00503                     if ((unsigned)paddr != (unsigned)iat - (unsigned)base + LMMH(m_pPEHeader->Imagebase))
00504                         dlprocptrs[(unsigned)iat - (unsigned)base + LMMH(m_pPEHeader->Imagebase)]
00505                             = std::string("old_") + name; // add both possibilities
00506                     // printf("Added symbol %s value %x\n", name.c_str(), paddr);
00507                     // printf("Also added old_%s value %x\n", name.c_str(), (int)iat - (int)base +
00508                     //      LMMH(m_pPEHeader->Imagebase));
00509                 }
00510                 iat++;
00511                 iatEntry = LMMH(*iat);
00512                 paddr+=4;
00513             }
00514             id++;
00515         }
00516     }
00517 
00518     // Was hoping that _main or main would turn up here for Borland console mode programs. No such luck.
00519     // I think IDA Pro must find it by a combination of FLIRT and some pattern matching
00520     //PEExportDtor* eid = (PEExportDtor*)
00521     //  (LMMH(m_pPEHeader->ExportTableRVA) + base);
00522 
00523 
00524     // Give the entry point a symbol
00525     ADDRESS entry = GetMainEntryPoint();
00526     if (entry != NO_ADDRESS) {
00527         std::map<ADDRESS, std::string>::iterator it = dlprocptrs.find(entry);
00528         if (it == dlprocptrs.end())
00529             dlprocptrs[entry] = "main";
00530     }
00531 
00532     // Give a name to any jumps you find to these import entries
00533     // NOTE: VERY early MSVC specific!! Temporary till we can think of a better way.
00534     ADDRESS start = GetEntryPoint();
00535     findJumps(start);
00536 
00537     fclose(fp);
00538 
00539 #if defined(_WIN32) && !defined(__MINGW32__)
00540     // attempt to load symbols for the exe or dll
00541 
00542     DWORD  error;
00543     HANDLE hProcess;
00544 
00545     hProcess = GetCurrentProcess();
00546     // hProcess = (HANDLE)processId;
00547 
00548     dbghelp::SymSetOptions(SYMOPT_LOAD_LINES);
00549 
00550     if (dbghelp::SymInitialize(hProcess, NULL, FALSE))
00551     {
00552         // SymInitialize returned success
00553     }
00554     else
00555     {
00556         // SymInitialize failed
00557         error = GetLastError();
00558         printf("SymInitialize returned error : %d\n", error);
00559         return true;
00560     }
00561 
00562     DWORD64 dwBaseAddr = 0;
00563 
00564     if (dwBaseAddr = dbghelp::SymLoadModule64(hProcess, NULL, (PSTR)sName, NULL, dwBaseAddr, 0))
00565     {
00566         assert(dwBaseAddr == m_pPEHeader->Imagebase);
00567         bool found = false;
00568         dbghelp::SymEnumSourceFiles(hProcess, dwBaseAddr,  0, lookforsource, &found);
00569         haveDebugInfo = found;
00570     }
00571     else
00572     {
00573         // SymLoadModule64 failed
00574         error = GetLastError();
00575         printf("SymLoadModule64 returned error : %d\n", error);
00576         return true;
00577     }
00578 #endif
00579 
00580     return true;
00581 }
00582 
00583 // Used above for a hack to find jump instructions pointing to IATs.
00584 // Heuristic: start just before the "start" entry point looking for FF 25 opcodes followed by a pointer to an import
00585 // entry.  E.g. FF 25 58 44 40 00  where 00404458 is the IAT for _ftol.
00586 // Note: some are on 0x10 byte boundaries, some on 2 byte boundaries (6 byte jumps packed), and there are often up to
00587 // 0x30 bytes of statically linked library code (e.g. _atexit, __onexit) with sometimes two static libs in a row.
00588 // So keep going until there is about 0x60 bytes with no match.
00589 // Note: slight chance of coming across a misaligned match; probability is about 1/65536 times dozens in 2^32 ~= 10^-13
00590 void Win32BinaryFile::findJumps(ADDRESS curr) {
00591     int cnt = 0;            // Count of bytes with no match
00592     SectionInfo* sec = GetSectionInfoByName(".text");
00593     if (sec == NULL) sec = GetSectionInfoByName("CODE");
00594     assert(sec);
00595     // Add to native addr to get host:
00596     int delta = sec->uHostAddr - sec->uNativeAddr;
00597     while (cnt < 0x60) {    // Max of 0x60 bytes without a match
00598         curr -= 2;          // Has to be on 2-byte boundary
00599         cnt += 2;
00600         if (LH(delta+curr) != 0xFF + (0x25<<8)) continue;
00601         ADDRESS operand = LMMH2(delta+curr+2);
00602         std::map<ADDRESS, std::string>::iterator it;
00603         it = dlprocptrs.find(operand);
00604         if (it == dlprocptrs.end()) continue;
00605         std::string sym = it->second;
00606         dlprocptrs[operand] = "__imp_" + sym;
00607         dlprocptrs[curr] = sym;      // Add new entry
00608         // std::cerr << "Added " << sym << " at 0x" << std::hex << curr << "\n";
00609         curr -= 4;                  // Next match is at least 4+2 bytes away
00610         cnt = 0;
00611     }
00612 }
00613 
00614 // Clean up and unload the binary image
00615 void Win32BinaryFile::UnLoad()
00616 {
00617 } 
00618 
00619 bool Win32BinaryFile::PostLoad(void* handle)
00620 {
00621     return false;
00622 }
00623 
00624 #if defined(_WIN32) && !defined(__MINGW32__)
00625 
00626 char *SymTagEnums[] = { "SymTagNull",
00627    "SymTagExe",
00628    "SymTagCompiland",
00629    "SymTagCompilandDetails",
00630    "SymTagCompilandEnv",
00631    "SymTagFunction",
00632    "SymTagBlock",
00633    "SymTagData",
00634    "SymTagAnnotation",
00635    "SymTagLabel",
00636    "SymTagPublicSymbol",
00637    "SymTagUDT",
00638    "SymTagEnum",
00639    "SymTagFunctionType",
00640    "SymTagPointerType",
00641    "SymTagArrayType", 
00642    "SymTagBaseType", 
00643    "SymTagTypedef", 
00644    "SymTagBaseClass",
00645    "SymTagFriend",
00646    "SymTagFunctionArgType", 
00647    "SymTagFuncDebugStart", 
00648    "SymTagFuncDebugEnd",
00649    "SymTagUsingNamespace", 
00650    "SymTagVTableShape",
00651    "SymTagVTable",
00652    "SymTagCustom",
00653    "SymTagThunk",
00654    "SymTagCustomType",
00655    "SymTagManagedType",
00656    "SymTagDimension"
00657 };
00658 
00659 enum SymTagEnum
00660 {
00661    SymTagNull,
00662    SymTagExe,
00663    SymTagCompiland,
00664    SymTagCompilandDetails,
00665    SymTagCompilandEnv,
00666    SymTagFunction,
00667    SymTagBlock,
00668    SymTagData,
00669    SymTagAnnotation,
00670    SymTagLabel,
00671    SymTagPublicSymbol,
00672    SymTagUDT,
00673    SymTagEnum,
00674    SymTagFunctionType,
00675    SymTagPointerType,
00676    SymTagArrayType, 
00677    SymTagBaseType, 
00678    SymTagTypedef, 
00679    SymTagBaseClass,
00680    SymTagFriend,
00681    SymTagFunctionArgType, 
00682    SymTagFuncDebugStart, 
00683    SymTagFuncDebugEnd,
00684    SymTagUsingNamespace, 
00685    SymTagVTableShape,
00686    SymTagVTable,
00687    SymTagCustom,
00688    SymTagThunk,
00689    SymTagCustomType,
00690    SymTagManagedType,
00691    SymTagDimension
00692 };
00693 
00694 char *basicTypes[] = 
00695   {
00696     "notype",
00697     "void",
00698     "char",
00699     "WCHAR",
00700     "??",
00701     "??",
00702     "int",
00703     "unsigned int",
00704     "float",
00705     "bcd",
00706     "bool",
00707     "??",
00708     "??",
00709     "long"
00710     "unsigned long",
00711   };
00712 
00713 void printType(DWORD index, DWORD64 ImageBase)
00714 {
00715     HANDLE hProcess = GetCurrentProcess();
00716 
00717     int got;
00718     WCHAR *name;
00719     got = dbghelp::SymGetTypeInfo(hProcess, ImageBase, index, dbghelp::TI_GET_SYMNAME, &name);
00720     if (got) {
00721         char nameA[1024];
00722         WideCharToMultiByte(CP_ACP,0,name,-1,nameA,sizeof(nameA),0,NULL);
00723         std::cout << nameA;
00724         return;
00725     }
00726 
00727     DWORD d;
00728     got = dbghelp::SymGetTypeInfo(hProcess, ImageBase, index, dbghelp::TI_GET_SYMTAG, &d);
00729     assert(got);
00730 
00731     switch(d) {
00732         case SymTagPointerType:
00733             {
00734                 got = dbghelp::SymGetTypeInfo(hProcess, ImageBase, index, dbghelp::TI_GET_TYPE, &d);
00735                 assert(got);
00736                 printType(d, ImageBase);
00737                 std::cout << "*";
00738             }
00739             break;
00740         case SymTagBaseType:
00741             got = dbghelp::SymGetTypeInfo(hProcess, ImageBase, index, dbghelp::TI_GET_BASETYPE, &d);
00742             assert(got);
00743             std::cout << basicTypes[d];
00744             break;
00745         default:
00746             std::cerr << "unhandled symtag " << SymTagEnums[d] << "\n";
00747             assert(false);
00748     }
00749 
00750 }
00751 
00752 BOOL CALLBACK printem(
00753   dbghelp::PSYMBOL_INFO pSymInfo,
00754   ULONG SymbolSize,
00755   PVOID UserContext
00756 )
00757 {
00758     HANDLE hProcess = GetCurrentProcess();
00759     printType(pSymInfo->TypeIndex, pSymInfo->ModBase);
00760     std::cout << " " << pSymInfo->Name << " flags: ";
00761     if (pSymInfo->Flags & SYMFLAG_VALUEPRESENT)
00762         std::cout << "value present, ";
00763     if (pSymInfo->Flags & SYMFLAG_REGISTER)
00764         std::cout << "register, ";
00765     if (pSymInfo->Flags & SYMFLAG_REGREL)
00766         std::cout << "regrel, ";
00767     if (pSymInfo->Flags & SYMFLAG_FRAMEREL)
00768         std::cout << "framerel, ";
00769     if (pSymInfo->Flags & SYMFLAG_PARAMETER)
00770         std::cout << "parameter, ";
00771     if (pSymInfo->Flags & SYMFLAG_LOCAL)
00772         std::cout << "local, ";
00773     if (pSymInfo->Flags & SYMFLAG_CONSTANT)
00774         std::cout << "constant, ";
00775     if (pSymInfo->Flags & SYMFLAG_EXPORT)
00776         std::cout << "export, ";
00777     if (pSymInfo->Flags & SYMFLAG_FORWARDER)
00778         std::cout << "forwarder, ";
00779     if (pSymInfo->Flags & SYMFLAG_FUNCTION)
00780         std::cout << "function, ";
00781     if (pSymInfo->Flags & SYMFLAG_VIRTUAL)
00782         std::cout << "virtual, ";
00783     if (pSymInfo->Flags & SYMFLAG_THUNK)
00784         std::cout << "thunk, ";
00785     if (pSymInfo->Flags & SYMFLAG_TLSREL)
00786         std::cout << "tlsrel, ";
00787     std::cout << "\n";
00788     std::cout << "register: " << pSymInfo->Register << " address: " << (int)pSymInfo->Address << "\n";
00789     return TRUE;
00790 }
00791 #endif
00792 
00793 const char* Win32BinaryFile::SymbolByAddress(ADDRESS dwAddr)
00794 {
00795     if (m_pPEHeader->Subsystem == 1 &&              // native
00796             LMMH(m_pPEHeader->EntrypointRVA) + LMMH(m_pPEHeader->Imagebase) == dwAddr)
00797         return "DriverEntry";
00798 
00799     if (IsMinGWsAllocStack(dwAddr))
00800         return "__mingw_allocstack";
00801     if (IsMinGWsFrameInit(dwAddr))
00802         return "__mingw_frame_init";
00803     if (IsMinGWsFrameEnd(dwAddr))
00804         return "__mingw_frame_end";
00805     if (IsMinGWsCleanupSetup(dwAddr))
00806         return "__mingw_cleanup_setup";
00807     if (IsMinGWsMalloc(dwAddr))
00808         return "malloc";
00809 
00810 #if defined(_WIN32) && !defined(__MINGW32__)
00811     HANDLE hProcess = GetCurrentProcess();
00812     dbghelp::SYMBOL_INFO *sym = (dbghelp::SYMBOL_INFO *)malloc(sizeof(dbghelp::SYMBOL_INFO) + 1000);
00813     sym->SizeOfStruct = sizeof(*sym);
00814     sym->MaxNameLen = 1000;
00815     sym->Name[0] = 0;
00816     BOOL got = dbghelp::SymFromAddr(hProcess, dwAddr, 0, sym);
00817     if (*sym->Name) {
00818         char *n = strdup(sym->Name);
00819 #if 0
00820         std::cout << "found symbol " << n << " for address " << dwAddr << "\n";
00821         std::cout << "typeindex: " << sym->TypeIndex << "\n";
00822         DWORD d = 0;
00823         got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, sym->TypeIndex, dbghelp::TI_GET_SYMTAG, &d);
00824         std::cout << "symtag: " << d << "\n";
00825         got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, sym->TypeIndex, dbghelp::TI_GET_CALLING_CONVENTION, &d);
00826         std::cout << "calling convention: " << d << "\n";
00827         DWORD my_typeid;
00828         got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, sym->TypeIndex, dbghelp::TI_GET_TYPEID, &my_typeid);
00829         std::cout << "typeid: " << my_typeid << "\n";
00830         got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, my_typeid, dbghelp::TI_GET_SYMTAG, &d);
00831         std::cout << "symtag: " << d << " ";
00832         got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, my_typeid, dbghelp::TI_GET_BASETYPE, &d);
00833         std::cout << "basetype: " << d << " ";      
00834         got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, my_typeid, dbghelp::TI_GET_TYPE, &d);
00835         std::cout << "type: " << d << "\n";     
00836         DWORD count = 0;
00837         got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, sym->TypeIndex, dbghelp::TI_GET_CHILDRENCOUNT, &count);
00838         std::cout << "num children: " << count << "\n";
00839         int FindChildrenSize = sizeof(dbghelp::TI_FINDCHILDREN_PARAMS) + count*sizeof(ULONG);
00840         dbghelp::TI_FINDCHILDREN_PARAMS* pFC = (dbghelp::TI_FINDCHILDREN_PARAMS*)malloc( FindChildrenSize );
00841         memset( pFC, 0, FindChildrenSize );
00842         pFC->Count = count;
00843         got = SymGetTypeInfo( hProcess, m_pPEHeader->Imagebase, sym->TypeIndex, dbghelp::TI_FINDCHILDREN, pFC );
00844         for (int i = 0; i < count; i++) {
00845             got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, pFC->ChildId[i], dbghelp::TI_GET_TYPEID, &my_typeid);
00846             std::cout << "  child: " << pFC->ChildId[i] << " typeid: " << my_typeid << " ";
00847             got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, my_typeid, dbghelp::TI_GET_SYMTAG, &d);
00848             std::cout << "symtag: " << d << " ";
00849             got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, my_typeid, dbghelp::TI_GET_BASETYPE, &d);
00850             std::cout << "basetype: " << d << " ";
00851             got = dbghelp::SymGetTypeInfo(hProcess, m_pPEHeader->Imagebase, my_typeid, dbghelp::TI_GET_TYPE, &d);
00852             std::cout << "type: " << d << "\n";     
00853         }
00854         // locals and params
00855         dbghelp::IMAGEHLP_STACK_FRAME stack;
00856         stack.InstructionOffset = dwAddr;
00857         dbghelp::SymSetContext(hProcess, &stack, 0);
00858         dbghelp::SymEnumSymbols(hProcess, 0, NULL, printem, 0);
00859 #endif
00860         free(sym);
00861         return n;
00862     } else if (IsJumpToAnotherAddr(dwAddr) != NO_ADDRESS)
00863         return SymbolByAddress(IsJumpToAnotherAddr(dwAddr));
00864 #endif
00865 
00866     std::map<ADDRESS, std::string>::iterator it = dlprocptrs.find(dwAddr);
00867     if (it == dlprocptrs.end())
00868         return 0;
00869     return (char*) it->second.c_str();
00870 }
00871 
00872 ADDRESS Win32BinaryFile::GetAddressByName(const char* pName,
00873     bool bNoTypeOK /* = false */) {
00874     // This is "looking up the wrong way" and hopefully is uncommon.  Use linear search
00875     std::map<ADDRESS, std::string>::iterator it = dlprocptrs.begin();
00876     while (it != dlprocptrs.end()) {
00877         // std::cerr << "Symbol: " << it->second.c_str() << " at 0x" << std::hex << it->first << "\n";
00878         if (strcmp(it->second.c_str(), pName) == 0)
00879             return it->first;
00880         it++;
00881     }
00882     return NO_ADDRESS;
00883 }
00884 
00885 void Win32BinaryFile::AddSymbol(ADDRESS uNative, const char *pName)
00886 {
00887     dlprocptrs[uNative] = pName;
00888 }
00889 
00890 bool Win32BinaryFile::DisplayDetails(const char* fileName, FILE* f
00891      /* = stdout */)
00892 {
00893     return false;
00894 }
00895 
00896 int Win32BinaryFile::win32Read2(short* ps) const {
00897     unsigned char* p = (unsigned char*)ps;
00898     // Little endian
00899     int n = (int)(p[0] + (p[1] << 8));
00900     return n;
00901 }
00902 
00903 int Win32BinaryFile::win32Read4(int* pi) const{
00904     short* p = (short*)pi;
00905     int n1 = win32Read2(p);
00906     int n2 = win32Read2(p+1);
00907     int n = (int) (n1 | (n2 << 16));
00908     return n;
00909 }
00910 
00911 // Read 2 bytes from given native address
00912 int Win32BinaryFile::readNative1(ADDRESS nat) {
00913     PSectionInfo si = GetSectionInfoByAddr(nat);
00914     if (si == 0)
00915         return -1;
00916     ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
00917     return *(char*)host;
00918 }
00919 
00920 // Read 2 bytes from given native address
00921 int Win32BinaryFile::readNative2(ADDRESS nat) {
00922     PSectionInfo si = GetSectionInfoByAddr(nat);
00923     if (si == 0) return 0;
00924     ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
00925     int n = win32Read2((short*)host);
00926     return n;
00927 }
00928 
00929 // Read 4 bytes from given native address
00930 int Win32BinaryFile::readNative4(ADDRESS nat) {
00931     PSectionInfo si = GetSectionInfoByAddr(nat);
00932     if (si == 0) return 0;
00933     ADDRESS host = si->uHostAddr - si->uNativeAddr + nat;
00934     int n = win32Read4((int*)host);
00935     return n;
00936 }
00937 
00938 // Read 8 bytes from given native address
00939 QWord Win32BinaryFile::readNative8(ADDRESS nat) {
00940     int raw[2];
00941 #ifdef WORDS_BIGENDIAN      // This tests the host machine
00942     // Source and host are different endianness
00943     raw[1] = readNative4(nat);
00944     raw[0] = readNative4(nat+4);
00945 #else
00946     // Source and host are same endianness
00947     raw[0] = readNative4(nat);
00948     raw[1] = readNative4(nat+4);
00949 #endif
00950     return *(QWord*)raw;
00951 }
00952 
00953 // Read 4 bytes as a float
00954 float Win32BinaryFile::readNativeFloat4(ADDRESS nat) {
00955     int raw = readNative4(nat);
00956     // Ugh! gcc says that reinterpreting from int to float is invalid!!
00957     //return reinterpret_cast<float>(raw);      // Note: cast, not convert!!
00958     return *(float*)&raw;                       // Note: cast, not convert
00959 }
00960 
00961 // Read 8 bytes as a float
00962 double Win32BinaryFile::readNativeFloat8(ADDRESS nat) {
00963     int raw[2];
00964 #ifdef WORDS_BIGENDIAN      // This tests the host machine
00965     // Source and host are different endianness
00966     raw[1] = readNative4(nat);
00967     raw[0] = readNative4(nat+4);
00968 #else
00969     // Source and host are same endianness
00970     raw[0] = readNative4(nat);
00971     raw[1] = readNative4(nat+4);
00972 #endif
00973     //return reinterpret_cast<double>(*raw);    // Note: cast, not convert!!
00974     return *(double*)raw;
00975 }
00976 
00977 bool Win32BinaryFile::IsDynamicLinkedProcPointer(ADDRESS uNative)
00978 {
00979     if (dlprocptrs.find(uNative) != dlprocptrs.end())
00980         return true;
00981     return false;
00982 }
00983 
00984 bool Win32BinaryFile::IsStaticLinkedLibProc(ADDRESS uNative)
00985 {
00986 #if defined(_WIN32) && !defined(__MINGW32__)
00987     HANDLE hProcess = GetCurrentProcess();
00988     dbghelp::IMAGEHLP_LINE64 line;
00989     line.SizeOfStruct = sizeof(line);   
00990     line.FileName = NULL;
00991     dbghelp::SymGetLineFromAddr64(hProcess, uNative, 0, &line);
00992     if (haveDebugInfo && line.FileName == NULL || line.FileName && *line.FileName == 'f')
00993         return true;
00994 #endif
00995 
00996     if (IsMinGWsAllocStack(uNative) || IsMinGWsFrameInit(uNative) || IsMinGWsFrameEnd(uNative) ||
00997             IsMinGWsCleanupSetup(uNative) || IsMinGWsMalloc(uNative)) {
00998         return true;
00999     }
01000 
01001     return false;
01002 }
01003 
01004 bool Win32BinaryFile::IsMinGWsAllocStack(ADDRESS uNative)
01005 {
01006     if (mingw_main) {
01007         PSectionInfo si = GetSectionInfoByAddr(uNative);
01008         if (si) {
01009             ADDRESS host = si->uHostAddr - si->uNativeAddr + uNative;
01010             unsigned char pat[] = 
01011                 { 0x51, 0x89, 0xE1, 0x83, 0xC1, 0x08, 0x3D, 0x00,
01012                   0x10, 0x00, 0x00, 0x72, 0x10, 0x81, 0xE9, 0x00,
01013                   0x10, 0x00, 0x00, 0x83, 0x09, 0x00, 0x2D, 0x00,
01014                   0x10, 0x00, 0x00, 0xEB, 0xE9, 0x29, 0xC1, 0x83,
01015                   0x09, 0x00, 0x89, 0xE0, 0x89, 0xCC, 0x8B, 0x08,
01016                   0x8B, 0x40, 0x04, 0xFF, 0xE0  };
01017             if (memcmp((void*)host, pat, sizeof(pat)) == 0) {
01018                 return true;
01019             }
01020         }
01021     }
01022     return false;
01023 }
01024 
01025 bool Win32BinaryFile::IsMinGWsFrameInit(ADDRESS uNative)
01026 {
01027     if (mingw_main) {
01028         PSectionInfo si = GetSectionInfoByAddr(uNative);
01029         if (si) {
01030             ADDRESS host = si->uHostAddr - si->uNativeAddr + uNative;
01031             unsigned char pat1[] = 
01032                 { 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x18, 0x89, 0x7D,
01033                   0xFC, 0x8B, 0x7D, 0x08, 0x89, 0x5D, 0xF4, 0x89,
01034                   0x75, 0xF8 };
01035             if (memcmp((void*)host, pat1, sizeof(pat1)) == 0) {
01036                 unsigned char pat2[] = 
01037                     { 0x85, 0xD2, 0x74, 0x24, 0x8B, 0x42, 0x2C, 0x85,
01038                       0xC0, 0x78, 0x3D, 0x8B, 0x42, 0x2C, 0x85, 0xC0,
01039                       0x75, 0x56, 0x8B, 0x42, 0x28, 0x89, 0x07, 0x89,
01040                       0x7A, 0x28, 0x8B, 0x5D, 0xF4, 0x8B, 0x75, 0xF8,
01041                       0x8B, 0x7D, 0xFC, 0x89, 0xEC, 0x5D, 0xC3
01042 
01043                     };
01044                 if (memcmp((void*)(host + sizeof(pat1) + 6), pat2, sizeof(pat2)) == 0) {
01045                     return true;
01046                 }
01047             }
01048         }
01049     }
01050     return false;
01051 }
01052 
01053 bool Win32BinaryFile::IsMinGWsFrameEnd(ADDRESS uNative)
01054 {
01055     if (mingw_main) {
01056         PSectionInfo si = GetSectionInfoByAddr(uNative);
01057         if (si) {
01058             ADDRESS host = si->uHostAddr - si->uNativeAddr + uNative;
01059             unsigned char pat1[] = 
01060                 { 0x55, 0x89, 0xE5, 0x53, 0x83, 0xEC, 0x14, 0x8B, 0x45, 0x08, 0x8B, 0x18 };
01061             if (memcmp((void*)host, pat1, sizeof(pat1)) == 0) {
01062                 unsigned char pat2[] = 
01063                     { 0x85, 0xC0, 0x74, 0x1B, 0x8B, 0x48, 0x2C, 0x85, 0xC9, 0x78, 0x34, 0x8B,
01064                       0x50, 0x2C, 0x85, 0xD2, 0x75, 0x4D, 0x89, 0x58, 0x28, 0x8B, 0x5D, 0xFC,
01065                       0xC9, 0xC3
01066                     };
01067                 if (memcmp((void*)(host + sizeof(pat1) + 5), pat2, sizeof(pat2)) == 0) {
01068                     return true;
01069                 }
01070             }
01071         }
01072     }
01073     return false;
01074 }
01075 
01076 bool Win32BinaryFile::IsMinGWsCleanupSetup(ADDRESS uNative)
01077 {
01078     if (mingw_main) {
01079         PSectionInfo si = GetSectionInfoByAddr(uNative);
01080         if (si) {
01081             ADDRESS host = si->uHostAddr - si->uNativeAddr + uNative;
01082             unsigned char pat1[] = 
01083                 { 0x55, 0x89, 0xE5, 0x53, 0x83, 0xEC, 0x04 };
01084             if (memcmp((void*)host, pat1, sizeof(pat1)) == 0) {
01085                 unsigned char pat2[] = 
01086                     { 0x85, 0xDB, 0x75, 0x35 };
01087                 if (memcmp((void*)(host + sizeof(pat1) + 6), pat2, sizeof(pat2)) == 0) {
01088                     unsigned char pat3[] = 
01089                         { 0x83, 0xF8, 0xFF, 0x74, 0x24, 0x85, 0xC0, 0x89, 0xC3, 0x74, 0x0E,
01090                           0x8D, 0x74, 0x26, 0x00 };
01091                     if (memcmp((void*)(host + sizeof(pat1) + 6 + sizeof(pat2) + 16), pat3, sizeof(pat3)) == 0) {
01092                         return true;
01093                     }
01094                 }
01095             }
01096         }
01097     }
01098     return false;
01099 }
01100 
01101 bool Win32BinaryFile::IsMinGWsMalloc(ADDRESS uNative)
01102 {
01103     if (mingw_main) {
01104         PSectionInfo si = GetSectionInfoByAddr(uNative);
01105         if (si) {
01106             ADDRESS host = si->uHostAddr - si->uNativeAddr + uNative;
01107             unsigned char pat1[] = 
01108                 { 0x55, 0x89, 0xE5, 0x8D, 0x45, 0xF4, 0x83, 0xEC, 0x58, 0x89, 0x45, 0xE0, 0x8D, 0x45, 0xC0, 0x89,
01109                   0x04, 0x24, 0x89, 0x5D, 0xF4, 0x89, 0x75, 0xF8, 0x89, 0x7D, 0xFC };
01110             if (memcmp((void*)host, pat1, sizeof(pat1)) == 0) {
01111                 unsigned char pat2[] = 
01112                     { 0x89, 0x65, 0xE8 };
01113                 if (memcmp((void*)(host + sizeof(pat1) + 0x15), pat2, sizeof(pat2)) == 0) {
01114                     return true;
01115                 }
01116             }
01117         }
01118     }
01119     return false;
01120 }
01121 
01122 ADDRESS Win32BinaryFile::IsJumpToAnotherAddr(ADDRESS uNative)
01123 {
01124     if ((readNative1(uNative) & 0xff) != 0xe9)
01125         return NO_ADDRESS;
01126     return readNative4(uNative+1) + uNative + 5;
01127 }
01128 
01129 const char *Win32BinaryFile::GetDynamicProcName(ADDRESS uNative)
01130 {
01131     return dlprocptrs[uNative].c_str();
01132 }
01133 
01134 LOAD_FMT Win32BinaryFile::GetFormat() const
01135 {
01136     return LOADFMT_PE;
01137 }
01138 
01139 MACHINE Win32BinaryFile::GetMachine() const
01140 {
01141     return MACHINE_PENTIUM;
01142 }
01143 
01144 bool Win32BinaryFile::isLibrary() const
01145 {
01146     return ( (m_pPEHeader->Flags & 0x2000) != 0 );
01147 }
01148 
01149 ADDRESS Win32BinaryFile::getImageBase()
01150 {
01151     return m_pPEHeader->Imagebase;
01152 }
01153 
01154 size_t Win32BinaryFile::getImageSize()
01155 {
01156     return m_pPEHeader->ImageSize;
01157 }
01158 
01159 std::list<const char *> Win32BinaryFile::getDependencyList()
01160 {
01161     return std::list<const char *>(); /* FIXME */
01162 }
01163 
01164 DWord Win32BinaryFile::getDelta() {
01165     // Stupid function anyway: delta depends on section
01166     // This should work for the header only
01167     //  return (DWord)base - LMMH(m_pPEHeader->Imagebase); 
01168     return (DWord)base - (DWord)m_pPEHeader->Imagebase; 
01169 }
01170 
01171 // This function is called via dlopen/dlsym; it returns a new BinaryFile derived concrete object. After this object is
01172 // returned, the virtual function call mechanism will call the rest of the code in this library.  It needs to be C
01173 // linkage so that it its name is not mangled
01174 extern "C" {
01175 #ifdef _WIN32
01176     __declspec(dllexport)
01177 #endif
01178     BinaryFile* construct()
01179     {
01180         return new Win32BinaryFile;
01181     }    
01182 }
01183 
01184 void Win32BinaryFile::dumpSymbols() {
01185     std::map<ADDRESS, std::string>::iterator it;
01186     std::cerr << std::hex;
01187     for (it = dlprocptrs.begin(); it != dlprocptrs.end(); ++it)
01188         std::cerr << "0x" << it->first << " " << it->second << "        ";
01189     std::cerr << std::dec << "\n";
01190 }
01191 

Generated on Tue Sep 19 21:18:36 2006 for Boomerang by  doxygen 1.4.6