Collected Windows fixes
[dyninst.git] / dyninstAPI / src / pdwinnt.C
1 /*
2  * Copyright (c) 1996-2011 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 #include "common/h/std_namesp.h"
33 #include <iomanip>
34 #include <string>
35 #include "dyninstAPI/src/symtab.h"
36 #include "common/h/headers.h"
37 #include "dyninstAPI/src/os.h"
38 #include "dyninstAPI/src/addressSpace.h"
39 #include "common/h/stats.h"
40 #include "common/h/Types.h"
41 #include "dyninstAPI/src/debug.h"
42 #include "dyninstAPI/src/instPoint.h"
43 #include "common/h/ntHeaders.h"
44 #include "dyninstAPI/src/mapped_object.h"
45 #include "dyninstAPI/src/emit-x86.h"
46 #include "common/h/arch.h"
47 #include "dyninstAPI/src/inst-x86.h"
48 #include "dyninstAPI/src/registerSpace.h"
49 #include "symtab.h"
50 #include "MemoryEmulator/memEmulator.h"
51 #include <boost/tuple/tuple.hpp>
52
53 #include "dyninstAPI/src/ast.h"
54
55 #include "dyninstAPI/src/function.h"
56 #include "dynProcess.h"
57
58 /* XXX This is only needed for emulating signals. */
59 #include "BPatch_thread.h"
60 #include "BPatch_process.h"
61 #include "nt_signal_emul.h"
62 #include "dyninstAPI/src/PCEventMuxer.h"
63
64 // prototypes of functions used in this file
65
66 void InitSymbolHandler( HANDLE hPCProcess );
67 void ReleaseSymbolHandler( HANDLE hPCProcess );
68 extern bool isValidAddress(AddressSpace *proc, Address where);
69
70 void printSysError(unsigned errNo) {
71     char buf[1000];
72     bool result = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNo, 
73                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
74                   buf, 1000, NULL);
75     if (!result) {
76         fprintf(stderr, "Couldn't print error message\n");
77         printSysError(GetLastError());
78     }
79     fprintf(stderr, "*** System error [%d]: %s\n", errNo, buf);
80     fflush(stderr);
81 }
82
83
84 // check if a file handle is for kernel32.dll
85 static bool kludge_isKernel32Dll(HANDLE fileHandle, std::string &kernel32Name) {
86     static DWORD IndxHigh, IndxLow;
87     static bool firstTime = true;
88     BY_HANDLE_FILE_INFORMATION info;
89     static std::string kernel32Name_;
90
91     if (firstTime) {
92        HANDLE kernel32H;
93        firstTime = false;
94        char sysRootDir[MAX_PATH+1];
95        if (GetSystemDirectory(sysRootDir, MAX_PATH) == 0)
96           assert(0);
97        kernel32Name_ = std::string(sysRootDir) + "\\kernel32.dll";
98        kernel32H = CreateFile(kernel32Name_.c_str(), GENERIC_READ, 
99                               FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
100        assert(kernel32H);
101        if (!GetFileInformationByHandle(kernel32H, &info)) {
102           printSysError(GetLastError());
103           assert(0);
104        }
105        IndxHigh = info.nFileIndexHigh;
106        IndxLow = info.nFileIndexLow;
107        CloseHandle(kernel32H);
108     }
109
110     if (!GetFileInformationByHandle(fileHandle, &info))
111        return false;
112
113     if (info.nFileIndexHigh==IndxHigh && info.nFileIndexLow==IndxLow) {
114       kernel32Name = kernel32Name_;
115       return true;
116     }
117     return false;
118 }
119
120 /* 
121    Loading libDyninstRT.dll
122
123    We load libDyninstRT.dll dynamically, by inserting code into the
124    application to call LoadLibraryA. We don't use the inferior RPC
125    mechanism from class PCProcess because it already assumes that
126    libdyninst is loaded (it uses the inferior heap).
127    Instead, we use a simple inferior call mechanism defined below
128    to insert the code to call LoadLibraryA("libdyninstRT.dll").
129  */
130 #if 0
131 Address loadDyninstDll(PCProcess *p, char Buffer[LOAD_DYNINST_BUF_SIZE]) {
132     return 0;
133 }
134 #endif
135 // osTraceMe is not needed in Windows NT
136 void OS::osTraceMe(void) {}
137
138 bool PCProcess::dumpImage(std::string outFile)
139 {
140   fprintf(stderr, "%s[%d]:  Sorry, dumpImage() not implemented for windows yet\n", FILE__, __LINE__);
141   fprintf(stderr, "\t cannot create '%s' as requested\n", outFile.c_str());
142   return false;
143 }
144
145
146 static void hasIndex(PCProcess *, unsigned, void *data, void *result) 
147 {
148     *((int *) data) = (int) result;
149 }
150
151
152
153
154 bool CALLBACK printMods(PCSTR name, DWORD64 addr, PVOID unused) {
155     fprintf(stderr, " %s @ %llx\n", name, addr);
156     return true;
157 }
158 #if 0
159 static bool decodeAccessViolation_defensive(EventRecord &ev, bool &wait_until_active)
160 {
161     bool ret = false;
162     wait_until_active = true;
163     ev.address = (eventAddress_t) ev.info.u.Exception.ExceptionRecord.ExceptionAddress;
164     Address violationAddr = 
165         ev.info.u.Exception.ExceptionRecord.ExceptionInformation[1];
166     mapped_object *obj = NULL;
167
168     switch(ev.info.u.Exception.ExceptionRecord.ExceptionInformation[0]) {
169     case 0: // bad read
170         if (dyn_debug_malware) {
171             Address origAddr = ev.address;
172             vector<func_instance *> funcs;
173             baseTramp *bt = NULL;
174             ev.proc->getAddrInfo(ev.address, origAddr, funcs, bt);
175             mal_printf("bad read in pdwinnt.C %lx[%lx]=>%lx [%d]\n",
176                        ev.address, origAddr, violationAddr,__LINE__);
177             // detach so we can see what's going on 
178             pdvector<pdvector<Frame> >  stacks;
179             if (!ev.proc->walkStacks(stacks)) {
180                 mal_printf("%s[%d]:  walkStacks failed\n", FILE__, __LINE__);
181                 return false;
182             }
183             for (unsigned i = 0; i < stacks.size(); ++i) {
184                 pdvector<Frame> &stack = stacks[i];
185                 for (unsigned int j = 0; j < stack.size(); ++j) {
186                     Address origPC = 0;
187                     vector<func_instance*> dontcare1;
188                     baseTramp *dontcare2 = NULL;
189                     ev.proc->getAddrInfo(stack[j].getPC(), origPC, dontcare1, dontcare2);
190                     mal_printf("frame %d: %lx[%lx]\n", j, stack[j].getPC(), origPC);
191                 }
192             }
193             dyn_saved_regs regs;
194             ev.lwp->getRegisters(&regs,false);
195             fprintf(stderr,"REGISTER STATE:\neax=%lx \necx=%lx \nedx=%lx \nebx=%lx \nesp=%lx \nebp=%lx \nesi=%lx "
196                    "\nedi=%lx\n",regs.cont.Eax, regs.cont.Ecx, regs.cont.Edx, 
197                    regs.cont.Ebx, regs.cont.Esp, regs.cont.Ebp, 
198                    regs.cont.Esi, regs.cont.Edi);
199         }
200         break;
201
202     case 1: {// bad write 
203         Address origAddr = ev.address;
204         vector<func_instance *> writefuncs;
205         baseTramp *bt = NULL;
206         bool success = ev.proc->getAddrInfo(ev.address, origAddr, writefuncs, bt);
207         if (dyn_debug_malware) {
208             Address origAddr = ev.address;
209                         Address shadowAddr = 0;
210                         bool valid = false;
211                         boost::tie(valid, shadowAddr) = ev.proc->getMemEm()->translateBackwards(violationAddr);
212
213                         cerr << "Overwrite insn @ " << hex << origAddr << dec << endl;
214             vector<func_instance *> writefuncs;
215             baseTramp *bti = NULL;
216             bool success = ev.proc->getAddrInfo(ev.address, origAddr, writefuncs, bti);
217             if (success) {
218                 fprintf(stderr,"---%s[%d] overwrite insn at %lx[%lx] in "
219                         "function\"%s\" [%lx], writing to %lx (%lx) \n",
220                         FILE__,__LINE__, ev.address, origAddr,
221                                                 writefuncs.empty() ? "<NO FUNC>" : writefuncs[0]->get_name().c_str(), 
222                                                 writefuncs.empty() ? 0 : writefuncs[0]->addr(), 
223                         violationAddr, shadowAddr);
224             } else { 
225                 fprintf(stderr,"---%s[%d] overwrite insn at %lx, not "
226                         "contained in any range, writing to %lx \n",
227                         __FILE__,__LINE__, ev.address, violationAddr);
228             }
229             dyn_saved_regs regs;
230             ev.lwp->getRegisters(&regs,false);
231             fprintf(stderr,"REGISTER STATE:\neax=%lx \necx=%lx \nedx=%lx \nebx=%lx \nesp=%lx \nebp=%lx \nesi=%lx "
232                    "\nedi=%lx\n",regs.cont.Eax, regs.cont.Ecx, regs.cont.Edx, 
233                    regs.cont.Ebx, regs.cont.Esp, regs.cont.Ebp, 
234                    regs.cont.Esi, regs.cont.Edi);
235         }
236
237         // ignore memory access violations originating in kernel32.dll 
238         // (if not originating from an instrumented instruction)
239         mapped_object *obj = ev.proc->findObject(origAddr);
240         assert(obj);
241         if ( BPatch_defensiveMode != obj->hybridMode() ) 
242         {
243             wait_until_active = false;
244             ret = true;
245             ev.type = evtIgnore;
246             ev.lwp->changeMemoryProtections(
247                 violationAddr - (violationAddr % ev.proc->getMemoryPageSize()), 
248                 ev.proc->getMemoryPageSize(), 
249                 PAGE_EXECUTE_READWRITE, 
250                 false);
251             break;
252         }
253         // it's a write to a page containing write-protected code if region
254         // permissions don't match the current permissions of the written page
255         obj = ev.proc->findObject(violationAddr);
256         if (!obj && ev.proc->isMemoryEmulated()) {
257             bool valid=false;
258             Address orig=0;
259             boost::tie(valid,orig) = ev.proc->getMemEm()->translateBackwards(violationAddr);
260             if (valid) {
261                 violationAddr = orig;
262                 obj = ev.proc->findObject(violationAddr);
263             }
264         }
265         if (obj) {
266             using namespace SymtabAPI;
267             Region *reg = obj->parse_img()->getObject()->
268                 findEnclosingRegion(violationAddr - obj->codeBase());
269             pdvector<CallbackBase *> callbacks;
270             if (reg && (reg->getRegionPermissions() == Region::RP_RW ||
271                         reg->getRegionPermissions() == Region::RP_RWX  ) &&
272                 getCBManager()->dispenseCallbacksMatching
273                     (evtCodeOverwrite, callbacks)) //checks for CBs, doesn't call them
274                 {
275                     ev.info2 = reg;
276                     ev.type = evtCodeOverwrite;
277                     ret = true;
278                     wait_until_active = false;
279                 }
280             callbacks.clear();
281         }
282         else {
283             fprintf(stderr,"%s[%d] WARNING, possible bug, write insn at "
284                     "%lx wrote to %lx\n",
285                     __FILE__,__LINE__,ev.address, violationAddr);
286             // detach so we can see what's going on 
287             //ev.proc->detachPCProcess(true);
288         }
289         break;
290     }
291     case 8: // no execute permissions
292         fprintf(stderr, "ERROR: executing code that lacks executable "
293                 "permissions in pdwinnt.C at %lx, evt.addr=%lx [%d]\n",
294                 ev.address, violationAddr,__LINE__);
295         ev.proc->detachPCProcess(true);
296         assert(0);
297         break;
298     default:
299         if (dyn_debug_malware) {
300             Address origAddr = ev.address;
301             vector<func_instance *> funcs;
302             baseTramp *bti = NULL;
303             ev.proc->getAddrInfo(ev.address, origAddr, funcs, bti);
304             mal_printf("weird exception in pdwinnt.C illegal instruction or "
305                        "access violation w/ code (%lx) %lx[%lx]=>%lx [%d]\n",
306                        ev.info.u.Exception.ExceptionRecord.ExceptionInformation[0],
307                        ev.address, origAddr, violationAddr,__LINE__);
308         }
309         ev.proc->detachPCProcess(true);
310         assert(0);
311     }
312     if (evtCodeOverwrite != ev.type && ev.proc->isMemoryEmulated()) {
313         // see if we were executing in defensive code whose memory access 
314         // would have been emulated
315         Address origAddr = ev.address;
316         vector<func_instance *> writefuncs;
317         baseTramp *bti = NULL;
318         bool success = ev.proc->getAddrInfo(ev.address, origAddr, writefuncs, bti);
319         mapped_object *faultObj = NULL;
320         if (success) {
321             faultObj = ev.proc->findObject(origAddr);
322         }
323         if (!faultObj || BPatch_defensiveMode == faultObj->hybridMode()) {
324             // KEVINTODO: we're emulating the instruction, pop saved regs off 
325             // of the stack and into the appropriate registers,
326             // signalHandlerEntry will have to fix up the saved 
327             // context information on the stack 
328             assert(1 || "stack imbalance and bad reg values resulting from incomplete memory emulation of instruction that caused a fault");
329         }
330     }
331     return ret;
332 }
333 #endif
334
335 // already setup on this FD.
336 // disconnect from controlling terminal 
337 void OS::osDisconnect(void) {
338 }
339
340 #if 0
341 bool PCProcess::setMemoryAccessRights (Address start, Address size, int rights)
342 {
343     //mal_printf("setMemoryAccessRights to %x [%lx %lx]\n", rights, start, start+size);
344     // get lwp from which we can call changeMemoryProtections
345     dyn_lwp *stoppedlwp = query_for_stopped_lwp();
346     assert( stoppedlwp );
347     if (PAGE_EXECUTE_READWRITE == rights || PAGE_READWRITE == rights) {
348         mapped_object *obj = findObject(start);
349         int page_size = getMemoryPageSize();
350         for (Address cur = start; cur < (start + size); cur += page_size) {
351             obj->removeProtectedPage(start -(start % page_size));
352         }
353     }
354     stoppedlwp->changeMemoryProtections(start, size, rights, true);
355     return true;
356 }
357 #endif
358 bool PCProcess::getMemoryAccessRights(Address start, Address size, int rights)
359 {
360    assert(0 && "Unimplemented!");
361    return 0;
362 }
363
364 #if 0
365 int dyn_lwp::changeMemoryProtections
366 (Address addr, Offset size, unsigned rights, bool setShadow)
367 {
368     unsigned oldRights=0;
369     unsigned pageSize = proc()->getMemoryPageSize();
370
371         Address pageBase = addr - (addr % pageSize);
372         size += (addr % pageSize);
373
374         // Temporary: set on a page-by-page basis to work around problems
375         // with memory deallocation
376         for (Address idx = pageBase; idx < pageBase + size; idx += pageSize) {
377       //mal_printf("setting rights to %lx for [%lx %lx)\n", rights, idx , idx + pageSize);
378                 if (!VirtualProtectEx((HANDLE)getProcessHandle(), (LPVOID)(idx), 
379                         (SIZE_T)pageSize, (DWORD)rights, (PDWORD)&oldRights)) 
380                 {
381                         fprintf(stderr, "ERROR: failed to set access rights for page %lx, error code %d "
382                                 "%s[%d]\n", addr, GetLastError(), FILE__, __LINE__);
383                         MEMORY_BASIC_INFORMATION meminfo;
384                         SIZE_T size = VirtualQueryEx(getPCProcessHandle(), (LPCVOID) (addr), &meminfo, sizeof(MEMORY_BASIC_INFORMATION));
385                         fprintf(stderr, "ERROR DUMP: baseAddr 0x%lx, AllocationBase 0x%lx, AllocationProtect 0x%lx, RegionSize 0x%lx, State 0x%lx, Protect 0x%lx, Type 0x%lx\n",
386                                 meminfo.BaseAddress, meminfo.AllocationBase, meminfo.AllocationProtect, meminfo.RegionSize, meminfo.State, meminfo.Protect, meminfo.Type);
387                 }
388                 else if (proc()->isMemoryEmulated() && setShadow) {
389                         Address shadowAddr = 0;
390                         unsigned shadowRights=0;
391                         bool valid = false;
392                         boost::tie(valid, shadowAddr) = proc()->getMemEm()->translate(idx);
393                         if (!valid) {
394                                 //fprintf(stderr, "WARNING: set access rights on page %lx that has "
395                                 //      "no shadow %s[%d]\n",addr,FILE__,__LINE__);
396                         }
397                         else 
398                         {
399                                 if (!VirtualProtectEx((HANDLE)getPCProcessHandle(), (LPVOID)(shadowAddr), 
400                                         (SIZE_T)pageSize, (DWORD)rights, (PDWORD)&shadowRights)) 
401                                 {
402                                         fprintf(stderr, "ERROR: set access rights found shadow page %lx "
403                                                 "for page %lx but failed to set its rights %s[%d]\n",
404                                                 shadowAddr, addr, FILE__, __LINE__);
405                                 }
406
407                                 if (shadowRights != oldRights) {
408                                         //mal_printf("WARNING: shadow page[%lx] rights %x did not match orig-page"
409                                         //           "[%lx] rights %x\n",shadowAddr,shadowRights, addr, oldRights);
410                                 }
411                         }
412                 }
413         }
414         return oldRights;
415 }
416 #endif
417
418
419 #if 0
420
421 // sets PC for stack frames other than the active stack frame
422 bool Frame::setPC(Address newpc) {
423
424         if (!pcAddr_) {
425                 // if pcAddr isn't set it's because the stackwalk isn't getting the 
426                 // frames right
427                 fprintf(stderr,"WARNING: unable to change stack frame PC from %lx to %lx "
428                         "because we don't know where the PC is on the stack %s[%d]\n",
429                         pc_,newpc,FILE__,__LINE__);
430                 return false;
431         }
432
433         if (getProc()->writeDataSpace( (void*)pcAddr_, 
434                 getProc()->getAddressWidth(), 
435                 &newpc) ) 
436         {
437                 this->pc_ = newpc;
438                 return true;
439         }
440
441         return false;
442 }
443 #endif
444
445 void InitSymbolHandler( HANDLE hPCProcess )
446 {
447 }
448
449 void
450 ReleaseSymbolHandler( HANDLE hPCProcess )
451 {
452     if( !SymCleanup( hPCProcess ) )
453     {
454         // TODO how to report error?
455         fprintf( stderr, "failed to release symbol handler: %x\n",
456             GetLastError() );
457     }
458
459     CloseHandle(hPCProcess);
460 }
461
462
463 /*
464  * stripAtSuffix
465  *
466  * Strips off of a string any suffix that consists of an @ sign followed by
467  * decimal digits.
468  *
469  * str  The string to strip the suffix from.  The string is altered in place.
470  */
471 static void stripAtSuffix(char *str)
472 {
473     // many symbols have a name like foo@4, we must remove the @4
474     // just searching for an @ is not enough,
475     // as it may occur on other positions. We search for the last one
476     // and check that it is followed only by digits.
477     char *p = strrchr(str, '@');
478     if (p) {
479       char *q = p+1;
480       strtoul(p+1, &q, 10);
481       if (q > p+1 && *q == '\0') {
482         *p = '\0';
483       }
484     }
485 }
486
487 char *cplus_demangle(char *c, int, bool includeTypes) { 
488     char buf[1000];
489     if (c[0]=='_') {
490        // VC++ 5.0 seems to decorate C symbols differently to C++ symbols
491        // and the UnDecorateSymbolName() function provided by imagehlp.lib
492        // doesn't manage (or want) to undecorate them, so it has to be done
493        // manually, removing a leading underscore from functions & variables
494        // and the trailing "$stuff" from variables (actually "$Sstuff")
495        unsigned i;
496        for (i=1; i<sizeof(buf) && c[i]!='$' && c[i]!='\0'; i++)
497            buf[i-1]=c[i];
498        buf[i-1]='\0';
499        stripAtSuffix(buf);
500        if (buf[0] == '\0') return 0; // avoid null names which seem to annoy Paradyn
501        return P_strdup(buf);
502     } else {
503        if (includeTypes) {
504           if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE| UNDNAME_NO_ACCESS_SPECIFIERS|UNDNAME_NO_MEMBER_TYPE|UNDNAME_NO_MS_KEYWORDS)) {
505             //   printf("Undecorate with types: %s = %s\n", c, buf);
506             stripAtSuffix(buf);
507             return P_strdup(buf);
508           }
509        }  else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_NAME_ONLY)) {
510          //     else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_COMPLETE|UNDNAME_32_BIT_DECODE)) {
511          //     printf("Undecorate: %s = %s\n", c, buf);
512          stripAtSuffix(buf);          
513          return P_strdup(buf);
514        }
515     }
516     return 0;
517 }
518
519 bool OS::osKill(int pid) {
520     bool res;
521     HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
522     if (h == NULL) {
523         return false;
524     }
525     res = TerminateProcess(h,0);
526     CloseHandle(h);
527     return res;
528 }
529
530
531
532 bool getLWPIDs(pdvector <unsigned> &LWPids)
533 {
534   assert (0 && "Not implemented");
535   return false;
536 }
537
538 #if 0
539 //
540 // This function retrieves the name of a DLL that has been
541 // loaded in an inferior PCProcess.  On the desktop flavors
542 // of Windows, the debug event that we get for loaded DLLs
543 // includes the location of a pointer to the DLL's image name.
544 // (Note the indirection.)  On Windows CE, the event contains
545 // the location of the image name string, with no indirection.
546 //
547 // There are several complications to overcome when reading this string:
548 //
549 // 1.  There is no guarantee that the image name is available.
550 //     In this case, the location in the debug event may be NULL,
551 //     or the pointer in the inferior PCProcess' address space may be NULL.
552 // 2.  The image name string may be either ASCII or Unicode.  Most of
553 //     the Windows system DLLs have Unicode strings, but many user-built
554 //     DLLs use single-byte strings.  If the string is Unicode, we need
555 //     to copy it to our address space and convert it to a single-byte
556 //     string because the rest of Paradyn/Dyninst has no clue what to
557 //     do with Unicode strings.
558 // 3.  We don't know how long the string is.  We have a loose upper
559 //     bound in that we know it is not more than MAX_PATH characters.
560 //     Unfortunately, the call we use to read from the inferior
561 //     PCProcess' address space will return failure if we ask for more
562 //     bytes than it can actually read (so we can't just issue a read
563 //     for MAX_PATH characters).  Given this limitation, we have to
564 //     try a read and check whether the read succeeded *and* whether
565 //     we read the entire image name string.  If not, we have to adjust
566 //     the amount we read and try again.
567 //
568 std::string GetLoadedDllImageName( PCProcess* p, const DEBUG_EVENT& ev )
569 {
570     char *msgText = NULL;
571         std::string ret;
572         void* pImageName = NULL;
573
574         if( ev.u.LoadDll.lpImageName != NULL )
575         {
576         msgText = new char[1024];       // buffer for error messages
577             // On non-CE flavors of Windows, the address given in the debug
578         // event struct is the address of a pointer to the DLL name string.
579
580         if( !p->readDataSpace( ev.u.LoadDll.lpImageName, 4, &pImageName, false ) )
581         {
582             sprintf( msgText, "Failed to read DLL image name pointer: %d\n",
583             GetLastError() );
584             logLine( msgText );
585             }
586     }
587         if( pImageName != NULL )
588         {
589                 // we have the pointer to the DLL image name -
590                 // now read the name
591
592                 // allocate a conservatively-sized buffer
593                 char* buf = new char[(MAX_PATH + 1) * sizeof(WCHAR)];
594                 WCHAR* wbuf = (WCHAR*)buf;
595
596                 // We don't know how long the image name actually is, but
597                 // we do know that they tend not to be very long.
598                 // Therefore, we use a scheme to try to minimize the number
599                 // of reads needed to get the image name.
600                 // We do reads within ranges, starting with [1,128] bytes,
601                 // then [129,256] bytes, etc. up to MAX_PATH if necessary.
602                 // Within each range, we do reads following a binary search
603                 // algorithm.  For example, for the [1,128] range, we start
604                 // by trying to read 128 bytes.  If that read fails, we
605                 // try to half the number of bytes (i.e., 64).  If that
606                 // read also fails, we continue to halve the read requests 
607                 // until we find one that succeeds.
608                 //
609                 // When a read succeeds, we still may not have gotten the
610                 // entire string.  So when reads start succeeding, we have to
611                 // check the data we got for a null-terimated string.  If we didn't
612                 // get the full string, we change the byte count to either
613                 // move into the next higher range (if we were already reading
614                 // the max within the current range) or we set it to a factor
615                 // of 1.5 of the current byte count to try a value between the
616                 // current succeeding read and one that had failed.
617                 unsigned int loRead = 1;                // range boundaries
618                 unsigned int hiRead = 128;
619                 unsigned int cbRead = 128;              // number of bytes to read
620                 unsigned int chunkRead = 64;    // amount to change cbRead if we fail
621                                                                                 // we will not halve this before we read
622                 bool gotString = false;
623                 bool doneReading = false;
624                 while( !doneReading )
625                 {
626                         // try the read with the current byte count
627                         if( p->readDataSpace( pImageName, cbRead, buf, false ) )
628                         {
629                                 // the read succeeded - 
630                                 // did we get the full string?
631                                 if( ev.u.LoadDll.fUnicode )
632                                 {
633                                         unsigned int cbReadIdx = cbRead / sizeof(WCHAR);
634                                         wbuf[cbReadIdx] = L'\0';
635                                         WCHAR* nulp = wcschr( wbuf, L'\0' );
636                                         assert( nulp != NULL );                 // because we just NULL-terminated the string
637                                         gotString = (nulp != &(wbuf[cbReadIdx]));
638                                 }
639                                 else
640                                 {
641                                         buf[cbRead] = '\0';
642                                         char* nulp = strchr( buf, '\0' );
643                                         assert( nulp != NULL );                 // because we just NULL-terminated the string
644                                         gotString = (nulp != &(buf[cbRead]));
645                                 }
646
647                                 if( gotString )
648                                 {
649                                         doneReading = true;
650                                 }
651                                 else
652                                 {
653                                         // we didn't get the full string
654                                         // we need to try a larger read
655                                         if( cbRead == hiRead )
656                                         {
657                                                 // we were at the high end of the current range -
658                                                 // move to the next range
659                                                 loRead = hiRead + 1;
660                                                 hiRead = loRead + 128 - 1;
661                                                 chunkRead = 128;                                // we will halve this before we read again
662                                                 if( loRead > (MAX_PATH * sizeof(WCHAR)) )
663                                                 {
664                                                         // we've tried every range but still failed
665                                                         doneReading = true;
666                                                 }
667                                                 else
668                                                 {
669                                                         cbRead = hiRead;
670                                                 }
671                                         }
672                                         else
673                                         {
674                                                 // we were within the current range -
675                                                 // try something higher but still within the range
676                                                 cbRead = cbRead + chunkRead;
677                                         }
678                                 }
679                         }
680                         else
681                         {
682                                 // the read failed -
683                                 // we need to try a smaller read
684                                 if( cbRead > loRead )
685                                 {
686                                         unsigned int nextRead = cbRead - chunkRead;
687                                         if( nextRead == cbRead )
688                                         {
689                                                 // we can't subdivide any further
690                                                 doneReading = true;
691                                         }
692                                         else
693                                         {
694                                                 cbRead = nextRead;
695                                         }
696                                 }
697                                 else
698                                 {
699                                         // there are no smaller reads to try in this range,
700                                         // and by induction, in any range.
701                                         doneReading = true;
702                                 }
703                         }
704
705                         // update the amount that we use to change the read request
706                         chunkRead /= 2;
707                 }
708
709                 if( !gotString )
710                 {
711                         // this is a serious problem because some read 
712                         // should've succeeded
713                         sprintf( msgText, "Failed to read DLL image name - no read succeeded\n" );
714                         logLine( msgText );
715                 }
716                 else
717                 {
718                         if( ev.u.LoadDll.fUnicode )
719                         {
720                                 // the DLL path is a Unicode string
721                                 // we have to convert it to single-byte characters
722                                 char* tmpbuf = new char[MAX_PATH];
723
724                                 WideCharToMultiByte(CP_ACP,             // code page to use (ANSI)
725                                                                         0,                      // flags
726                                                                         wbuf,           // Unicode string
727                                                                         -1,                     // length of Unicode string (-1 => null-terminated)
728                                                                         tmpbuf,         // destination buffer
729                                                                         MAX_PATH,       // size of destionation buffer
730                                                                         NULL,           // default for unmappable chars
731                                                                         NULL);          // var to set when defaulting a char
732
733                                 // swap buffers so that buf points to the single-byte string
734                                 // when we're out of this code block
735                                 delete[] buf;
736                                 buf = tmpbuf;
737                         }
738                         ret = buf;
739                 }
740
741                 delete[] buf;
742         }
743         else
744         {
745                 // we were given an image name pointer, but it was NULL
746                 // this happens for some system DLLs, and if we attach to
747                 // the PCProcess instead of creating it ourselves.
748                 // However, it is very important for us to know about kernel32.dll,
749                 // so we check for it specially.
750                 //
751                 // This call only changes the string parameter if the indicated file is
752                 // actually kernel32.dll.
753                 if (kludge_isKernel32Dll(ev.u.LoadDll.hFile, ret))
754             return ret;
755
756         //I'm embarassed to be writing this.  We didn't get a name for the image, 
757         // but we did get a file handle.  According to MSDN, the best way to turn
758         // a file handle into a file name is to map the file into the address space
759         // (using the handle), then ask the OS what file we have mapped at that location.
760         // I'm sad now.
761         
762         void *pmap = NULL;
763         HANDLE fmap = CreateFileMapping(ev.u.LoadDll.hFile, NULL, 
764                                         PAGE_READONLY, 0, 1, NULL);
765         if (fmap) {
766             pmap = MapViewOfFile(fmap, FILE_MAP_READ, 0, 0, 1);
767             if (pmap) {   
768                 char filename[MAX_PATH+1];
769                 int result = GetMappedFileName(GetCurrentProcess(), pmap, filename, MAX_PATH);
770                 if (result)
771                     ret = std::string(filename);
772                 UnmapViewOfFile(pmap);
773             }
774             CloseHandle(fmap);
775         }
776         }
777
778         if (ret.substr(0,7) == "\\Device") {
779       HANDLE currentProcess = p->ProcessHandle_;
780       DWORD num_modules_needed;
781       int errorCheck = EnumProcessModules(currentProcess,
782                                           NULL,
783                                           0,
784                                           &num_modules_needed);
785           num_modules_needed /= sizeof(HMODULE);
786       HMODULE* loadedModules = new HMODULE[num_modules_needed];
787       errorCheck = EnumProcessModules(currentProcess,
788                                           loadedModules,
789                                           sizeof(HMODULE)*num_modules_needed,
790                                           &num_modules_needed);
791       HMODULE* candidateModule = loadedModules; 
792       while(candidateModule < loadedModules + num_modules_needed)
793       {
794          MODULEINFO candidateInfo;
795          GetModuleInformation(currentProcess, *candidateModule, &candidateInfo,
796                               sizeof(candidateInfo));
797          if(ev.u.LoadDll.lpBaseOfDll == candidateInfo.lpBaseOfDll)
798             break;
799          candidateModule++;
800       }
801       if(candidateModule != loadedModules + num_modules_needed) 
802       {
803          TCHAR filename[MAX_PATH];
804          if(GetModuleFileNameEx(currentProcess, *candidateModule, filename, MAX_PATH))
805          {
806             ret = filename;
807          }
808       }
809       delete[] loadedModules;
810
811         }
812         // cleanup
813     if (msgText)
814         delete[] msgText;
815
816         return ret;
817 }
818 #endif
819
820
821
822 bool AddressSpace::getDyninstRTLibName() {
823     // Set the name of the dyninst RT lib
824     if (dyninstRT_name.length() == 0) {
825         // Get env variable
826         if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
827             dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
828         }
829         else {
830             std::string msg = std::string("Environment variable ") +
831                std::string("DYNINSTAPI_RT_LIB") +
832                std::string(" has not been defined");
833             showErrorCallback(101, msg);
834             return false;
835         }
836     }
837     //Canonicalize name
838     char *sptr = P_strdup(dyninstRT_name.c_str());
839     for (unsigned i=0; i<strlen(sptr); i++)
840        if (sptr[i] == '/') sptr[i] = '\\';
841     dyninstRT_name = sptr;
842     free(sptr);
843            
844     if (_access(dyninstRT_name.c_str(), 04)) {
845         std::string msg = std::string("Runtime library ") + dyninstRT_name +
846                        std::string(" does not exist or cannot be accessed!");
847         showErrorCallback(101, msg);
848         return false;
849     }
850
851     return true;
852 }
853
854 #if 0
855 // Load the dyninst library
856 bool PCProcess::loadDYNINSTlib()
857 {
858     loadDyninstLibAddr = getAOut()->parse_img()->getObject()->getEntryOffset() + getAOut()->getBaseAddress();
859     Address LoadLibAddr;
860     int_symbol sym;
861     
862     dyn_lwp *lwp;
863     lwp = getInitialLwp();
864  /*   if (lwp->status() == running) {
865        lwp->pauseLWP();
866     }*/
867
868     if (!getSymbolInfo("_LoadLibraryA@4", sym) &&
869         !getSymbolInfo("_LoadLibraryA", sym) &&
870         !getSymbolInfo("LoadLibraryA", sym))
871         {
872             printf("unable to find function LoadLibrary\n");
873             assert(0);
874         }
875     LoadLibAddr = sym.getAddr();
876     assert(LoadLibAddr);
877
878     char ibuf[BYTES_TO_SAVE];
879     memset(ibuf, '\0', BYTES_TO_SAVE);//ccw 25 aug 2000
880     char *iptr = ibuf;
881     strcpy(iptr, dyninstRT_name.c_str());
882     
883     // Code overview:
884     // Dynininst library name
885     //    Executable code begins here:
886     // Push (address of dyninst lib name)
887     // Call LoadLibrary
888     // Pop (cancel push)
889     // Trap
890     
891     // 4: give us plenty of room after the string to start instructions
892     int instructionOffset = strlen(iptr) + 4;
893     // Regenerate the pointer
894     iptr = &(ibuf[instructionOffset]);
895     
896     // At this point, the buffer contains the name of the dyninst
897     // RT lib. We now generate code to load this string into memory
898     // via a call to LoadLibrary
899     
900     // push nameAddr ; 5 bytes
901     *iptr++ = (char)0x68; 
902     // Argument for push
903     *(int *)iptr = loadDyninstLibAddr; // string at codeBase
904     iptr += sizeof(int);
905     
906     int offsetFromBufferStart = (int)iptr - (int)ibuf;
907     offsetFromBufferStart += 5; // Skip next instruction as well.
908     // call LoadLibrary ; 5 bytes
909     *iptr++ = (char)0xe8;
910     
911     // Jump offset is relative
912     *(int *)iptr = LoadLibAddr - (loadDyninstLibAddr + 
913                                   offsetFromBufferStart); // End of next instruction
914     iptr += sizeof(int);
915     
916     
917     // add sp, 4 (Pop)
918     *iptr++ = (char)0x83; *iptr++ = (char)0xc4; *iptr++ = (char)0x04;
919     
920     // int3
921     *iptr = (char)0xcc;
922     
923     int offsetToTrap = (int) iptr - (int) ibuf;
924
925     readDataSpace((void *)loadDyninstLibAddr, BYTES_TO_SAVE, savedCodeBuffer, false);
926     writeDataSpace((void *)loadDyninstLibAddr, BYTES_TO_SAVE, ibuf);
927     
928     flushInstructionCache_((void *)loadDyninstLibAddr, BYTES_TO_SAVE);
929     
930     dyninstlib_brk_addr = loadDyninstLibAddr + offsetToTrap;
931     
932     savedRegs = new dyn_saved_regs;
933
934     bool status = lwp->getRegisters(savedRegs);
935     assert(status == true);    
936
937         lwp->changePC(loadDyninstLibAddr + instructionOffset, NULL);
938     
939     setBootstrapState(loadingRT_bs);
940     return true;
941 }
942 #endif
943 // Cleanup after dyninst lib loaded
944 #if 0
945 bool PCProcess::loadDYNINSTlibCleanup(dyn_lwp *)
946 {
947     // First things first: 
948     assert(savedRegs != NULL);
949     getInitialLwp()->restoreRegisters(*savedRegs);
950     delete savedRegs;
951     savedRegs = NULL;
952
953     writeDataSpace((void *) loadDyninstLibAddr,
954                    BYTES_TO_SAVE,
955                    (void *)savedCodeBuffer);
956
957     flushInstructionCache_((void *)getAOut()->codeAbs(), BYTES_TO_SAVE);
958
959     dyninstlib_brk_addr = 0;
960
961     return true;
962 }
963 #endif
964 void loadNativeDemangler() 
965 {
966     // ensure we load line number information when we load
967     // modules, and give us mangled names
968     DWORD dwOpts = SymGetOptions();
969     dwOpts &= ~(SYMOPT_UNDNAME);
970     dwOpts |= SYMOPT_LOAD_LINES;
971     dwOpts &= ~(SYMOPT_DEFERRED_LOADS);
972     SymSetOptions(dwOpts);
973 }
974
975
976 void dyninst_yield()
977 {
978     SwitchToThread();
979 }
980
981 void OS::make_tempfile(char *name) {
982 }
983
984 bool OS::execute_file(char *file) {
985    STARTUPINFO s;
986    PROCESS_INFORMATION proc;
987    BOOL result;
988
989    ZeroMemory(&s, sizeof(s));
990    ZeroMemory(&proc, sizeof(proc));
991    s.cb = sizeof(s);
992
993    result = CreateProcess(NULL, file, NULL, NULL, FALSE, 0, NULL, NULL, 
994                           &s, &proc);
995    if (!result) {
996       fprintf(stderr, "Couldn't create %s - Error %d\n", file, GetLastError());
997       return false;
998    }
999
1000    WaitForSingleObject(proc.hProcess, INFINITE);
1001    CloseHandle(proc.hProcess);
1002    CloseHandle(proc.hThread);
1003    return true;
1004 }
1005
1006 void OS::unlink(char *file) {
1007    DeleteFile(file);
1008 }
1009
1010 #if !defined(TF_BIT)
1011 #define TF_BIT 0x100
1012 #endif
1013
1014 #if defined (cap_dynamic_heap)
1015 void PCProcess::inferiorMallocConstraints(Address near, Address &lo, Address &hi,
1016                                         inferiorHeapType /* type */ ) 
1017 {
1018 }
1019 #endif
1020
1021 /**
1022  stdcall:
1023    * C Naming - Name prefixed by a '_', followed by the name, then an '@',
1024      followed by number of bytes in arguments.  
1025      i.e. foo(int a, double b) = _foo@12
1026    * C++ Naming - __stdcall
1027    * Args - Arguments are passed on the stack.
1028    * Cleanup - Callee cleans up the stack before returning
1029  cdecl:
1030    * C Naming - Name prefixed by a '_'
1031    * C++ Naming - __cdecl in demangled name
1032    * Args - Arguments are passed on the stack.
1033    * Cleanup - Caller cleans up the stack after the return
1034  fastcall:
1035    * C Naming - Name prefixed by a '@', followed by the func name, then 
1036      another '@', followed by the number of bytes in the arguments.  i.e.
1037      foo(double a, int b, int c, int d) = @foo@20
1038    * C++ Naming - __fastcall in the mangled name
1039    * Args - First two arguments that are less than DWORD size are passed in ECX & EDX
1040    * Cleanup - Callee cleans up the stack before returning
1041  thiscall:
1042    * C Naming - NA
1043    * C++ Naming - __thiscall in the demangled name
1044    * 'this' parameter is passed in ECX, others are passed in the stack
1045    * Cleanup Callee cleans up the stack before returning
1046  **/
1047 callType func_instance::getCallingConvention() {
1048     const char *name = symTabName().c_str();
1049     const int buffer_size = 1024;
1050     char buffer[buffer_size];
1051     const char *pos;
1052
1053     if (callingConv != unknown_call)
1054         return callingConv;
1055
1056     if (!name) {
1057         //Umm...
1058         return unknown_call;
1059     }
1060
1061     switch(name[0]) {
1062         case '?':
1063             //C++ Encoded symbol. Everything is stored in the C++ name 
1064             // mangling scheme
1065             UnDecorateSymbolName(name, buffer, buffer_size, 
1066                 UNDNAME_NO_ARGUMENTS | UNDNAME_NO_FUNCTION_RETURNS);
1067             if (strstr(buffer, "__thiscall")) {
1068                 callingConv = thiscall_call;
1069                 return callingConv;
1070             }
1071             if (strstr(buffer, "__fastcall")) {
1072                 callingConv = fastcall_call;
1073                 return callingConv;
1074             }
1075             if (strstr(buffer, "__stdcall")) {
1076                 callingConv = stdcall_call;
1077                 return callingConv;
1078             }
1079             if (strstr(buffer, "__cdecl")) {
1080                 callingConv = cdecl_call;
1081                 return callingConv;
1082             }
1083             break;
1084         case '_':
1085           //Check for stdcall or cdecl
1086           pos = strrchr(name, '@');
1087           if (pos) {
1088             callingConv = stdcall_call;
1089             return callingConv;
1090           }
1091           else {
1092             callingConv = cdecl_call;
1093             return callingConv;
1094           }
1095           break;
1096         case '@':
1097           //Should be a fast call
1098           pos = strrchr(name, '@');
1099           if (pos) {
1100              callingConv = fastcall_call;
1101              return callingConv;
1102           }
1103           break;
1104     }
1105
1106     //We have no idea what this call is.  We probably got an undecorated
1107     // name.  If the function doesn't clean up it's own stack (doesn't 
1108     // have a ret #) instruction, then it must be a cdecl call, as that's
1109     // the only type that doesn't clean its own stack.
1110     //If the function is part of a class, then it's most likely a thiscall,
1111     // although that could be incorrect for a static function.  
1112     //Otherwise let's guess that it's a stdcall.
1113     if (!ifunc()->cleansOwnStack()) {
1114         callingConv = cdecl_call;
1115     }
1116     else if (strstr(name, "::")) {
1117         callingConv = thiscall_call;
1118     }
1119     else {
1120         callingConv = stdcall_call;
1121     }
1122     return callingConv;
1123 }
1124
1125 static void emitNeededCallSaves(codeGen &gen, Register reg, pdvector<Register> &extra_saves);
1126 static void emitNeededCallRestores(codeGen &gen, pdvector<Register> &saves);
1127
1128 int EmitterIA32::emitCallParams(codeGen &gen, 
1129                               const pdvector<AstNodePtr> &operands,
1130                               func_instance *target, 
1131                               pdvector<Register> &extra_saves, 
1132                               bool noCost)
1133 {
1134     callType call_conven = target->getCallingConvention();
1135     int estimatedFrameSize = 0;
1136     pdvector <Register> srcs;
1137     Register ecx_target = REG_NULL, edx_target = REG_NULL;
1138     Address unused = ADDR_NULL;
1139     const int num_operands = operands.size();
1140
1141     switch (call_conven) {
1142         case unknown_call:
1143         case cdecl_call:
1144         case stdcall_call:
1145           //Push all registers onto stack
1146           for (unsigned u = 0; u < operands.size(); u++) {
1147               Register src = REG_NULL;
1148               Address unused = ADDR_NULL;
1149               if (!operands[u]->generateCode_phase2( gen, false, unused, src)) assert(0);
1150               assert(src != REG_NULL);
1151               srcs.push_back(src);
1152           }
1153           break;
1154     case thiscall_call:
1155         //Allocate the ecx register for the 'this' parameter
1156         if (num_operands) {
1157             //result = gen.rs()->allocateSpecificRegister(gen, REGNUM_ECX, false);
1158             //if (!result) {
1159             //    emitNeededCallSaves(gen, REGNUM_ECX, extra_saves);
1160             //}
1161             if (!operands[0]->generateCode_phase2(gen, 
1162                                                   noCost, 
1163                                                   unused, ecx_target)) assert(0);
1164         }
1165         srcs.push_back(Null_Register);
1166         //Push other registers onto the stack
1167         for (unsigned u = 1; u < operands.size(); u++) {
1168               Register src = REG_NULL;
1169               Address unused = ADDR_NULL;
1170               if (!operands[u]->generateCode_phase2( gen, false, unused, src)) assert(0);
1171               assert(src != REG_NULL);
1172               srcs.push_back(src);
1173         }     
1174         break;
1175     case fastcall_call:
1176         if (num_operands) {
1177             //Allocate the ecx register for the first parameter
1178             //ecx_target = gen.rs()->allocateSpecificRegister(gen, REGNUM_ECX, false);
1179             //if (!ecx_target) {
1180             //    emitNeededCallSaves(gen, REGNUM_ECX, extra_saves);
1181             //}
1182         }
1183         if (num_operands > 1) {
1184             //Allocate the edx register for the second parameter
1185             //edx_target = gen.rs()->allocateSpecificRegister(gen, REGNUM_EDX, false);
1186             //if (!edx_target) {
1187             //    emitNeededCallSaves(gen, REGNUM_EDX, extra_saves);
1188             //}
1189         }
1190         if (num_operands) {
1191             if (!operands[0]->generateCode_phase2(gen, 
1192                                                   noCost, 
1193                                                   unused, ecx_target)) assert(0);
1194         }
1195         if (num_operands > 1) {
1196             if (!operands[1]->generateCode_phase2(gen, 
1197                                                   noCost, unused, edx_target)) assert(0);
1198         }
1199         srcs.push_back(Null_Register);
1200         srcs.push_back(Null_Register);
1201
1202         //Push other registers onto the stack
1203         for (unsigned u = 2; u < operands.size(); u++) {
1204               Register src = REG_NULL;
1205               Address unused = ADDR_NULL;
1206               if (!operands[u]->generateCode_phase2( gen, false, unused, src)) assert(0);
1207               assert(src != REG_NULL);
1208               srcs.push_back(src);
1209         }
1210         break;
1211     default:
1212         fprintf(stderr, "Internal error.  Unknown calling convention\n");
1213         assert(0);
1214     }
1215
1216     // push arguments in reverse order, last argument first
1217     // must use int instead of unsigned to avoid nasty underflow problem:
1218     for (int i=srcs.size() - 1; i >= 0; i--) {
1219        if (srcs[i] == Null_Register) continue;
1220            RealRegister r = gen.rs()->loadVirtual(srcs[i], gen);
1221            ::emitPush(r, gen);
1222        estimatedFrameSize += 4;
1223        if (operands[i]->decRefCount())
1224           gen.rs()->freeRegister(srcs[i]);
1225     }
1226
1227     if (ecx_target != REG_NULL) {
1228         //Store the parameter in ecx
1229                 gen.rs()->loadVirtualToSpecific(ecx_target, RealRegister(REGNUM_ECX), gen);
1230     }
1231
1232     if (edx_target != REG_NULL) {
1233                 gen.rs()->loadVirtualToSpecific(edx_target, RealRegister(REGNUM_EDX), gen);
1234     }
1235     return estimatedFrameSize;
1236 }
1237
1238 bool EmitterIA32::emitCallCleanup(codeGen &gen, func_instance *target, 
1239                      int frame_size, pdvector<Register> &extra_saves)
1240 {
1241     callType call_conv = target->getCallingConvention();
1242     if ((call_conv == unknown_call || call_conv == cdecl_call) && frame_size)
1243     {
1244         //Caller clean-up
1245         emitOpRegImm(0, RealRegister(REGNUM_ESP), frame_size, gen); // add esp, frame_size        
1246     }
1247  gen.rs()->incStack(-1 * frame_size);
1248
1249     //Restore extra registers we may have saved when storing parameters in
1250     // specific registers
1251     //emitNeededCallRestores(gen, extra_saves);
1252     return 0;
1253 }
1254
1255 static void emitNeededCallSaves(codeGen &gen, Register regi, 
1256                            pdvector<Register> &extra_saves)
1257 {
1258     extra_saves.push_back(regi);
1259     switch (regi) {
1260         case REGNUM_EAX:
1261             emitSimpleInsn(PUSHEAX, gen);
1262             break;
1263         case REGNUM_EBX:
1264             emitSimpleInsn(PUSHEBX, gen);
1265             break;
1266         case REGNUM_ECX:
1267             emitSimpleInsn(PUSHECX, gen);
1268             break;
1269         case REGNUM_EDX:
1270             emitSimpleInsn(PUSHEDX, gen);
1271             break;
1272         case REGNUM_EDI:
1273             emitSimpleInsn(PUSHEDI, gen);
1274             break;
1275     }
1276 }
1277
1278 static void emitNeededCallRestores(codeGen &gen, pdvector<Register> &saves)
1279 {
1280     for (unsigned i=0; i<saves.size(); i++) {
1281       switch (saves[i]) {
1282           case REGNUM_EAX:
1283               emitSimpleInsn(POP_EAX, gen);
1284               break;
1285           case REGNUM_EBX:
1286               emitSimpleInsn(POP_EBX, gen);
1287               break;
1288           case REGNUM_ECX:
1289               emitSimpleInsn(POP_ECX, gen);
1290               break;
1291           case REGNUM_EDX:
1292               emitSimpleInsn(POP_EDX, gen);
1293               break;
1294           case REGNUM_EDI:
1295               emitSimpleInsn(POP_EDI, gen);
1296               break;
1297       }
1298     }
1299     saves.clear();
1300 }
1301
1302
1303
1304 #if 0
1305 mapped_object *PCProcess::createObjectNoFile(Address addr)
1306 {
1307         cerr << "createObjectNoFile " << hex << addr << dec << endl;
1308     Address closestObjEnd = 0;
1309     for (unsigned i=0; i<mapped_objects.size(); i++)
1310     {
1311         if (addr >= mapped_objects[i]->codeAbs() &&
1312             addr <   mapped_objects[i]->codeAbs() 
1313                    + mapped_objects[i]->imageSize())
1314         {
1315             fprintf(stderr,"createObjectNoFile called for addr %lx, "
1316                     "matching existing mapped_object %s %s[%d]\n", addr,
1317                     mapped_objects[i]->fullName().c_str(), FILE__,__LINE__);
1318             return mapped_objects[i];
1319         }
1320         if (  addr >= ( mapped_objects[i]->codeAbs() + 
1321                         mapped_objects[i]->imageSize() ) &&  
1322             closestObjEnd < ( mapped_objects[i]->codeAbs() + 
1323                                mapped_objects[i]->imageSize() ) ) 
1324         {
1325             closestObjEnd = mapped_objects[i]->codeAbs() + 
1326                             mapped_objects[i]->imageSize();
1327         }
1328     }
1329
1330     Address testRead = 0;
1331
1332     // VirtualQueryEx rounds down to pages size, so we need to round up first.
1333     if (proc()->proc() && closestObjEnd % proc()->proc()->getMemoryPageSize())
1334     {
1335         closestObjEnd = closestObjEnd 
1336             - (closestObjEnd % proc()->proc()->getMemoryPageSize()) 
1337             + proc()->proc()->getMemoryPageSize();
1338     }
1339     if (proc()->proc() && readDataSpace((void*)addr, proc()->getAddressWidth(),
1340                                         &testRead, false)) 
1341     {
1342                 // create a module for the region enclosing this address
1343         MEMORY_BASIC_INFORMATION meminfo;
1344         memset(&meminfo,0, sizeof(MEMORY_BASIC_INFORMATION) );
1345         SIZE_T size = VirtualQueryEx(proc()->ProcessHandle_,
1346                                      (LPCVOID)addr, &meminfo, 
1347                                      sizeof(MEMORY_BASIC_INFORMATION));
1348         assert(meminfo.State == MEM_COMMIT);
1349                 cerr << "VirtualQuery reports baseAddr " << hex << meminfo.BaseAddress << ", allocBase " << meminfo.AllocationBase << ", size " << meminfo.RegionSize << ", state " << meminfo.State << dec << endl;
1350
1351         Address objStart = (Address) meminfo.AllocationBase;
1352         Address probeAddr = (Address) meminfo.BaseAddress +  (Address) meminfo.RegionSize;
1353         Address objEnd = probeAddr;
1354         MEMORY_BASIC_INFORMATION probe;
1355         memset(&probe, 0, sizeof(MEMORY_BASIC_INFORMATION));
1356         do {
1357             objEnd = probeAddr;
1358             SIZE_T size2 = VirtualQueryEx(proc()->ProcessHandle_,
1359                                           (LPCVOID) ((Address)meminfo.BaseAddress + meminfo.RegionSize),
1360                                           &probe,
1361                                           sizeof(MEMORY_BASIC_INFORMATION));
1362                         cerr << "VirtualQuery reports baseAddr " << hex << probe.BaseAddress << ", allocBase " << probe.AllocationBase << ", size " << probe.RegionSize << ", state " << probe.State << dec << endl;
1363
1364                         probeAddr = (Address) probe.BaseAddress + (Address) probe.RegionSize;
1365         } while ((probe.AllocationBase == meminfo.AllocationBase) && // we're in the same allocation unit...
1366                         (objEnd != probeAddr)); // we're making forward progress
1367
1368
1369         // The size of the region returned by VirtualQueryEx is from BaseAddress
1370         // to the end, NOT from meminfo.AllocationBase, which is what we want.
1371         // BaseAddress is the start address of the page of the address parameter
1372         // that is sent to VirtualQueryEx as a parameter
1373         Address regionSize = objEnd - objStart;
1374         mal_printf("[%lx %lx] is valid region containing %lx and corresponding "
1375                "to no object, closest is object ending at %lx %s[%d]\n", 
1376                objStart, 
1377                objEnd,
1378                addr, closestObjEnd, FILE__,__LINE__);
1379         // read region into this PCProcess
1380         unsigned char* rawRegion = (unsigned char*) 
1381             ::LocalAlloc(LMEM_FIXED, regionSize);
1382                 if (!proc()->readDataSpace((void *)objStart,
1383                                                                    regionSize,
1384                                                                    rawRegion, true))
1385                 {
1386                         cerr << "Error: failed to read memory region [" << hex << objStart << "," << objStart + regionSize << "]" << dec << endl;
1387                         printSysError(GetLastError());
1388                         assert(0);
1389                 }
1390                 // set up file descriptor
1391         char regname[64];
1392         snprintf(regname,63,"mmap_buffer_%lx_%lx",
1393                     objStart, objEnd);
1394         fileDescriptor desc(string(regname), 
1395                             0, 
1396                             (HANDLE)0, 
1397                             (HANDLE)0, 
1398                             true, 
1399                             (Address)objStart,
1400                             (Address)regionSize,
1401                             rawRegion);
1402         mapped_object *obj = mapped_object::createMappedObject
1403             (desc,this,proc()->getHybridMode(),false);
1404         if (obj != NULL) {
1405             obj->setMemoryImg();
1406             //mapped_objects.push_back(obj);
1407             addMappedObject(obj);
1408
1409             obj->parse_img()->getOrCreateModule(
1410                 obj->parse_img()->getObject()->getDefaultModule());
1411             return obj;
1412         } else {
1413            fprintf(stderr,"Failed to create object (that was not backed by a file) at %lx\n", objStart);
1414         }
1415     }
1416     return NULL;
1417 }
1418 #endif
1419
1420
1421
1422 bool OS::executableExists(const std::string &file) {
1423    struct stat file_stat;
1424    int stat_result;
1425
1426    stat_result = stat(file.c_str(), &file_stat);
1427    if (stat_result == -1)
1428        stat_result = stat((file + std::string(".exe")).c_str(), &file_stat);
1429    return (stat_result != -1);
1430 }
1431
1432 #if 0
1433 func_instance *dyn_thread::map_initial_func(func_instance *ifunc) {
1434     if (!ifunc || strcmp(ifunc->prettyName().c_str(), "mainCRTStartup"))
1435         return ifunc;
1436
1437     //mainCRTStartup is not a real initial function.  Use main, if it exists.
1438     const pdvector<func_instance *> *mains = proc->getAOut()->findFuncVectorByPretty("main");
1439     if (!mains || !mains->size())
1440         return ifunc;
1441     return (*mains)[0];
1442 }
1443 #endif
1444
1445
1446 bool PCProcess::hasPassedMain() 
1447 {
1448    return true;
1449 }
1450
1451
1452 bool PCProcess::startDebugger()
1453 {
1454    return false;
1455 }
1456
1457 // Temporary remote debugger interface.
1458 // I assume these will be removed when procControlAPI is complete.
1459 bool OS_isConnected(void)
1460 {
1461     return true;  // We're always connected to the child on this platform.
1462 }
1463
1464 bool OS_connect(BPatch_remoteHost &remote)
1465 {
1466     return true;  // We're always connected to the child on this platform.
1467 }
1468
1469 bool OS_getPidList(BPatch_remoteHost &remote,
1470                    BPatch_Vector<unsigned int> &tlist)
1471 {
1472     return false;  // Not implemented.
1473 }
1474
1475 bool OS_getPidInfo(BPatch_remoteHost &remote,
1476                    unsigned int pid, std::string &pidStr)
1477 {
1478     return false;  // Not implemented.
1479 }
1480
1481 bool OS_disconnect(BPatch_remoteHost &remote)
1482 {
1483     return true;
1484 }
1485 #if 0
1486 mapped_object *PCProcess::createObjectNoFile(Address addr)
1487 {
1488     Address closestObjEnd = 0;
1489     for (unsigned i=0; i<mapped_objects.size(); i++)
1490     {
1491         if (addr >= mapped_objects[i]->codeAbs() &&
1492             addr <   mapped_objects[i]->codeAbs()
1493                    + mapped_objects[i]->imageSize())
1494         {
1495             fprintf(stderr,"createObjectNoFile called for addr %lx, "
1496                     "matching existing mapped_object %s %s[%d]\n",
1497                     mapped_objects[i]->fullName().c_str(), FILE__,__LINE__);
1498             return mapped_objects[i];
1499         }
1500         if (  addr >= ( mapped_objects[i]->codeAbs() +
1501                         mapped_objects[i]->imageSize() ) &&
1502             closestObjEnd < ( mapped_objects[i]->codeAbs() +
1503                                mapped_objects[i]->imageSize() ) )
1504         {
1505             closestObjEnd = mapped_objects[i]->codeAbs() +
1506                             mapped_objects[i]->imageSize();
1507         }
1508     }
1509
1510     Address testRead = 0;
1511
1512     // VirtualQueryEx rounds down to pages size, so we need to round up first.
1513     if (proc()->proc() && closestObjEnd % proc()->proc()->getMemoryPageSize())
1514     {
1515         closestObjEnd = closestObjEnd
1516             - (closestObjEnd % proc()->proc()->getMemoryPageSize())
1517             + proc()->proc()->getMemoryPageSize();
1518     }
1519     if (proc()->proc() && readDataSpace((void*)addr, proc()->getAddressWidth(),
1520                                         &testRead, false))
1521     {
1522         // create a module for the region enclosing this address
1523         MEMORY_BASIC_INFORMATION meminfo;
1524         memset(&meminfo,0, sizeof(MEMORY_BASIC_INFORMATION) );
1525         SIZE_T size = VirtualQueryEx(proc()->ProcessHandle_,
1526                                      (LPCVOID)addr, &meminfo,
1527                                      sizeof(MEMORY_BASIC_INFORMATION));
1528         assert(meminfo.State == MEM_COMMIT);
1529         // The size of the region returned by VirtualQueryEx is from BaseAddress
1530         // to the end, NOT from meminfo.AllocationBase, which is what we want.
1531         // BaseAddress is the start address of the page of the address parameter
1532         // that is sent to VirtualQueryEx as a parameter
1533         Address regionSize = (Address)meminfo.BaseAddress
1534             - (Address)meminfo.AllocationBase
1535             + (Address)meminfo.RegionSize;
1536         mal_printf("[%lx %lx] is valid region containing %lx and corresponding "
1537                "to no object, closest is object ending at %lx %s[%d]\n",
1538                meminfo.AllocationBase,
1539                ((Address)meminfo.AllocationBase) + regionSize,
1540                addr, closestObjEnd, FILE__,__LINE__);
1541         // read region into this PCProcess
1542         unsigned char* rawRegion = (unsigned char*)
1543             ::LocalAlloc(LMEM_FIXED, meminfo.RegionSize);
1544         assert( proc()->readDataSpace(meminfo.AllocationBase,
1545                                     regionSize, rawRegion, true) );
1546         // set up file descriptor
1547         char regname[64];
1548         snprintf(regname,63,"mmap_buffer_%lx_%lx",
1549                  ((Address)meminfo.AllocationBase),
1550                  ((Address)meminfo.AllocationBase) + regionSize);
1551
1552         fileDescriptor desc(string(regname),
1553                             0,
1554                             (HANDLE)0,
1555                             (HANDLE)0,
1556                             true,
1557                             (Address)meminfo.AllocationBase,
1558                             (Address)meminfo.RegionSize,
1559                             rawRegion);
1560         mapped_object *obj = mapped_object::createMappedObject
1561             (desc,this,proc()->getHybridMode(),false);
1562         if (obj != NULL) {
1563             mapped_objects.push_back(obj);
1564             addOrigRange(obj);
1565             return obj;
1566         }
1567     }
1568     return NULL;
1569 }
1570 #endif
1571
1572 bool PCProcess::dumpCore(std::string coreFile)
1573 {
1574         assert(0);
1575         return false;
1576 }
1577
1578 bool PCProcess::hideDebugger()
1579 {
1580         assert(0);
1581         return false;
1582 }
1583
1584 bool PCProcess::setMemoryAccessRights(Dyninst::Address start, Dyninst::Address size, int rights)
1585 {
1586         assert(0);
1587         return false;
1588 }
1589
1590 unsigned long PCProcess::setAOutLoadAddress(fileDescriptor &desc)
1591 {
1592         assert(0);
1593         return 0;
1594 }
1595
1596 bool PCEventMuxer::useCallback(Dyninst::ProcControlAPI::EventType et)
1597 {
1598     // This switch statement can be derived from the EventTypes and Events
1599     // table in the ProcControlAPI manual -- it states what Events are
1600     // available on each platform
1601     
1602     switch(et.code()) {
1603         case Dyninst::ProcControlAPI::EventType::Exit:
1604             switch(et.time()) {
1605                 case Dyninst::ProcControlAPI::EventType::Pre:
1606                 case Dyninst::ProcControlAPI::EventType::Post:
1607                                         return true;
1608                 default:
1609                     break;
1610             }
1611             break;
1612                 case Dyninst::ProcControlAPI::EventType::LWPDestroy:
1613             switch(et.time()) {
1614                 case Dyninst::ProcControlAPI::EventType::Pre:
1615                                         return true;
1616                 default:
1617                     break;
1618             }
1619             break;
1620     }
1621
1622     return false;
1623 }
1624
1625 bool PCEventMuxer::useBreakpoint(Dyninst::ProcControlAPI::EventType et)
1626 {
1627         return false;
1628 }
1629
1630 bool PCEventHandler::isKillSignal(int signal)
1631 {
1632         // Kill on Windows does not generate a signal
1633         return false;
1634 }
1635 bool PCEventHandler::isCrashSignal(int signal)
1636 {
1637         switch(signal)
1638         {
1639         case EXCEPTION_ACCESS_VIOLATION:
1640         case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
1641         case EXCEPTION_DATATYPE_MISALIGNMENT:
1642         case EXCEPTION_FLT_DIVIDE_BY_ZERO:
1643         case EXCEPTION_FLT_INVALID_OPERATION:
1644         case EXCEPTION_ILLEGAL_INSTRUCTION:
1645         case EXCEPTION_IN_PAGE_ERROR:
1646         case EXCEPTION_INT_DIVIDE_BY_ZERO:
1647         case EXCEPTION_NONCONTINUABLE_EXCEPTION:
1648         case EXCEPTION_PRIV_INSTRUCTION:
1649         case EXCEPTION_STACK_OVERFLOW:
1650                 return true;
1651         }
1652         return false;
1653 }
1654 bool PCEventHandler::shouldStopForSignal(int signal)
1655 {
1656         switch(signal)
1657         {
1658                 case EXCEPTION_BREAKPOINT:
1659                         return true;
1660         }
1661         return false;
1662 }
1663 bool PCEventHandler::isValidRTSignal(int signal, PCEventHandler::RTBreakpointVal breakpointVal,
1664                                                                          Dyninst::Address arg1, int status)
1665 {
1666         if(signal == EXCEPTION_BREAKPOINT)
1667         {
1668         if( breakpointVal == NormalRTBreakpoint ) {
1669             if( (status != DSE_forkExit) || (arg1 != 0) ) return true;
1670
1671             proccontrol_printf("%s[%d]: child received signal %d\n",
1672                     FILE__, __LINE__, EXCEPTION_BREAKPOINT);
1673         } else if( breakpointVal == SoftRTBreakpoint ) {
1674             if( status == DSE_forkExit ) {
1675                 if( arg1 == 0 ) return true;
1676
1677                 proccontrol_printf("%s[%d]: parent process received SIGSTOP\n",
1678                         FILE__, __LINE__);
1679             }else{
1680                 proccontrol_printf("%s[%d]: SIGSTOP wasn't due to fork exit\n",
1681                         FILE__, __LINE__);
1682             }
1683         } else {
1684             proccontrol_printf("%s[%d]: mismatch in signal for breakpoint type\n",
1685                     FILE__, __LINE__);
1686         }
1687         } else {
1688         proccontrol_printf("%s[%d]: signal wasn't sent by RT library\n",
1689                 FILE__, __LINE__);
1690     }
1691
1692         return false;
1693 }
1694
1695 bool PCProcess::usesDataLoadAddress() const
1696 {
1697         return false;
1698 }
1699 bool PCProcess::setEnvPreload(std::vector<std::string> &envp, std::string fileName)
1700 {
1701         // We don't LD_PRELOAD on Windows
1702         return true;
1703 }
1704
1705 void PCProcess::redirectFds(int stdin_fd, int stdout_fd, int stderr_fd, std::map<int,int> &result)
1706 {
1707         // Not implemented on existing dyninst-on-windows, just skip
1708         return;
1709 }
1710 std::string PCProcess::createExecPath(const std::string &file, const std::string &dir)
1711 {
1712         return dir + file;
1713 }
1714
1715 bool PCProcess::multithread_capable(bool ignoreIfMtNotSet)
1716 {
1717         return true;
1718 }
1719
1720 bool PCProcess::copyDanglingMemory(PCProcess *parent)
1721 {
1722         assert(0);
1723         return false;
1724 }
1725
1726 bool PCProcess::instrumentMTFuncs()
1727 {
1728         // This is not needed on Windows, as we get thread events directly.
1729         return true;
1730 }
1731
1732 bool PCProcess::getExecFileDescriptor(std::string filename, bool waitForTrap, fileDescriptor &desc)
1733 {
1734         Address mainFileBase = 0;
1735         Dyninst::ProcControlAPI::ExecFileInfo* efi = pcProc_->getExecutableInfo();
1736
1737         desc = fileDescriptor(filename, efi->fileBase, efi->fileBase, false);
1738         desc.setHandles(efi->processHandle, efi->fileHandle);
1739
1740         delete efi;
1741         return true;
1742 }
1743
1744 bool PCProcess::skipHeap(const heapDescriptor &heap)
1745 {
1746         return false;
1747 }
1748
1749 bool PCProcess::postRTLoadCleanup()
1750 {
1751         return true;
1752 }
1753
1754 unsigned long PCProcess::findFunctionToHijack()
1755 {
1756         return 0;
1757 }
1758
1759 bool PCProcess::postRTLoadRPC()
1760 {
1761     Address loadDyninstLibAddr = getAOut()->parse_img()->getObject()->getEntryOffset() + getAOut()->getBaseAddress();
1762         Address LoadLibAddr;
1763     int_symbol sym;
1764     
1765
1766     if (!getSymbolInfo("_LoadLibraryA@4", sym) &&
1767         !getSymbolInfo("_LoadLibraryA", sym) &&
1768         !getSymbolInfo("LoadLibraryA", sym))
1769         {
1770             printf("unable to find function LoadLibrary\n");
1771             assert(0);
1772         }
1773     LoadLibAddr = sym.getAddr();
1774     assert(LoadLibAddr);
1775
1776     char ibuf[BYTES_TO_SAVE];
1777     memset(ibuf, '\0', BYTES_TO_SAVE);//ccw 25 aug 2000
1778     char *iptr = ibuf;
1779     
1780     // Code overview:
1781     // Dynininst library name
1782     //    Executable code begins here:
1783     // Push (address of dyninst lib name)
1784     // Call LoadLibrary
1785     // Pop (cancel push)
1786     // Trap
1787     
1788     
1789     // push nameAddr ; 5 bytes
1790     *iptr++ = (char)0x68; 
1791     // Argument for push
1792         int* relocAddr = (int*)(iptr);
1793     iptr += sizeof(int);
1794     
1795     int offsetFromBufferStart = (int)iptr - (int)ibuf;
1796     offsetFromBufferStart += 5; // Skip next instruction as well.
1797     // call LoadLibrary ; 5 bytes
1798     *iptr++ = (char)0xe8;
1799     
1800     // Jump offset is relative
1801     *(int *)iptr = LoadLibAddr - (loadDyninstLibAddr + 
1802                                   offsetFromBufferStart); // End of next instruction
1803     iptr += sizeof(int);
1804     
1805     
1806     // add sp, 4 (Pop)
1807     *iptr++ = (char)0x83; *iptr++ = (char)0xc4; *iptr++ = (char)0x04;
1808     
1809     // int3
1810     *iptr = (char)0xcc;
1811     
1812     int offsetToTrap = (int) iptr - (int) ibuf;
1813         strcpy(iptr+1, dyninstRT_name.c_str());
1814     *(int *)relocAddr = offsetToTrap + 1 + loadDyninstLibAddr; // string at end of code
1815         void* result;
1816         postIRPC(ibuf, BYTES_TO_SAVE, NULL, false, NULL, true, &result, false, false, loadDyninstLibAddr);
1817
1818    return true;
1819 }
1820
1821
1822 AstNodePtr PCProcess::createLoadRTAST()
1823 {
1824         assert(!"Unused on Windows");
1825         return AstNodePtr();
1826 }
1827
1828 inferiorHeapType PCProcess::getDynamicHeapType() const
1829 {
1830         return anyHeap;
1831 }
1832
1833 mapped_object* PCProcess::createObjectNoFile(Dyninst::Address addr)
1834 {
1835         assert(0);
1836         return false;
1837 }
1838
1839
1840 void OS::get_sigaction_names(std::vector<std::string> &)
1841 {
1842         assert(0 && "Unimplemented");
1843 }