Compilation fixes for gcc 3.1, MSVC 6.0 & 7.0
[dyninst.git] / dyninstAPI / src / pdwinnt.C
1 /*
2  * Copyright (c) 1996-2002 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  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 // $Id: pdwinnt.C,v 1.53 2002/06/17 17:04:04 gaburici Exp $
43 #include <iomanip.h>
44 #include "dyninstAPI/src/symtab.h"
45 #include "common/h/headers.h"
46 #include "dyninstAPI/src/os.h"
47 #include "dyninstAPI/src/process.h"
48 #include "dyninstAPI/src/pdThread.h"
49 #include "dyninstAPI/src/stats.h"
50 #include "common/h/Types.h"
51 #include "dyninstAPI/src/showerror.h"
52 #include "dyninstAPI/src/instPoint.h"
53
54 #ifndef BPATCH_LIBRARY
55 #include "paradynd/src/main.h"
56 #include "paradynd/src/init.h"
57 #endif
58
59 #ifdef BPATCH_LIBRARY
60 /* XXX This is only needed for emulating signals. */
61 #include "BPatch_thread.h"
62 #include "nt_signal_emul.h"
63 #endif
64
65 // prototypes of functions used in this file
66 static string GetLoadedDllImageName( process* p, const DEBUG_EVENT& ev );
67
68
69
70 //ccw  27 july 2000 : dummy methods to get the thing to compile before i add
71 //the remoteDevice : 29 mar 2001
72 #ifdef mips_unknown_ce2_11
73 #include <stdio.h> //for wprintf
74
75 void kludgeWCHAR(const char *str8, WCHAR *str16){
76         int k;
77
78         k=0;
79         while(str8[k]!='\0'){
80                 str16[k] = str8[k];
81                 k++;
82         }
83         str16[k] = '\0';
84         str16[k+1]='\0';
85
86 }
87
88 //int GetThreadContext(HANDLE hThread, w32CONTEXT *lpContext){
89 //      return 0;
90 //}
91
92 //int SetThreadContext(HANDLE hThread, const w32CONTEXT *lpContext){
93 //      return 0;
94 //}
95 #endif
96
97 extern bool isValidAddress(process *proc, Address where);
98 extern process *findProcess(int);
99
100 //HANDLE kludgeProcHandle;
101
102 void printSysError(unsigned errNo) {
103     char buf[1000];
104     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNo, 
105                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
106                   buf, 1000, NULL);
107     fprintf(stderr, "*** System error [%d]: %s\n", errNo, buf);
108     fflush(stderr);
109 }
110
111
112 // check if a file handle is for kernel32.dll
113 static bool kludge_isKernel32Dll(HANDLE fileHandle, string &kernel32Name) {
114     static DWORD IndxHigh, IndxLow;
115     static bool firstTime = true;
116     BY_HANDLE_FILE_INFORMATION info;
117     static string kernel32Name_;
118
119     if (firstTime) {
120         HANDLE kernel32H;
121         firstTime = false;
122         char sysRootDir[MAX_PATH+1];
123         if (GetSystemDirectory(sysRootDir, MAX_PATH) == 0)
124           assert(0);
125         kernel32Name_ = string(sysRootDir) + "\\kernel32.dll";
126         kernel32H = CreateFile(kernel32Name_.c_str(), GENERIC_READ, 
127                                FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
128         assert(kernel32H);
129         if (!GetFileInformationByHandle(kernel32H, &info)) {
130             printSysError(GetLastError());
131             assert(0);
132         }
133         IndxHigh = info.nFileIndexHigh;
134         IndxLow = info.nFileIndexLow;
135         CloseHandle(kernel32H);
136     }
137
138     if (!GetFileInformationByHandle(fileHandle, &info))
139         return false;
140
141     if (info.nFileIndexHigh==IndxHigh && info.nFileIndexLow==IndxLow) {
142       kernel32Name = kernel32Name_;
143       return true;
144     }
145     return false;
146 }
147
148
149 void dumpMem(process *p, void * addr, unsigned nbytes) {
150     unsigned char *buf = new unsigned char[nbytes];
151     memset(buf, 0, nbytes);
152     function_base *f;
153     assert(buf);
154
155     if (f = p->findFuncByAddr((Address)addr))
156     {
157         printf("Function %s, addr=0x%lx, sz=%d\n", 
158                 f->prettyName().c_str(),
159                 f->getAddress(p),
160                 f->size());
161     }
162     p->readDataSpace((void *)((unsigned)addr-32), nbytes, buf, true);
163     printf("## 0x%lx:\n", (unsigned)addr-32);
164     for (unsigned u = 0; u < nbytes; u++)
165     {
166             printf(" %x", buf[u]);
167     }
168     printf( "\n" );
169     p->readDataSpace(addr, nbytes, buf, true);
170     printf("## 0x%lx:\n", addr);
171     for (unsigned u1 = 0; u1 < nbytes; u1++)
172     {
173             printf(" %x", buf[u1]);
174     }
175     printf( "\n" );
176 }
177
178
179
180 //
181 // walkStackFrame
182 //
183 // Try to walk one more frame in the stack of the indicated process.
184 // Assumes that the STACKFRAME argument is either the result
185 // from a previous StackWalk call, or has been initialized 
186 // to the context from a GetThreadContext call.
187 //
188 inline
189 BOOL
190 walkStackFrame( HANDLE hProc, HANDLE hThread, STACKFRAME* psf )
191 {
192         return StackWalk( IMAGE_FILE_MACHINE_I386,
193                         hProc,
194                         hThread,
195                                 psf,
196                         NULL,
197                                 NULL,
198                         SymFunctionTableAccess,
199                         SymGetModuleBase,
200                                 NULL);
201 }
202
203
204 //
205 // findFunctionFromAddress
206 // 
207 // Finds the function corresponding to the given address.
208 // Handles situations where the address is within instrumentation,
209 // and situations where the function has been relocated.
210 //
211 function_base*
212 findFunctionFromAddress( process* proc, Address addr )
213 {
214     function_base* fp = NULL;
215
216     instPoint* ip = findInstPointFromAddress( proc, addr );
217     if( ip != NULL )
218     {
219         // the address is within a tramp
220         // find the function in which the tramp was installed
221         fp = (function_base*)( ip->iPgetFunction() );
222     }
223     else
224     {
225         // the address isn't within a tramp
226         // check if it is a known function (relocated or otherwise)
227         fp = (function_base*)( proc->findFuncByAddr( addr ) );
228     }
229     return fp;
230 }
231
232
233
234 #ifdef i386_unknown_nt4_0 //ccw 27 july 2000 : 29 mar 2001
235 //
236 // process::walkStack
237 //
238 // Walk the stack of thread 0 of our process.
239 // We assume that a trace is complete if we get to a main function
240 // (main, WinMain, or some variant of mainCRTStartup).
241 // If we can't get a complete trace, we return an empty vector.
242 //
243 // Note that this routine does *not* handle stack walks for multi-threaded
244 // programs - it only handles stack walks in thread zero.
245 // When we support multithreaded apps under Windows, this routine could
246 // take a thread parameter that specifies which thread to use.
247 //
248 // Also, note that we have *not* been able to find a mechanism that 
249 // can perform stack walks reliably for apps compiled with the FPO 
250 // (frame pointer omission) optimization.  Even if the FPO data is
251 // available, the Win32 StackWalk call either skips functions or bottoms
252 // out the stack too early.  Unfortunately, this means that we require
253 // that the app under study *not* use the FPO optimization.  (Specify /Oy- 
254 // for the VC++ compiler to turn this optimization off.)
255 //
256
257 bool process::walkStack(Frame /* currentFrame */, vector<Frame> &stackWalk, bool paused)
258 {
259     bool needToCont = paused ? false : (status() == running);
260
261 #ifndef BPATCH_LIBRARY
262     startTimingStackwalk();
263 #endif
264
265 #ifdef DEBUG_STACKWALK
266     cout << "\n<stack>" << endl;
267 #endif // DEBUG_STACKWALK
268
269     // pause the application if necessary
270     if( !paused && !pause() )
271     {
272         // pause failed...give up
273         cerr << "walkStack: pause failed" << endl;
274
275 #ifndef BPATCH_LIBRARY
276         stopTimingStackwalk();
277 #endif
278         return false;
279     }
280
281     // establish the current execution context
282     CONTEXT cont;
283     HANDLE hThread = (HANDLE)threads[0]->get_handle();
284
285     cont.ContextFlags = CONTEXT_FULL;
286     if (!GetThreadContext(hThread, &cont))
287     {
288         cerr << "walkStack: GetThreadContext failed:" << GetLastError()
289              << endl;
290
291 #ifndef BPATCH_LIBRARY
292         stopTimingStackwalk();
293 #endif
294         return false;
295     }
296
297     STACKFRAME sf;
298     ZeroMemory( &sf, sizeof(STACKFRAME) );
299     sf.AddrPC.Offset = cont.Eip;
300     sf.AddrPC.Mode = AddrModeFlat;
301     sf.AddrFrame.Offset = cont.Ebp;
302     sf.AddrFrame.Mode = AddrModeFlat;
303     sf.AddrStack.Offset = cont.Esp;
304     sf.AddrStack.Mode = AddrModeFlat;
305     sf.AddrReturn.Mode = AddrModeFlat;
306
307     // walk the stack, frame by frame
308     // we use the Win32 StackWalk function to automatically
309     // handle compiler optimizations, especially FPO optimizations
310     bool done = false;
311     bool reachedMain = false;
312
313     while( !done ) {
314         STACKFRAME saved_sf = sf;
315         BOOL walked;
316         ADDRESS patchedAddrReturn;
317         ADDRESS patchedAddrPC;
318         instPoint* ip = NULL;
319         function_base* fp = NULL;
320
321         // set defaults for return address and PC
322         patchedAddrReturn = saved_sf.AddrReturn;
323         patchedAddrPC = saved_sf.AddrPC;
324
325         // try to step through the stack using the current information
326         walked = walkStackFrame((HANDLE)getProcFileDescriptor(), hThread, &sf);
327
328         if( !walked && (GetLastError() == ERROR_INVALID_ADDRESS) ) {
329
330           // try to patch the return address, in case it is outside
331           // of the original text of the process.  It might be outside
332           // the original text if the function has been relocated, or
333           // if it represents a return from a call instruction that
334           // has been relocated to a base tramp.
335           // we first try to patch the return address only, because it
336           // is most likely that the return address only is out of the
337           // original text space.  Once we process the first stack
338           // frame, it appears that the StackWalk function transfers 
339           // the return address from the STACKFRAME struct to the PC,
340           // so once we've gotten a valid return address in a 
341           // STACKFRAME, the PC will be within the original text after
342           // the StackWalk
343           sf = saved_sf;
344           fp = findFunctionFromAddress( this, sf.AddrReturn.Offset );
345
346           if( fp != NULL ) {
347             // because StackWalk seems to support it, we simply use 
348             // the address of the function itself rather than
349             // trying to do the much more difficult task of finding
350             // the original address of the relocated instruction
351             patchedAddrReturn.Offset = fp->addr();
352             sf.AddrReturn = patchedAddrReturn;
353           }
354
355           // retry the stack step
356           walked = 
357               walkStackFrame((HANDLE)getProcFileDescriptor(), hThread, &sf);
358         }
359
360         if( !walked && (GetLastError() == ERROR_INVALID_ADDRESS) ) {
361
362           // patching the return address alone didn't work.
363           // try patching the return address and the PC
364           sf = saved_sf;
365           fp = findFunctionFromAddress( this, sf.AddrPC.Offset );
366
367           if( fp != NULL ) {
368
369             // because StackWalk seems to support it, we simply use 
370             // the address of the function itself rather than
371             // trying to do the much more difficult task of finding
372             // the original address of the relocated instruction
373             patchedAddrPC.Offset = fp->addr();
374             sf.AddrPC = patchedAddrPC;
375           }
376
377           // use the patched return address we calculated above
378           sf.AddrReturn = patchedAddrReturn;
379
380           // retry the stack step
381           walked = 
382               walkStackFrame((HANDLE)getProcFileDescriptor(), hThread, &sf);
383         }
384
385         if( !walked && (GetLastError() == ERROR_INVALID_ADDRESS) )
386         {
387
388           // patching both addresses didn't work
389           //
390           // try patching the PC only
391           sf = saved_sf;
392           sf.AddrPC = patchedAddrPC;
393
394           // retry the stack step
395           walked = 
396               walkStackFrame((HANDLE)getProcFileDescriptor(), hThread, &sf);
397         }
398
399
400         // by now we've tried all of our tricks to handle the stack 
401         // frame if we haven't succeeded by now, we're not going to be
402         // able to handle this frame
403         if( walked ) {
404           
405           Address pc = NULL;
406           
407           // save the PC for this stack frame
408           // make sure we use the original address in case
409           // it was outside the original text of the process
410           if( saved_sf.AddrReturn.Offset == 0 ) {
411             
412             // this was the first stack frame, so we had better
413             // use the original PC
414             pc = saved_sf.AddrPC.Offset;
415             
416           } else {
417             
418             // this was not the first stack frame
419             // use the original return address
420             pc = saved_sf.AddrReturn.Offset;
421           }
422         
423           stackWalk.push_back(Frame(pc, 0, getPid(), NULL, 0, false));
424
425           // check whether we reached a known "main" function
426           // we consider it a complete stack walk iff we see
427           // a "main" function on the stack
428           //
429           // note: this criteria is not likely to be generally 
430           //       applicable - it will fail for walking stacks 
431           //       in non-primary threads
432           
433           fp = findFunctionFromAddress( this, pc );
434           
435           if( (fp != NULL) && ((fp == getMainFunction()) || 
436                                (fp->prettyName() == "mainCRTStartup") ||
437                                (fp->prettyName() == "wmainCRTStartup")) ) {
438             
439             reachedMain = true;
440           }
441             
442 #ifdef DEBUG_STACKWALK
443           cout << "0x" << setw(8) << setfill('0') << hex << pc << ": ";
444           
445           if( fp != NULL ) {
446             cout << fp->prettyName();
447           } else {
448             cout << "<unknown>";
449           }
450           
451           if( sf.AddrPC.Offset != pc ) {
452             cout << " (originally 0x" << setw(8) << setfill('0') 
453                  << hex << sf.AddrPC.Offset << ")";
454           }
455           cout << endl;
456 #endif
457           
458         } else {
459           // we tried everything we know to recover - we'll have 
460           // to fail
461           done = true;
462         }
463         
464     }
465
466     // handle incomplete stack walks
467     // (defined as a stack on which the main function did not appear)
468     if( !reachedMain ) {
469       stackWalk.resize(0);
470     } else {
471       stackWalk.push_back(Frame());
472     }
473
474     // resume the application if needed
475     if( !paused && needToCont ) {
476         if( !continueProc() ) {
477             cerr << "walkStack: continueProc failed" << endl;
478         }
479     }
480     
481 #ifndef BPATCH_LIBRARY
482     stopTimingStackwalk();
483 #endif
484
485     return true;
486 }
487 #endif
488
489 #if defined(mips_unknown_ce2_11) //ccw 6 feb 2001 : 29 mar 2001
490 //ccw 6 feb 2001 : windows CE does not have the NT walkStack function
491 //so we use this one.
492
493 void process::walkStack(Frame currentFrame, vector<Frame> &stackWalk, 
494                         bool paused)
495 {
496   bool needToCont = paused ? false : (status() == running);
497   
498   if (pause()) {
499     Address spOld = 0xffffffff;
500
501     while (!currentFrame.isLastFrame()) {
502       Address spNew = currentFrame.getSP(); // ccw 6 feb 2001 : should get SP?
503       
504       // successive frame pointers might be the same (e.g. leaf functions)
505       if (spOld < spNew) {
506         
507         // not moving up stack
508         if (!paused && needToCont && !continueProc()) {
509           cerr << "walkStack: continueProc failed" << endl;
510         }
511         
512         vector<Address> ev; // empty vector
513         pcs = ev;
514         
515         return;
516       }
517       
518       spOld = spNew;
519       
520       Address next_pc = currentFrame.getPC();
521       stackWalk.push_back(currentFrame);
522
523       //ccw 6 feb 2001 : at this point, i need to use the 
524       //list of functions parsed from the debug symbols to
525       //determine the frame size for each function and find the 
526       //return value for each (which is the previous fir value)
527       currentFrame = currentFrame.getCallerFrame(this); 
528       
529     }
530     
531     stackWalk.push_back(currentFrame);
532   }
533
534   if (!paused && needToCont) {
535      if (!continueProc()){
536         cerr << "walkStack: continueProc failed" << endl;
537      }
538   }  
539
540   return;
541 }
542 #endif
543
544 /* 
545    Loading libDyninstRT.dll
546
547    We load libDyninstRT.dll dynamically, by inserting code into the
548    application to call LoadLibraryA. We don't use the inferior RPC
549    mechanism from class process because it already assumes that
550    libdyninst is loaded (it uses the inferior heap).
551    Instead, we use a simple inferior call mechanism defined below
552    to insert the code to call LoadLibraryA("libdyninstRT.dll").
553  */
554
555 Address loadDyninstDll(process *p, char Buffer[LOAD_DYNINST_BUF_SIZE]) {
556     Address codeBase = p->getImage()->codeOffset();
557         Address hackLoadLibAddr = 0x01f9ac30; //ccw 2 feb 2001 : HACK
558
559     Address LoadLibBase;
560     Address LoadLibAddr;
561     Symbol sym;
562         //ccw 22 aug 2000 : this function hand codes x86 op codes!!!!
563         //change these to mips instructions!!!
564
565 #ifdef mips_unknown_ce2_11 //ccw 14 aug 2000 : 29 mar 2001
566
567         //ccw 2 feb 2001
568         //this is a terrible hack.  i know that LoadLibrary is 0xac30 bytes from
569         //the base address of coredll.dll from emprical evidence.  i have no
570         //debug symbols for coredll.dll to prove this dynamically though....
571         
572         for(int i=0; i< (p->sharedObjects())->size();i++){
573                 
574                 if((*p->sharedObjects())[i]->getName() == "coredll.dll" ){
575                         hackLoadLibAddr = (*p->sharedObjects())[i]->getBaseAddress() + 0x0000bf1c;
576                         //0x0000ac30; //HACK 24 apr 2001
577                 }
578         }
579
580 #if 0 
581         //ccw 2 feb 2001 : this is taken out because the above
582         //loop determines the correct address for LoadLibrary
583         //this statement requires LoadLibrary to show up in
584         //the map file of the mutatee, which only happens if
585         //the mutatee explicitly calls LoadLibrary
586         if (!p->getSymbolInfo("LoadLibraryW", sym, LoadLibBase)) {
587
588          if( !p->getSymbolInfo( "__imp_LoadLibraryW", sym, LoadLibBase )) //ccw 1 oct 2000, not a good idea
589          {
590                 printf("unable to find function LoadLibrary\n");
591                 assert(0);
592         }
593     }
594 #endif 
595
596 #else
597         if (!p->getSymbolInfo("_LoadLibraryA@4", sym, LoadLibBase)) {
598         if( !p->getSymbolInfo( "_LoadLibraryA", sym, LoadLibBase ))
599         {
600                 printf("unable to find function LoadLibrary\n");
601                 assert(0);
602         }
603     }
604 #endif
605
606 #ifndef mips_unknown_ce2_11 //ccw 2 feb 2001
607     LoadLibAddr = sym.addr() + LoadLibBase;
608     assert(LoadLibAddr);
609 #endif
610
611     char ibuf[LOAD_DYNINST_BUF_SIZE];
612     char *iptr = ibuf;
613         memset(ibuf, '\0', LOAD_DYNINST_BUF_SIZE);//ccw 25 aug 2000
614
615 #ifdef mips_unknown_ce2_11 //ccw 22 aug 2000
616         //the following are the instructions to load libdyninstRT_API.dll
617         
618         //ccw 2 oct 2000
619         //the instructions we need to generate are:
620         // lui $a0,hi16(codeBase)  # codeBase contains libBuf
621         // ori $a0,lo16(codeBase)
622         // lui $t0, hi16(hackLoadLibAddr)
623         // ori $t0, lo16(hackLoadLibAddr)
624         // jalr $t0
625         // nop
626         // nop
627         // break
628         // nop
629         // nop
630         // nop
631         // where libBuf is the location of the string containing the name of the dll
632         // in the remote process's memory
633
634         WCHAR libBuf[] = L"\\libdyninstAPI_RT.dll";
635         BYTE instBuff[4]; //buffer for the instruction to write to memory;
636
637         //lay the name of the DLL to load into memory, UNICODE!
638         assert(memcpy(iptr, (char*)libBuf, 42));
639         iptr +=42;
640         memset(iptr, '\0', 2);
641         iptr +=2;
642
643         //LUI //ccw 2 oct 2000
644         instBuff[0]=((char*) &codeBase)[2];
645         instBuff[1]=((char*) &codeBase)[3];
646         instBuff[2]=0x04;
647         instBuff[3]=0x3C;
648         memcpy(iptr, (char*) &instBuff, 4);
649         iptr +=4;
650
651         //ORI //ccw 2 oct 2000
652         instBuff[0]=((char*) &codeBase)[0];
653         instBuff[1]=((char*) &codeBase)[1];
654         instBuff[2]=0x84;
655         instBuff[3]=0x34;
656         memcpy(iptr, (char*) &instBuff, 4);
657         iptr +=4;
658
659         //LUI //ccw 2 feb 2001
660         instBuff[0]=((char*) &hackLoadLibAddr)[2];
661         instBuff[1]=((char*) &hackLoadLibAddr)[3];
662         instBuff[2]=0x08;
663         instBuff[3]=0x3C;
664         memcpy(iptr, (char*) &instBuff, 4);
665         iptr +=4;
666
667         //ORI //ccw 2 feb 2001
668         instBuff[0]=((char*) &hackLoadLibAddr)[0];
669         instBuff[1]=((char*) &hackLoadLibAddr)[1];
670         instBuff[2]=0x08;
671         instBuff[3]=0x35;
672         memcpy(iptr, (char*) &instBuff, 4);
673         iptr +=4;
674
675         //JALR
676         instBuff[0]=0x09;
677         instBuff[1]=0xf8;
678         instBuff[2]=0x00;
679         instBuff[3]=0x01;
680         memcpy(iptr, (char*) &instBuff, 4);
681         iptr +=4;
682
683
684         //NOP
685         instBuff[0]=0x00;
686         instBuff[1]=0x00;
687         instBuff[2]=0x00;
688         instBuff[3]=0x00;
689         memcpy(iptr, (char*) &instBuff, 4);
690         iptr +=4;
691
692         //NOP
693         instBuff[0]=0x00;
694         instBuff[1]=0x00;
695         instBuff[2]=0x00;
696         instBuff[3]=0x00;
697         memcpy(iptr, (char*) &instBuff, 4);
698         iptr +=4;
699
700
701         //DebugBreak();
702         instBuff[0]=0x0D;
703         instBuff[1]=0x00;
704         instBuff[2]=0x00;
705         instBuff[3]=0x00;
706         memcpy(iptr, (char*) &instBuff, 4);
707         iptr +=4;
708
709
710         //ccw 25 aug 2000 : throw some NOPs after the debugBreak just in case!
711         //NOP
712         instBuff[0]=0x00;
713         instBuff[1]=0x00;
714         instBuff[2]=0x00;
715         instBuff[3]=0x00;
716         memcpy(iptr, (char*) &instBuff, 4);
717         iptr +=4;
718         
719         memcpy(iptr, (char*) &instBuff, 4);
720         iptr +=4;
721
722         memcpy(iptr, (char*) &instBuff, 4);
723         iptr +=4;
724
725 #else
726
727     // push nameAddr ; 5 bytes
728     *iptr++ = (char)0x68; 
729     *(int *)iptr = codeBase + 14; 
730     iptr += sizeof(int);
731
732     // call LoadLibrary ; 5 bytes
733     *iptr++ = (char)0xe8;
734     // offset relative to next instruction (address codeBase+10)
735     *(int *)iptr = LoadLibAddr - (codeBase + 10);
736     iptr += sizeof(int);
737
738     // add sp, 4
739     *iptr++ = (char)0x83; *iptr++ = (char)0xc4; *iptr++ = (char)0x04;
740
741     // int3
742     *iptr++ = (char)0xcc;
743
744     if (!process::dyninstName.length())
745         // check for an environment variable
746 #ifdef BPATCH_LIBRARY  // dyninstAPI loads a different run-time library
747         process::dyninstName = getenv("DYNINSTAPI_RT_LIB");
748 #else
749         process::dyninstName = getenv("PARADYN_LIB");
750 #endif
751
752     if (!process::dyninstName.length())
753         // if environment variable unset, use the default name/strategy
754 #ifdef BPATCH_LIBRARY
755         process::dyninstName = "libdyninstAPI_RT.dll";
756 #else
757         process::dyninstName = "libdyninstRT.dll";
758 #endif
759         
760     // make sure that directory separators are what LoadLibrary expects
761     strcpy(iptr, process::dyninstName.c_str());
762     for (unsigned int i=0; i<strlen(iptr); i++)
763         if (iptr[i]=='/') iptr[i]='\\';
764 #endif
765
766     p->readDataSpace((void *)codeBase, LOAD_DYNINST_BUF_SIZE, Buffer, false);
767     p->writeDataSpace((void *)codeBase, LOAD_DYNINST_BUF_SIZE, ibuf);
768
769 #ifdef mips_unknown_ce2_11 //ccw 22 aug 2000
770         //add to process, then to remoteDevice
771     return codeBase+44;//this is for the offset of the string!
772 #else
773         return codeBase;
774 #endif
775 }
776
777
778
779 // osTraceMe is not needed in Windows NT
780 void OS::osTraceMe(void) {}
781
782
783 #ifndef BPATCH_LIBRARY
784 void checkProcStatus() {
785     int wait_status;
786     extern void doDeferredRPCs();
787
788     process::waitProcs(&wait_status);
789     doDeferredRPCs();
790 }
791 #endif
792
793
794 // ccw 2 may 2001 win2k fixes
795 // when you launch a process to be debugged with win2k (as in createProcess)
796 // the system sends you back at least two debug events before starting the
797 // process.  a debug event is also sent back for every dll that is loaded
798 // prior to starting main(), these include ntdll.dll and kernel32.dll and any
799 // other dlls the process needs that are not loaded with an explicit call
800 // to LoadLibrary().
801 //
802 // dyninst catches the first debug event (CREATE_PROCESS) and initializes
803 // various process specific data structures.
804 // dyninst catches the second debug event (an EXCEPTION_DEBUG_EVENT) and used this
805 // event as a trigger to put in the bit of code that forced the mutatee to
806 // load libdyninstAPI_RT.dll.  In win2k, this does not work.  The bit of code
807 // is run and the trailing DebugBreak is caught and handled but the Dll will not
808 // be loaded.  The EXCEPTION_DEBUG_EVENT must be handled and continued from before
809 // LoadLibrary will perform correctly.
810 //
811 // the fix for this is to handle this EXCEPTION_DEBUG_EVENT, and put a DebugBreak (0xcc) 
812 // at the beginning of main() in the mutatee.  catching that DebugBreak allows dyninst
813 // to write in the bit of code used to load the libdyninstAPI_RT.dll.
814 //
815 // after this, dyninst previously instrumented the mutatee to force the execution of
816 // DYNINSTinit() in the dll.  in order to take out this bit of complexity, the DllMain()
817 // function in the dll, which is run upon loading the dll, is used to automatically call
818 // DYNINSTinit().
819 //
820 // DYNINSTinit() takes two parameters, a flag denoting how dyninst attached to this process
821 // and the pid of the mutator.  These are passed from the mutator to the mutatee by
822 // finding a variable in the dll and writing the correct values into the mutatee's
823 // address space.  When a Dll is loaded, a LOAD_DLL debug event is thrown before the
824 // execution of DllMain(), so dyninst catches this event, writes the necessary values
825 // into the mutatee memory, then lets DllMain() call DYNINSTinit().
826 // the DebugBreak() at the end of DYNINSTinit() is now removed for NT/win2K
827 //
828 // the bit of code inserted to load the dll fires a DebugBreak() to signal that it is
829 // done. dyninst catches this, patches up the code that was used to load the dll, 
830 // replaces what was overwritten in main() and resets the instruction pointer (EIP)
831 // to the beginning of main().
832
833 int secondBkpt = 0; //ccw 30 apr 2001 : used to signal that we have seen the first EXCEPTION_DEBUG_EVENT
834 int mungeAddr = 0; //ccw 2 may 2001 : used to track where we wrote the LoadLibrary code
835 byte savedOpCode[256]; //ccw 2 may 2001 : the op code we overwrite in main()
836 byte newOpCode[256];   // ccw 27 june 2001 : the op code we add in main()
837 //ccw 6 july 2001 the two above arrays are 256 bytes because writing one byte does not always cause the
838 //instruction cache to be reloaded. 
839
840 Address mainAddr=0 ; //ccw 2 may 2001 : the address of main()
841
842 //ccw 2 may 2001 : the following function sets the varible name to the value given.
843 // returns true if it is successful.
844 bool setVariable(process* p, string name, int value){
845         string full_name = string("_") + string(name);
846         Symbol syminfo;
847         if (!p->getSymbolInfo(full_name, syminfo)) {
848                 string short_name(name);
849                 if (!p->getSymbolInfo(short_name, syminfo)) {
850                     assert(0);
851                 }
852         }
853
854         if( syminfo.type() == Symbol::PDST_FUNCTION)
855                 assert(0); 
856         Address tmpAddr = syminfo.addr();
857         return p->writeDataSpace((void*)tmpAddr, sizeof(int), (void*) &value);
858 }
859
860 #ifdef mips_unknown_ce2_11
861 int secondDLL = 0; //ccw 24 oct 2000 : 28 mar 2001
862 #endif
863 DWORD continueType = DBG_CONTINUE; //ccw 25 oct 2000 : 28 mar 2001
864
865
866 /*
867    wait for inferior processes to terminate or stop.
868 */
869 #ifdef BPATCH_LIBRARY
870 int process::waitProcs(int *status, bool block) {
871 #else
872 int process::waitProcs(int *status) {
873 #endif
874     DEBUG_EVENT debugEv;
875     process *p;
876 #ifdef BPATCH_LIBRARY
877     *status = 0;
878 #endif
879
880     // We wait for 1 millisecond here. On the Unix platforms, the wait
881     // happens on the select in controllerMainLoop. But on NT, because
882     // we have to handle traps, we set the timeout on the select as 0,
883     // so that we can check for traps quickly
884 #ifdef BPATCH_LIBRARY
885     DWORD milliseconds;
886     if (block) milliseconds = INFINITE;
887     else milliseconds = 1;
888
889 #if defined(mips_unknown_ce2_11) //ccw 28 july 2000 : 29 mar 2001
890     if (!BPatch::bpatch->rDevice->RemoteWaitForDebugEvent(&debugEv, milliseconds))
891 #else
892     if (!WaitForDebugEvent(&debugEv, milliseconds))
893 #endif    
894
895 #else
896
897     if (!WaitForDebugEvent(&debugEv, 1))
898
899 #endif
900         return 0;
901
902     //printf("Debug event from process %d, tid %d\n", debugEv.dwProcessId,
903     //   debugEv.dwThreadId);
904     p = findProcess(debugEv.dwProcessId);
905     if (p == NULL) {
906         /* 
907            this case can happen when we create a process, but then are
908            unable to parse the symbol table, and so don't complete the
909            creation of the process. We just ignore the event here.  
910         */
911
912 #if defined(mips_unknown_ce2_11) //ccw 28 july 2000 : 29 mar 2001
913         BPatch::bpatch->rDevice->RemoteContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
914                            DBG_CONTINUE);
915 #else
916                 ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
917                            DBG_CONTINUE);
918
919 #endif
920         return 0; 
921     }
922 #if defined(mips_unknown_ce2_11 )
923         continueType = DBG_CONTINUE;
924 #endif
925     switch (debugEv.dwDebugEventCode) {
926     case EXCEPTION_DEBUG_EVENT: {
927         DWORD exnCode = debugEv.u.Exception.ExceptionRecord.ExceptionCode;
928         switch(exnCode) {
929         case EXCEPTION_BREAKPOINT: {
930             //printf("Debug breakpoint exception, %d, addr = %x\n", 
931             //       debugEv.u.Exception.ExceptionRecord.ExceptionFlags,
932             //       debugEv.u.Exception.ExceptionRecord.ExceptionAddress);
933             
934 #if defined(mips_unknown_ce2_11) //ccw 20 mar 2001 : 29 mar 2001
935                 continueType = DBG_EXCEPTION_NOT_HANDLED;//ccw 25 oct 2000
936 #endif
937
938
939 #if !defined(mips_unknown_ce2_11)
940                 if(!secondBkpt && !p->wasCreatedViaAttach()){
941                         // if this was created via attach then
942                         // we are not at main() so no reason to
943                         // put a breakpoint there, we are already
944                         // at a state that will allow loadLibrary() to
945                         // succeed. 
946                         //ccw this is the breakpoint BEFORE main();
947                         //i need to insert the 0xcc into main() now.
948                         //byte debugOpCode = 0xcc;
949                         p->savedRegs = p->getRegisters();
950                         function_base *mainFunc;
951                         //DebugBreak();//ccw 14 may 2001  
952                         if (!((mainFunc = p->findOneFunction("main")))){
953                                 if(!(mainFunc = p->findOneFunction("_main"))){
954                                         if(!(mainFunc = p->findOneFunction("WinMain"))){
955                                                 if(!(mainFunc = p->findOneFunction("_WinMain"))){
956                                                         assert(0);
957                                                 }
958                                         }
959                                 }
960
961                         }
962                         mainAddr = mainFunc->addr();
963                         //ccw save what we overwrite for later.
964                         p->readDataSpace_((void*) (mainAddr), 256, (void*)savedOpCode);
965
966                         // insert the breakpoint into the code we just read
967                         CopyMemory( newOpCode, savedOpCode, 256 );
968                         newOpCode[0] = 0xcc;
969
970                         // write the modified code sequence back
971                         p->writeDataSpace((void*) (mainAddr), 256, (void*)newOpCode);
972                         p->flushInstructionCache_( (void*)mainAddr, 256 );
973
974                         secondBkpt=1;
975                         break;
976                 }
977 #endif
978
979
980             if (!p->reachedFirstBreak) {
981                 int inst_offset=  0xd; 
982                 if (!p->hasLoadedDyninstLib && !p->isLoadingDyninstLib) {
983                         //ccw 11 july 2001: IS THIS TRUE?
984                         //ccw 28 feb 2001
985                         //for MIPS/WINCE this never happens here, it is done in the
986                         //LOAD_DLL exception handler.  this is because of the
987                         //bug in which WINCE only passes one debug break when
988                         //it starts a process (unlike NT which gives two).
989                         //more explaination below in LOAD_DLL
990                         //DebugBreak();//ccw 30 jan 2001
991                         continueType = DBG_CONTINUE;//ccw 25 oct 2000 : 29 mar 2001
992
993
994
995                     Address addr = loadDyninstDll(p, p->savedData);
996                     mungeAddr = addr; //ccw 15 june 2001
997                     p->savedRegs = p->getRegisters();
998                     p->changePC(addr);
999                     //p->LoadDyninstTrapAddr = addr + 0xd;
1000                     p->isLoadingDyninstLib = true;
1001                     break;
1002                 } else if (p->isLoadingDyninstLib
1003 #if defined(mips_unknown_ce2_11)
1004                         ){
1005                         continueType = DBG_EXCEPTION_NOT_HANDLED;//ccw 25 oct 2000
1006 #else
1007                         && ((int) mungeAddr + inst_offset) ==
1008                         (int) debugEv.u.Exception.ExceptionRecord.ExceptionAddress) {
1009 #endif
1010                         //NOTE the above test is different for CE/NT
1011                         //
1012                         //ccw 2 may 2001 the above test is changed so that we only
1013                         // respond to events after
1014                         // the load library code has completed.  (we know that the 
1015                         // DebugBreak 0xd bytes from 
1016                         // the beginning of where we inserted code signals that we
1017                         // have finished load library) 
1018
1019                     p->isLoadingDyninstLib = false;
1020                     p->hasLoadedDyninstLib = true;
1021 #if !defined(mips_unknown_ce2_11)
1022                         //ccw 25 june 2001 NEED TO FLUSH ICACHE here
1023                         p->flushInstructionCache_((void*) ((w32CONTEXT*) p->savedRegs)->Eip,0x100);
1024 #endif
1025
1026                         if(mainAddr){
1027                             // patch main() back to its original form
1028                             p->writeDataSpace((void*) (mainAddr),16,(void*) savedOpCode); //ccw 2 may 2001
1029                             // reset the IP to run what we just inserted.
1030                             ((w32CONTEXT*) p->savedRegs)->Eip-=1; //ccw 2 may 2001
1031                         }
1032
1033                     p->restoreRegisters(p->savedRegs);
1034                     delete p->savedRegs;
1035                     p->writeDataSpace((void *)p->getImage()->codeOffset(),
1036                                       LOAD_DYNINST_BUF_SIZE,
1037                                       (void *)p->savedData);
1038 #if !defined(mips_unknown_ce2_11)                   
1039                         if(mainAddr){
1040                                 //ccw 25 june 2001 NEED TO FLUSH ICACHE here
1041                                 //p->flushInstructionCache_((void*) ((CONTEXT*) p->savedRegs)->Eip,0x100);
1042                                 p->readDataSpace_((void*)(mainAddr), 256, (void*) newOpCode);
1043                                 p->writeDataSpace((void*) (mainAddr),256,(void*) savedOpCode); //ccw 2 may 2001
1044                                 //technically, we only need to writeDataSpace once, up at the previous
1045                                 // if statement. BUT writing once does not seem to always flush the 
1046                                 // icache, and neither does FlushInsturctionCache()
1047                                 // the readDataSpace_ is completely spurrious but is here for the same
1048                                 // reason, to get the icache updated correctly with the old op code before
1049                                 // we continue. 
1050                         }
1051 #endif  
1052         
1053                 }else{
1054                         break;  //ccw 20 june 2001 this is the DYNINSTinit breakpoint
1055                 }
1056                 p->reachedFirstBreak = true;
1057       
1058                 if (!p->createdViaAttach) {
1059                     int pid = p->getPid();
1060                     p->status_ = stopped;
1061
1062                     if (!p->initDyninstLib()) {
1063                         OS::osKill(pid);
1064                         handleProcessExit(p, -1);
1065 #ifdef BPATCH_LIBRARY
1066                         *status = SIGEM_SIGNALED | SIGTERM;
1067                         return p->getPid();
1068 #else
1069                         return 0;
1070 #endif
1071                     }
1072
1073                     string buffer = string("PID=") + string(pid);
1074                     buffer += string(", passed trap at start of program");
1075                     statusLine(buffer.c_str());
1076       
1077                     buffer=string("PID=") + string(pid) 
1078                          + ", installing call to DYNINSTinit()";
1079                     statusLine(buffer.c_str());
1080 #if !defined(BPATCH_LIBRARY)
1081                     p->installBootstrapInst();//ccw 20 june 2001 
1082                         // now we dont need to do this,  DLLMain() does it.
1083                         //this still needs to be done for paradyn
1084  
1085                     // now, let main() and then DYNINSTinit() get invoked.  As it
1086                     // completes, DYNINSTinit() does a DYNINSTbreakPoint, at which time
1087                     // we read bootstrap information "sent back" (in a global vrble),
1088                     // propagate metric instances, do tp->newProgramCallbackFunc(), etc.
1089                      break; //ccw 20 june 2001, commented out  with p->installBootstrapInst()
1090 #endif
1091                 } else {
1092                     //printf("First breakpoint after attach\n");
1093                     p->pause_();
1094                     break;
1095                 }
1096             }
1097
1098             // the process has already been initialized
1099             // First lookup in the tramp table, to see if the breakpoint
1100             // is from an instrumentation point.
1101
1102             // lookup in tramp table
1103
1104 #if !defined( mips_unknown_ce2_11 )//ccw 26 july 2000 : 29 mar 2001
1105             Address trampAddr = 0;
1106             unsigned u; unsigned k;
1107             unsigned key = 
1108                 (unsigned)debugEv.u.Exception.ExceptionRecord.ExceptionAddress;
1109             for (u = HASH1(key); 1; u = (u + HASH2(key)) % TRAMPTABLESZ) {
1110                 k = p->trampTable[u].key;
1111                 if (k == 0)
1112                     break;
1113                 else if (k == key) {
1114                     trampAddr = p->trampTable[u].val;
1115                     break;
1116                 }
1117             }
1118             if (trampAddr) {
1119                     // this is a trap from an instrumentation point
1120
1121             // find the current thread
1122             pdThread* currThread = NULL;
1123                     for(unsigned int i = 0; i < p->threads.size(); i++)
1124             {
1125                         if ((unsigned)p->threads[i]->get_tid() == debugEv.dwThreadId)
1126                 {
1127                     currThread = p->threads[i];
1128                     break;
1129                 }
1130             }
1131             assert( currThread != NULL );
1132
1133             // Due to a race between the processing of trap debug events
1134             // and the desire to run an inferior RPC, it is possible that
1135             // we hit the trap, set ourselves up to run an inferior RPC,
1136             // and then processed the trap notification.  If this happens,
1137             // we don't end up running *any* of the inferior RPC code.
1138             //
1139             // We can tell that this is what's happened based on the
1140             // thread's Eip - if it doesn't match the ExceptionAddress, we
1141             // know that we had tried to reset the Eip to execute an inferior
1142             // RPC.  In that case, we leave the Eip alone here, which means
1143             // the inferior RPC code will execute when we continue the thread.
1144             // We have to remember that we need to execute this instrumentatin
1145             // once the inferior RPC is done, however.
1146             // 
1147                         CONTEXT cont;
1148                         cont.ContextFlags = CONTEXT_FULL;
1149                         if( !GetThreadContext( (HANDLE)currThread->get_handle(), &cont ) )
1150             {
1151                             assert(false);
1152             }
1153             if( debugEv.u.Exception.ExceptionRecord.ExceptionAddress == (PVOID)(cont.Eip - 1) )
1154             {
1155                 // The Eip indicates we've just executed a trap instruction
1156                 // reset the Eip to the address of the base tramp
1157                 cont.Eip = trampAddr;
1158                 if( !SetThreadContext( (HANDLE)currThread->get_handle(), &cont ) )
1159                 {
1160                     assert( false );
1161                 }
1162             }
1163             else
1164             {
1165                 // We leave the Eip alone, since we've set it to execute 
1166                 // at inferior RPC code.  However, we need to remember that
1167                 // we should execute the base tramp once the inferiorRPC is
1168                 // completed.
1169                 currThread->set_pending_tramp_addr( trampAddr );
1170             }
1171
1172                     break;
1173             }
1174 #endif // mips_unknown_ce2_11
1175             
1176             // If it is not from an instrumentation point,
1177             // it could be from a call to DYNINSTbreakPoint
1178             // or an inferior procedure call
1179
1180             p->status_ = stopped;
1181             p->pause_();
1182             int result = p->procStopFromDYNINSTinit();
1183             assert(result >= 0 && result <= 2);
1184             if (result != 0) {
1185                 if (result == 1) {
1186 #if defined( mips_unknown_ce2_11 )//ccw 20 mar 2001 : 29 mar 2001
1187                         continueType = DBG_EXCEPTION_NOT_HANDLED;//ccw 1 mar 2001
1188 #endif                  
1189                         //p->pause_();
1190                 } else {
1191                     // procStopFromDYNINSTinit called continueProc()
1192                     // What should we do here?
1193                     break;
1194                 }
1195             } else if (p->handleTrapIfDueToRPC()) {
1196                 //p->pause_();
1197                 break;
1198             } else {
1199 #ifdef BPATCH_LIBRARY /* Don't ignore unknown bkpt in library; leave stopped. */
1200                 *status = SIGEM_STOPPED | SIGTRAP;
1201 #if defined( mips_unknown_ce2_11 )//ccw 20 mar 2001 : 29 mar 2001
1202                         continueType = DBG_EXCEPTION_NOT_HANDLED;//ccw 1 mar 2001
1203 #endif
1204
1205 #else
1206                 // Unknown breakpoint: we just ignore it
1207                 printf("Debug breakpoint exception, %d, addr = %x\n", 
1208                        debugEv.u.Exception.ExceptionRecord.ExceptionFlags,
1209                        debugEv.u.Exception.ExceptionRecord.ExceptionAddress);
1210                 p->status_ = running;
1211                 p->continueProc_();
1212 #endif
1213             }
1214             break;
1215         }
1216         case EXCEPTION_ILLEGAL_INSTRUCTION:
1217             //printf("Illegal instruction\n");
1218             p->pause_();
1219             p->status_ = stopped;
1220             if( p->handleTrapIfDueToRPC() )
1221         {
1222                     // handleTrapIfDueToRPC calls continueProc()
1223             // however, under Windows NT, it doesn't actually 
1224             // continue the thread until the ContinueDbgEvent call is made
1225
1226             // We take advantage of this fact to ensure that any
1227             // pending instrumentation is executed.  (I.e., instrumentation
1228             // put off so we could be sure to execute inferior RPC code is
1229             // now executed.)
1230             if( p->currRunningRPCs.size() == 0 )
1231             {
1232                 // we finished the inferior RPC, so we can now execute
1233                 // any pending instrumentation
1234
1235                 // find the current thread
1236                 pdThread* currThread = NULL;
1237                 for( unsigned int i = 0; i < p->threads.size(); i++ )
1238                 {
1239                             if ((unsigned)p->threads[i]->get_tid() == debugEv.dwThreadId)
1240                     {
1241                         currThread = p->threads[i];
1242                         break;
1243                     }
1244                 }
1245                 assert( currThread != NULL );
1246
1247                 Address pendingTrampAddr = currThread->get_pending_tramp_addr();
1248                 if( pendingTrampAddr != NULL )
1249                 {
1250                     // reset the Eip to the pending instrumentation
1251                     CONTEXT ctxt;
1252                     ctxt.ContextFlags = CONTEXT_FULL;
1253                     if( !GetThreadContext( (HANDLE)currThread->get_handle(), &ctxt ) )
1254                     {
1255                         assert( false );
1256                     }
1257                     ctxt.Eip = pendingTrampAddr;
1258                     if( !SetThreadContext( (HANDLE)currThread->get_handle(), &ctxt ) )
1259                     {
1260                         assert( false );
1261                     }
1262                     currThread->set_pending_tramp_addr( NULL );
1263                 }
1264             }
1265                     break;
1266             }
1267             p->status_ = running;
1268             p->continueProc_();
1269 #if defined( mips_unknown_ce2_11) //ccw 28 july 2000 : 29 mar 2001
1270             BPatch::bpatch->rDevice->RemoteContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
1271                                    DBG_EXCEPTION_NOT_HANDLED);
1272 #else
1273             ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
1274                                    DBG_EXCEPTION_NOT_HANDLED);
1275 #endif
1276             return 0;
1277
1278         case EXCEPTION_ACCESS_VIOLATION:
1279             printf("Access violation exception, %d, addr = %08x\n", 
1280                    debugEv.u.Exception.ExceptionRecord.ExceptionFlags,
1281                    debugEv.u.Exception.ExceptionRecord.ExceptionAddress);
1282             dumpMem(p, debugEv.u.Exception.ExceptionRecord.ExceptionAddress, 32);
1283
1284         {
1285
1286             // Parameters for walkStack.
1287 #ifndef mips_unknown_ce2_11 //ccw 6 feb 2001 : 29 mar 2001
1288
1289           vector<Frame> stackWalk;
1290           p->walkStack(p->getActiveFrame(), stackWalk, false);
1291
1292             for( unsigned i = 0; i < stackWalk.size(); i++ )
1293             {
1294                 function_base* f = p->findFuncByAddr( stackWalk[i].getPC() );
1295                 const char* szFuncName = (f != NULL) ? f->prettyName().c_str() : "<unknown>";
1296                 fprintf( stderr, "%08x: %s\n", stackWalk[i].getPC(), szFuncName );
1297             }
1298 #endif
1299
1300         }
1301             //  ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
1302             //                     DBG_EXCEPTION_NOT_HANDLED);
1303             //  break;
1304         default:
1305             //printf("exeption %x, addr %x\n", exnCode, 
1306             //   debugEv.u.Exception.ExceptionRecord.ExceptionAddress);
1307 #if defined( mips_unknown_ce2_11 )//ccw 28 july 2000 : 29 mar 2001
1308                 BPatch::bpatch->rDevice->RemoteContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
1309                                    DBG_EXCEPTION_NOT_HANDLED);
1310 #else
1311                 ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
1312                                    DBG_EXCEPTION_NOT_HANDLED);
1313 #endif
1314
1315             return 0;
1316         }
1317     } break;
1318
1319     case CREATE_THREAD_DEBUG_EVENT: {
1320         //printf("create thread, tid = %d\n", debugEv.dwThreadId);
1321         assert(p->threads.size() > 0); // main thread should be already defined
1322         pdThread *t = new pdThread(p, debugEv.dwThreadId,
1323                                    debugEv.u.CreateThread.hThread);
1324         p->threads.push_back(t);
1325     } break;
1326
1327     case CREATE_PROCESS_DEBUG_EVENT: {
1328         //CREATE_PROCESS_DEBUG_INFO info = debugEv.u.CreateProcessInfo;
1329         //printf("CREATE_PROCESS event: %d\n", debugEv.dwProcessId);
1330         p = findProcess(debugEv.dwProcessId);
1331         if (p) {
1332             secondBkpt = 0; //ccw 27 june 2001 : allows for more than one mutatee to be started
1333             //fprintf(stderr,"create process: base = %x\n", info.lpBaseOfImage);
1334             if (p->threads.size() == 0) {
1335                 // define the main thread
1336                 p->threads.push_back(new pdThread(p));
1337             }
1338             p->threads[0]->update_handle(debugEv.dwThreadId, 
1339                                          debugEv.u.CreateProcessInfo.hThread);
1340             
1341         }
1342     } break;
1343
1344     case EXIT_THREAD_DEBUG_EVENT: {
1345         //printf("exit thread, tid = %d\n", debugEv.dwThreadId);
1346         unsigned nThreads = p->threads.size();
1347         // start from one to skip main thread
1348         for (unsigned u = 1; u < nThreads; u++) {
1349             if ((unsigned)p->threads[u]->get_tid() == debugEv.dwThreadId) {
1350                 delete p->threads[u];
1351                 p->threads[u] = p->threads[nThreads-1];
1352                 p->threads.resize(nThreads-1);
1353                 break;
1354             }
1355         }
1356     } break;
1357
1358     case EXIT_PROCESS_DEBUG_EVENT:
1359         p = findProcess(debugEv.dwProcessId);
1360         if (p) {
1361             char errorLine[1024];
1362             sprintf(errorLine, "Process %d has terminated with code 0x%x\n", 
1363                 p->getPid(), debugEv.u.ExitProcess.dwExitCode);
1364             statusLine(errorLine);
1365             logLine(errorLine);
1366             handleProcessExit(p, debugEv.u.ExitProcess.dwExitCode);
1367         }
1368 #ifdef BPATCH_LIBRARY
1369         *status = SIGEM_EXITED;
1370 #else
1371         break;
1372 #endif
1373         break; //ccw 23 july 2001
1374     case LOAD_DLL_DEBUG_EVENT: {
1375         //printf("load dll: hFile=%x, base=%x, debugOff=%x, debugSz=%d lpname=%x, %d\n",
1376         //       debugEv.u.LoadDll.hFile, debugEv.u.LoadDll.lpBaseOfDll,
1377         //       debugEv.u.LoadDll.dwDebugInfoFileOffset,
1378         //       debugEv.u.LoadDll.nDebugInfoSize,
1379         //       debugEv.u.LoadDll.lpImageName,
1380         //       /*debugEv.u.LoadDll.fUnicode*/
1381         //       GetFileSize(debugEv.u.LoadDll.hFile,NULL));
1382
1383         // We are currently not handling dynamic libraries loaded after the
1384         // application starts.
1385         if (p->isBootstrappedYet())
1386           break;
1387
1388         // set the proc handle for the process that is loading the library
1389         // This is need when we use the imagehelp library to get the
1390         // symbols for the dll.
1391         // kludgeProcHandle = (HANDLE)p->getProcFileDescriptor();
1392
1393         // obtain the name of the DLL
1394         string imageName = GetLoadedDllImageName( p, debugEv );
1395
1396
1397         // try to load symbols for the DLL
1398         if (!SymLoadModule((HANDLE)p->getProcFileDescriptor(),
1399                            debugEv.u.LoadDll.hFile,
1400                            NULL, NULL, 0, 0)) {
1401
1402                 char msgText[1024];
1403
1404                 sprintf( msgText, "SymLoadModule failed for %s: 0x%x\n",
1405                         imageName.c_str(), GetLastError() );
1406
1407                 logLine(msgText);
1408         }
1409
1410         // discover structure of new DLL, and incorporate into our
1411         // list of known DLLs
1412         if (imageName.length() > 0) {
1413
1414         shared_object *so = 
1415 #if defined( mips_unknown_ce2_11 )//ccw 29 mar 2001
1416         new shared_object(imageName, (unsigned long) debugEv.u.LoadDll.lpBaseOfDll,
1417                 false, true, true, 0);
1418 #else
1419                 new shared_object(imageName, 0,false, true, true, 0);
1420 #endif
1421             assert(p->dyn);
1422             p->dyn->sharedObjects.push_back(so);
1423             if (!p->shared_objects) {
1424               p->shared_objects = new vector<shared_object *>;
1425             }
1426             (*(p->shared_objects)).push_back(so);
1427 #ifndef BPATCH_LIBRARY
1428             tp->resourceBatchMode(true);
1429 #endif 
1430             p->addASharedObject(*so);
1431 #ifndef BPATCH_LIBRARY
1432             tp->resourceBatchMode(false);
1433 #endif 
1434             p->setDynamicLinking();
1435
1436 #ifdef BPATCH_LIBRARY
1437             {
1438                 char dllFilename[_MAX_FNAME];
1439                 char dllExtension[_MAX_EXT];
1440
1441                 _splitpath( imageName.c_str(),
1442                             NULL,
1443                             NULL,
1444                             dllFilename,
1445                             dllExtension );
1446                 if( !_stricmp( dllFilename, "libdyninstAPI_RT" ) &&
1447                     !_stricmp( dllExtension, ".dll" ) ) {
1448                     // ccw 2 may 2001
1449                     //when we load libdyninstAPI_RT.dll we need to find the local
1450                     //variables in the dll that will hold the cause and pid so when
1451                     //DLLMain is called they will be correctly passed to DYNINSTinit
1452                     if(!setVariable(p, "libdyninstAPI_RT_DLL_localCause", 1)){
1453                          assert(0);
1454                     }
1455                     if(!setVariable(p, "libdyninstAPI_RT_DLL_localPid", getpid())){
1456                          assert(0);
1457                     }
1458                 }
1459             }
1460 #endif  
1461           }
1462                 //ccw 31 jan 2001 : 29 mar 2001
1463                 //here i need to check to see if this is the first breakpt since
1464                 //creating the process and if it is, do whatever should happen when 
1465                 //i get the second NT breakpoint.
1466                 //This is a HACK that fixes the bug that WinCE does NOT send a
1467                 //debug message before starting main, you get one when you create
1468                 //the process (before loading and dlls and any initializations take place)
1469                 //and that is it.  so i grab one after coredll.dll is loaded
1470                 //and load the libdyninstAPI_RT.dll
1471
1472 #ifdef mips_unknown_ce2_11 //ccw 31 jan 2001 : 29 mar 2001
1473                 if(!_stricmp(imageName.c_str(),"coredll.dll")){ 
1474                         //make sure we have loaded coredll.dll --this contains LoadLibrary
1475
1476                         continueType = DBG_EXCEPTION_NOT_HANDLED;//ccw 25 oct 2000
1477                         if (!p->reachedFirstBreak) {
1478
1479                                 if (!p->hasLoadedDyninstLib && !p->isLoadingDyninstLib) {
1480                                         //DebugBreak();//ccw 30 jan 2001
1481                                         continueType = DBG_CONTINUE;//ccw 25 oct 2000
1482                                         //DebugBreak();
1483                                         Address addr = loadDyninstDll(p, p->savedData);
1484                                         p->savedRegs = p->getRegisters();
1485                                         p->changePC(addr);
1486                                         //p->LoadDyninstTrapAddr = addr + 0xd;
1487                                         p->isLoadingDyninstLib = true;
1488                                         break;
1489                                 }
1490                         }
1491                 }
1492 #endif
1493         
1494         }
1495     break;
1496     case UNLOAD_DLL_DEBUG_EVENT:
1497         // TODO
1498         //printf("unload dll\n");
1499         break;
1500     case OUTPUT_DEBUG_STRING_EVENT:
1501 #if defined( mips_unknown_ce2_11 ) //ccw 29 mar 2001
1502         //printf("output debug string\n");
1503                 char dbgStr[512];//ccw 3 oct 2000
1504                 memset(dbgStr,'\0', 512); //ccw 3 oct 2000
1505                 p->readDataSpace_(debugEv.u.DebugString.lpDebugStringData, //ccw 3 oct 2000
1506                         (debugEv.u.DebugString.nDebugStringLength<512) ? 
1507                         debugEv.u.DebugString.nDebugStringLength:511 , dbgStr );
1508                 wprintf(L"output debug string: %s\n",dbgStr); //ccw 3 oct 2000
1509                 //DebugBreak();
1510 #endif
1511         //printf("output debug string\n");
1512         break;
1513     case RIP_EVENT:
1514         //printf("rip event\n");
1515         break;
1516     default:
1517         ;
1518         //printf("unknown debug event\n");
1519         
1520     }
1521 #if defined( mips_unknown_ce2_11 )//ccw 28 july 2000 : 29 mar 2001
1522     if (!BPatch::bpatch->rDevice->RemoteContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
1523                             continueType)) {
1524 #else
1525     if (!ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
1526                             DBG_CONTINUE)) {
1527 #endif
1528         DebugBreak();
1529         printf("ContinueDebugEvent failed\n");
1530         printSysError(GetLastError());
1531     }
1532
1533 #ifdef BPATCH_LIBRARY
1534     if (*status)
1535         return debugEv.dwProcessId;
1536     else
1537         return 0;
1538 #else
1539     return 0;
1540 #endif
1541 }
1542
1543
1544 // already setup on this FD.
1545 // disconnect from controlling terminal 
1546 void OS::osDisconnect(void) {
1547 #ifdef notdef
1548   int ttyfd = open ("/dev/tty", O_RDONLY);
1549   ioctl (ttyfd, TIOCNOTTY, NULL); 
1550   P_close (ttyfd);
1551 #endif
1552 }
1553
1554
1555 bool process::attach() {
1556     if (createdViaAttach) {
1557 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1558         if (!BPatch::bpatch->rDevice->RemoteDebugActiveProcess(getPid())) {
1559 #else
1560         if (!DebugActiveProcess(getPid())) {
1561 #endif
1562             //printf("Error: DebugActiveProcess failed\n");
1563             return false;
1564         }
1565     }
1566 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1567     proc_fd = (int)BPatch::bpatch->rDevice->RemoteOpenProcess(PROCESS_ALL_ACCESS, false, getPid());
1568 #else
1569     proc_fd = (int)OpenProcess(PROCESS_ALL_ACCESS, false, getPid());
1570
1571 #endif
1572
1573     if (proc_fd == NULL) {
1574         //printf("Error: OpenProcess failed\n");
1575         assert(0);
1576     }
1577
1578     void initSymbols(HANDLE procH, const string file, const string dir);
1579     initSymbols((HANDLE)proc_fd, symbols->file(), "");
1580     if (createdViaAttach) {
1581         //
1582         //void initSymbols(HANDLE procH, const string file, const string dir);
1583         //initSymbols((HANDLE)proc_fd, symbols->file(), "");
1584     }
1585     return true;
1586 }
1587
1588 /* continue a process that is stopped */
1589 bool process::continueProc_() {
1590     if (hasNewPC) {
1591       changePC(currentPC_);
1592       hasNewPC = false;
1593     }
1594     for (unsigned u = 0; u < threads.size(); u++) {
1595         unsigned count;
1596 #ifdef mips_unknown_ce2_11 //ccw 10 feb 2001 : 29 mar 2001
1597                 count = BPatch::bpatch->rDevice->RemoteResumeThread((HANDLE)threads[u]->get_handle());
1598 #else
1599                 count = ResumeThread((HANDLE)threads[u]->get_handle());
1600 #endif
1601
1602         if (count == 0xFFFFFFFF) {
1603             printSysError(GetLastError());
1604             return false;
1605         }
1606     }
1607     return true;
1608 }
1609
1610
1611 #ifdef BPATCH_LIBRARY
1612 /*
1613    terminate execution of a process
1614  */
1615 bool process::terminateProc_()
1616 {
1617     OS::osKill(pid);
1618     handleProcessExit(this, -1);
1619     return true;
1620 }
1621 #endif
1622
1623
1624 /*
1625    pause a process that is running
1626 */
1627 bool process::pause_() {
1628     for (unsigned u = 0; u < threads.size(); u++) {
1629         unsigned count ;
1630 #ifdef mips_unknown_ce2_11 //ccw 10 feb 2001 : 29 mar 2001
1631         count = BPatch::bpatch->rDevice->RemoteSuspendThread((HANDLE)threads[u]->get_handle());
1632 #else
1633         count = SuspendThread((HANDLE)threads[u]->get_handle());
1634 #endif
1635
1636         if (count == 0xFFFFFFFF) {
1637             // printf("pause_: %d\n", threads[u]->get_tid());
1638             // printSysError(GetLastError());
1639             return false;
1640         } 
1641     }
1642     return true;
1643 }
1644
1645 /*
1646    close the file descriptor for the file associated with a process
1647 */
1648 bool process::detach_() {
1649     return false;
1650 }
1651
1652
1653 #ifdef BPATCH_LIBRARY
1654 /*
1655    detach from thr process, continuing its execution if the parameter "cont"
1656    is true.
1657  */
1658 bool process::API_detach_(const bool cont)
1659 {
1660     // XXX Not yet implemented
1661     assert(false);
1662     return false;
1663 }
1664 #endif
1665
1666
1667 bool process::dumpCore_(const string) {
1668     return false;
1669 }
1670
1671 bool process::writeTextWord_(caddr_t inTraced, int data) {
1672     return writeDataSpace_(inTraced, sizeof(int), (caddr_t) &data);
1673 }
1674
1675 bool process::writeTextSpace_(void *inTraced, u_int amount, const void *inSelf) {
1676     return writeDataSpace_(inTraced, amount, inSelf);
1677 }
1678
1679 bool process::flushInstructionCache_(void *baseAddr, size_t size){ //ccw 25 june 2001
1680         return FlushInstructionCache((HANDLE)proc_fd, baseAddr, size);
1681 }
1682
1683 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
1684 bool process::readTextSpace_(void *inTraced, u_int amount, const void *inSelf) {
1685   return readDataSpace_(inTraced, amount, (void *)inSelf);
1686 }
1687 #endif
1688
1689 bool process::writeDataSpace_(void *inTraced, u_int amount, const void *inSelf) {
1690     DWORD nbytes;
1691
1692     //printf("write %d bytes, %x\n", amount, inTraced);
1693 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1694     bool res = BPatch::bpatch->rDevice->RemoteWriteProcessMemory((HANDLE)proc_fd, (LPVOID)inTraced, 
1695                                   (LPVOID)inSelf, (DWORD)amount, &nbytes);
1696 #else
1697     bool res = WriteProcessMemory((HANDLE)proc_fd, (LPVOID)inTraced, 
1698                                   (LPVOID)inSelf, (DWORD)amount, &nbytes);
1699 #endif
1700     return res && (nbytes == amount);
1701 }
1702
1703
1704 bool process::readDataSpace_(const void *inTraced, u_int amount, void *inSelf) {
1705     DWORD nbytes;
1706 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1707     bool res = BPatch::bpatch->rDevice->RemoteReadProcessMemory((HANDLE)proc_fd, (LPVOID)inTraced, 
1708                                  (LPVOID)inSelf, (DWORD)amount, &nbytes);
1709 #else
1710     bool res = ReadProcessMemory((HANDLE)proc_fd, (LPVOID)inTraced, 
1711                                  (LPVOID)inSelf, (DWORD)amount, &nbytes);
1712 #endif
1713     return res && (nbytes == amount);
1714 }
1715
1716
1717 bool process::loopUntilStopped() { assert(0); return false; }
1718
1719 float OS::compute_rusage_cpu() { return 0.0; }
1720 float OS::compute_rusage_sys() { return 0.0; }
1721 float OS::compute_rusage_min() { return 0.0; }
1722 float OS::compute_rusage_maj() { return 0.0; }
1723 float OS::compute_rusage_swap() { return 0.0; }
1724 float OS::compute_rusage_io_in() { return 0.0; }
1725 float OS::compute_rusage_io_out() { return 0.0; }
1726 float OS::compute_rusage_msg_send() { return 0.0; }
1727 float OS::compute_rusage_msg_recv() { return 0.0; }
1728 float OS::compute_rusage_sigs() { return 0.0; }
1729 float OS::compute_rusage_vol_cs() { return 0.0; }
1730 float OS::compute_rusage_inv_cs() { return 0.0; }
1731
1732
1733 int getNumberOfCPUs() {
1734     SYSTEM_INFO info;
1735     GetSystemInfo(&info);
1736     return info.dwNumberOfProcessors;
1737 }  
1738
1739
1740 Frame process::getActiveFrame(unsigned /*lwp*/)
1741 {
1742    w32CONTEXT cont; //ccw 27 july 2000 : 29 mar 2001
1743    
1744    Address pc = 0, fp = 0, sp = 0;
1745
1746     // we must set ContextFlags to indicate the registers we want returned,
1747     // in this case, the control registers.
1748     // The values for ContextFlags are defined in winnt.h
1749     cont.ContextFlags = CONTEXT_CONTROL;
1750 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1751     if (BPatch::bpatch->rDevice->RemoteGetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
1752 #else
1753     if (GetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
1754
1755 #endif
1756
1757 #ifdef i386_unknown_nt4_0 //ccw 27 july 2000 : 29 mar 2001
1758
1759       fp = cont.Ebp;
1760       pc = cont.Eip;
1761 #elif mips_unknown_ce2_11
1762       pc = cont.Fir;
1763       sp = cont.IntSp;
1764       fp = cont.IntS8;
1765 #endif
1766       return Frame(pc, fp, sp, getPid(), NULL, 0, true);
1767     }
1768     printSysError(GetLastError());
1769     return Frame();
1770 }
1771
1772 #if defined(i386_unknown_nt4_0) //ccw 29 mar 2001
1773  
1774
1775 Frame Frame::getCallerFrame(process *p) const
1776 {
1777     // For x86, the frame-pointer (EBP) points to the previous 
1778     // frame-pointer, and the saved return address is in EBP-4.
1779
1780     struct {
1781         Address fp;
1782         Address rtn;
1783     } addrs;
1784
1785     if (p->readDataSpace((caddr_t)(fp_), sizeof(int)*2,
1786                          (caddr_t)&addrs, true))
1787     {
1788         Frame ret;
1789         ret.fp_ = addrs.fp;
1790         ret.pc_ = addrs.rtn;
1791         return ret;
1792     }
1793
1794     return Frame(); // zero frame
1795 }
1796
1797 #elif mips_unknown_ce2_11 //ccw 6 feb 2001
1798
1799 Frame Frame::getCallerFrame(process *p) const
1800 {
1801 //      DebugBreak();//ccw 6 feb 2001
1802
1803         Frame ret;
1804         Address prevPC;
1805
1806         //find which function we are in to determine the frame size
1807
1808         // (i.e. $pc in native/basetramp/minitramp code)
1809         instPoint     *ip = NULL;
1810         trampTemplate *bt = NULL;
1811         instInstance  *mt = NULL;
1812         pd_Function *callee = findAddressInFuncsAndTramps(p, pc_, ip, bt, mt);
1813         // non-NULL "ip" means that $pc is in instrumentation
1814         // non-NULL "bt" means that $pc is in basetramp
1815         // non-NULL "mt" means that $pc is in minitramp
1816         if (ip) assert(bt || mt);
1817
1818         ret.sp_ = sp_ - callee->frame_size;
1819
1820         Address tmpSp = sp_ + 20;
1821         p->readDataSpace((caddr_t)(tmpSp), sizeof(int),
1822                          &prevPC, true);
1823
1824         ret.pc_ = prevPC;
1825           
1826
1827         return ret;
1828 }
1829 #endif
1830
1831 #ifdef mips_unknown_ce2_11 //ccw 10 aug 2000 : 29 mar 2001
1832 void *process::getRegisters(unsigned lwp) {
1833     w32CONTEXT *cont = new w32CONTEXT; //ccw 27 july 2000
1834     if (!cont)
1835                 return NULL;
1836     // we must set ContextFlags to indicate the registers we want returned,
1837     // in this case, the control registers.
1838     // The values for ContextFlags are defined in winnt.h
1839     cont->ContextFlags = w32CONTEXT_FULL;//ccw 27 july 2000
1840     if (!BPatch::bpatch->rDevice->RemoteGetThreadContext((void*) lwp, cont)) { //ccw 10 aug 2000
1841                 delete cont;
1842                 return NULL;
1843     }
1844     return (void *)cont;
1845 }
1846 #else
1847 void *process::getRegisters(unsigned lwp)
1848 {
1849   return getRegisters();
1850 }
1851 #endif
1852
1853 void *process::getRegisters() {
1854     w32CONTEXT *cont = new w32CONTEXT; //ccw 27 july 2000 : 29 mar 2001
1855     if (!cont)
1856         return NULL;
1857     // we must set ContextFlags to indicate the registers we want returned,
1858     // in this case, the control registers.
1859     // The values for ContextFlags are defined in winnt.h
1860     cont->ContextFlags = w32CONTEXT_FULL;//ccw 27 july 2000 : 29 mar 2001
1861 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1862     if (!BPatch::bpatch->rDevice->RemoteGetThreadContext((HANDLE)threads[0]->get_handle(), cont)) {
1863 #else
1864     if (!GetThreadContext((HANDLE)threads[0]->get_handle(), cont)) {
1865 #endif
1866
1867         delete cont;
1868         return NULL;
1869     }
1870     return (void *)cont;
1871 }
1872
1873 bool process::changePC(Address addr, const void *savedRegs, int lwp)
1874 {
1875   return changePC(addr, savedRegs);
1876 }
1877
1878 bool process::changePC(Address addr, const void *savedRegs) {
1879   if (!savedRegs) return changePC(addr);
1880     assert(status_ == stopped);
1881     w32CONTEXT cont = *(w32CONTEXT *)savedRegs; //ccw 27 july 2000 : 29 mar 2001
1882 //      DebugBreak();
1883 #ifdef i386_unknown_nt4_0 //ccw 27 july 2000 : 29 mar 2001
1884     cont.Eip = addr;
1885 #elif  mips_unknown_ce2_11 
1886         cont.Fir = addr;
1887 #endif
1888
1889 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1890     if (!BPatch::bpatch->rDevice->RemoteSetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
1891 #else
1892     if (!SetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
1893 #endif
1894
1895         printf("SethreadContext failed\n");
1896         return false;
1897     }
1898     return true;
1899 }
1900
1901 bool process::changePC(Address addr) {
1902     assert(status_ == stopped || status_ == neonatal);
1903
1904      w32CONTEXT cont;//ccw 27 july 2000
1905
1906     cont.ContextFlags = w32CONTEXT_FULL;//ccw 27 july 2000 : 29 mar 2001
1907 //      DebugBreak();
1908 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1909     if (!BPatch::bpatch->rDevice->RemoteGetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
1910 #else
1911     if (!GetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
1912 #endif
1913                 printf("GetThreadContext failed\n");
1914                 return false;
1915     }
1916 #ifdef i386_unknown_nt4_0 //ccw 27 july 2000 : 29 mar 2001
1917     cont.Eip = addr;
1918 #elif  mips_unknown_ce2_11 
1919         cont.Fir = addr;
1920 #endif
1921 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1922     if (!BPatch::bpatch->rDevice->RemoteSetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
1923 #else
1924     if (!SetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
1925 #endif
1926         return false;
1927     }
1928     return true;
1929 }
1930
1931 bool process::restoreRegisters(void *buffer) {
1932 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1933     if (!BPatch::bpatch->rDevice->RemoteSetThreadContext((HANDLE)threads[0]->get_handle(),
1934          (w32CONTEXT *)buffer)) {//ccw 27 july 2000
1935 #else
1936     if (!SetThreadContext((HANDLE)threads[0]->get_handle(), (w32CONTEXT *)buffer)) {//ccw 27 july 2000
1937 #endif
1938         //printf("SetThreadContext failed\n");
1939         return false;
1940     }
1941     return true;
1942 }
1943
1944 bool process::isRunning_() const {
1945     // TODO
1946     printf("process::isRunning_() returning true\n");
1947     return true;
1948 }
1949
1950
1951 string process::tryToFindExecutable(const string& iprogpath, int pid) {
1952   return iprogpath;
1953 }
1954
1955 bool process::set_breakpoint_for_syscall_completion() {
1956    /* Can assume: (1) process is paused and (2) in a system call.
1957       We want to set a TRAP for the syscall exit, and do the
1958       inferiorRPC at that time.  We'll use /proc PIOCSEXIT.
1959       Returns true iff breakpoint was successfully set. */
1960
1961     // This is never called on Windows NT
1962     assert(false);
1963     return false;
1964 }
1965
1966 void process::clear_breakpoint_for_syscall_completion() { return; }
1967
1968 Address process::read_inferiorRPC_result_register(Register reg) { //ccw 17 july 2001
1969    w32CONTEXT *cont = new w32CONTEXT;//ccw 27 july 2000 : 29 mar 2001
1970     if (!cont)
1971         return NULL;
1972     // we must set ContextFlags to indicate the registers we want returned,
1973     // in this case, the control registers.
1974     // The values for ContextFlags are defined in winnt.h
1975     cont->ContextFlags = w32CONTEXT_FULL;//ccw 27 july 2000
1976 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
1977     if (!BPatch::bpatch->rDevice->RemoteGetThreadContext((HANDLE)threads[0]->get_handle(), cont)) {
1978 #else
1979     if (!GetThreadContext((HANDLE)threads[0]->get_handle(), cont)) {
1980 #endif
1981         delete cont;
1982         return NULL;
1983     }
1984 #ifdef i386_unknown_nt4_0 //ccw 27 july 2000 : 29 mar 2001
1985     return cont->Eax;
1986 #elif mips_unknown_ce2_11 
1987         return (&cont->IntZero)[reg]; 
1988         //the registers in the MIPS context returned by
1989         //winCE return general registers 0..31 in the struct
1990         //starting at IntZero and going to IntRa, each being a DWORD
1991 #endif
1992 }
1993
1994 bool process::executingSystemCall(unsigned /*lwp*/) {
1995    // TODO
1996    return false;
1997 }
1998
1999 // TODO
2000 bool process::needToAddALeafFrame(Frame , Address &) {
2001   return false;
2002 }
2003
2004
2005 void initSymbols(HANDLE procH, const string file, const string dir) {
2006   string searchPath;
2007   char sysRootDir[MAX_PATH+1];
2008   if (GetSystemDirectory(sysRootDir, MAX_PATH) == 0)
2009      assert(0);
2010   string sysSymsDir = string(sysRootDir) + "\\..\\symbols";
2011   if (dir.length())
2012     searchPath = dir + ";";
2013   searchPath = searchPath + sysSymsDir + ";" + sysSymsDir + "\\dll";
2014   if (!SymInitialize(procH, (char *)searchPath.c_str(), 0)) {
2015     fprintf(stderr,"SymInitialize failed, %x\n", GetLastError()); fflush(stderr);
2016     return;
2017   }
2018   if (!SymLoadModule(procH, NULL, (char *)file.c_str(), NULL, 0, 0)) {
2019     printf("SymLoadModule failed for \"%s\", %x\n",
2020             file.c_str(), GetLastError());
2021     return;
2022   }
2023 }
2024
2025
2026
2027
2028
2029 /*****************************************************************************
2030  * forkNewProcess: starts a new process, setting up trace and io links between
2031  *                the new process and the daemon
2032  * Returns true if succesfull.
2033  * 
2034  * Arguments:
2035  *   file: file to execute
2036  *   dir: working directory for the new process
2037  *   argv: arguments to new process
2038  *   envp: environment **** not in use
2039  *   inputFile: where to redirect standard input
2040  *   outputFile: where to redirect standard output
2041  *   traceLink: handle or file descriptor of trace link (read only)
2042  //removed all ioLink related code for output redirection
2043  *   ioLink: handle or file descriptor of io link (read only)
2044  *   pid: process id of new process
2045  *   tid: thread id for main thread (needed by WindowsNT)
2046  *   procHandle: handle for new process (needed by WindowsNT)
2047  *   thrHandle: handle for main thread (needed by WindowsNT)
2048  ****************************************************************************/
2049 bool forkNewProcess(string &file, string dir, vector<string> argv, 
2050                     vector<string>envp, string inputFile, string outputFile,
2051                     int &traceLink,  
2052                     int &pid, int &tid, 
2053                     int &procHandle, int &thrHandle, int /* stdin_fd */, 
2054                     int stdout_fd, int /* stderr_fd */) {
2055 #ifdef mips_unknown_ce2_11 //ccw 8 aug 2000 : 29 mar 2001
2056         WCHAR appName[256];
2057         WCHAR dirName[256];
2058         WCHAR commLine[256];
2059 #endif
2060
2061 #ifndef BPATCH_LIBRARY
2062 #ifdef notdef_Pipes     // isn't this all obsolete???
2063     HANDLE rTracePipe;
2064     HANDLE wTracePipe;
2065     // security attributes to make handles inherited
2066     SECURITY_ATTRIBUTES sa;
2067     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
2068     sa.bInheritHandle = true;
2069     sa.lpSecurityDescriptor = NULL;
2070     
2071     // create trace pipe
2072     if (!CreatePipe(&rTracePipe, &wTracePipe, &sa, 0)) {
2073         string msg = string("Unable to create trace pipe for program '") 
2074             + File + string("': ") + string(sys_errlist[errno]);
2075         showErrorCallback(68, msg);
2076         return(NULL);
2077     }
2078     
2079     /* removed for output redirection
2080     HANDLE rIoPipe;
2081     HANDLE wIoPipe;
2082     // create IO pipe
2083     // ioPipe is used to redirect the child's stdout & stderr to a pipe which
2084     // is in turn read by the parent via the process->ioLink socket.
2085     if (!CreatePipe(&rIoPipe, &wIoPipe, &sa, 0)) {
2086         string msg = string("Unable to create IO pipe for program '") + File +
2087             string("': ") + string(sys_errlist[errno]);
2088         showErrorCallback(68, msg);
2089         return(NULL);
2090     }
2091     SetEnvironmentVariable("PARADYN_IO_PIPE",
2092                            string((unsigned)wIoPipe).c_str());
2093     */
2094
2095     printf("tracepipe = %d\n", (unsigned)wTracePipe);
2096     // enter trace and IO pipes in child's environment
2097     SetEnvironmentVariable("PARADYN_TRACE_PIPE", 
2098                            string((unsigned)wTracePipe).c_str());
2099 #endif
2100     //  extern int traceSocket;
2101     //  SetEnvironmentVariable("PARADYND_TRACE_SOCKET", string((unsigned)traceSocket).c_str());
2102 #endif /* BPATCH_LIBRARY */
2103     
2104     // create the child process
2105     
2106     string args;
2107     for (unsigned ai=0; ai<argv.size(); ai++) {
2108         args += argv[ai];
2109         args += " ";
2110     }
2111     
2112     STARTUPINFO stinfo;
2113     memset(&stinfo, 0, sizeof(STARTUPINFO));
2114     stinfo.cb = sizeof(STARTUPINFO);
2115
2116     /*to do: output redirection
2117     //stinfo.hStdOutput = (HANDLE)ioLink;
2118     stinfo.hStdOutput = (HANDLE)stdout_fd;
2119     stinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
2120     stinfo.hStdError = GetStdHandle(STD_ERROR_HANDLE);
2121     stinfo.dwFlags |= STARTF_USESTDHANDLES;
2122     */
2123     PROCESS_INFORMATION procInfo;
2124 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
2125         kludgeWCHAR(file.c_str(),appName);
2126         kludgeWCHAR(args.c_str(),commLine);
2127         if(dir == ""){
2128                 dirName[0] = (unsigned short) 0;
2129         }else{
2130                 kludgeWCHAR(dir.c_str(),dirName);
2131         }
2132
2133         /* ccw 8 aug 2000  : 29 mar 2001
2134          WARNING:  
2135                 If compiler optimization are turned on (-Ox) for remoteDevice.C the following
2136                 line of code bugs. An extra parameter is passed to the function before 
2137                 appName and consequently each argument is shifted one to the right, 
2138                 completely destroying the code.
2139                 
2140                 DO NOT TURN ON -Ox for remoteDevice.C!
2141
2142                 if need be, pdwinnt.C can be compiled with -Ox
2143                 less optimization may be safe, it has not yet been tried. if someone is bored
2144                 they should try different optimization flags to see if any work correctly here.
2145                 Until then the mips/ce version of dyninst will be compiled w/o ANY optimizations!
2146         */
2147         //DebugBreak();
2148     if (BPatch::bpatch->rDevice->RemoteCreateProcess(appName , commLine,
2149                       NULL, NULL, false,
2150                       (DWORD) DEBUG_PROCESS  /* | CREATE_NEW_CONSOLE /* | CREATE_SUSPENDED */,
2151                       NULL, dirName, 
2152                       &stinfo, &procInfo)) {
2153
2154 #else
2155
2156     if (CreateProcess(file.c_str(), (char *)args.c_str(), 
2157                       NULL, NULL, TRUE,
2158                       DEBUG_PROCESS /* | CREATE_NEW_CONSOLE /* | CREATE_SUSPENDED */,
2159                       NULL, dir == "" ? NULL : dir.c_str(), 
2160                       &stinfo, &procInfo)) {
2161 #endif
2162
2163         procHandle = (Word)procInfo.hProcess;
2164         thrHandle = (Word)procInfo.hThread;
2165         pid = (Word)procInfo.dwProcessId;
2166         tid = (Word)procInfo.dwThreadId;
2167 #ifdef notdef_Pipes
2168         traceLink = (Word)rTracePipe;
2169         CloseHandle(wTracePipe);
2170         / *removed for output redirection
2171         //ioLink = (Word)rIoPipe;
2172         CloseHandle(wIoPipe);
2173         */
2174         //initSymbols((HANDLE)procHandle, file, dir);
2175 #else
2176         traceLink = -1;
2177         /* removed for output redirection
2178         ioLink = -1;
2179         */
2180 #endif
2181         return true;
2182     }
2183    
2184 #ifndef BPATCH_LIBRARY
2185 #ifdef notdef_Pipes
2186     CloseHandle(rTracePipe);
2187     CloseHandle(wTracePipe);
2188     / *removed for output redirection
2189     CloseHandle(rIoPipe);
2190     CloseHandle(wIoPipe);
2191     */
2192 #endif
2193 #endif /* BPATCH_LIBRARY */
2194
2195     // Output failure message
2196     LPVOID lpMsgBuf;
2197
2198     if (FormatMessage( 
2199             FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
2200             NULL,
2201             GetLastError(),
2202             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
2203             (LPTSTR) &lpMsgBuf,
2204             0,
2205             NULL 
2206         ) > 0) {
2207         char *errorLine = (char *)malloc(strlen((char *)lpMsgBuf) +
2208                                          file.length() + 64);
2209         if (errorLine != NULL) {
2210             sprintf(errorLine, "Unable to start %s: %s\n", file.c_str(),
2211                     (char *)lpMsgBuf);
2212             logLine(errorLine);
2213             showErrorCallback(68, (const char *) errorLine);
2214
2215             free(errorLine);
2216         }
2217
2218         // Free the buffer returned by FormatMsg
2219         LocalFree(lpMsgBuf);
2220     } else {
2221         char errorLine[512];
2222         sprintf(errorLine, "Unable to start %s: unknown error\n",
2223                 file.c_str());
2224         logLine(errorLine);
2225         showErrorCallback(68, (const char *) errorLine);
2226     }
2227
2228     return false;
2229 }
2230
2231 char *cplus_demangle(char *c, int) { 
2232     char buf[1000];
2233     if (c[0]=='_') {
2234         // VC++ 5.0 seems to decorate C symbols differently to C++ symbols
2235         // and the UnDecorateSymbolName() function provided by imagehlp.lib
2236         // doesn't manage (or want) to undecorate them, so it has to be done
2237         // manually, removing a leading underscore from functions & variables
2238         // and the trailing "$stuff" from variables (actually "$Sstuff")
2239         unsigned i;
2240         for (i=1; i<sizeof(buf) && c[i]!='$' && c[i]!='\0'; i++)
2241            { buf[i-1]=c[i]; }
2242         if (i==1) return 0; // avoid null names which seem to annoy Paradyn
2243         buf[i-1]='\0';
2244         return strdup(buf);
2245       }
2246     else if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_NAME_ONLY)) {
2247         //printf("Undecorate: %s = %s\n", c, buf);
2248
2249         // many symbols have a name like foo@4, we must remove the @4
2250         // just searching for an @ is not enough,
2251         // as it may occur on other positions. We search for the last one
2252         // and check that it is followed only by digits.
2253         char *p = strrchr(buf, '@');
2254         if (p) {
2255           char *q = p+1;
2256           strtoul(p+1, &q, 10);
2257           if (q > p+1 && *q == '\0') {
2258             *p = '\0';
2259           }
2260         }
2261         return strdup(buf);
2262     }
2263     return 0;
2264 }
2265
2266 bool OS::osKill(int pid) {
2267     bool res;
2268 #ifdef mips_unknown_ce2_11 //ccw 28 july 2000 : 29 mar 2001
2269     HANDLE h = BPatch::bpatch->rDevice->RemoteOpenProcess(PROCESS_ALL_ACCESS, false, pid);
2270 #else
2271     HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
2272 #endif
2273     if (h == NULL) {
2274         return false;
2275     }
2276 #ifdef mips_unknown_ce2_11 //ccw 31 aug 2000 : 29 mar 2001
2277     res = BPatch::bpatch->rDevice->RemoteTerminateProcess(h,0);
2278     BPatch::bpatch->rDevice->RemoteCloseHandle(h);
2279 #else
2280     res = TerminateProcess(h,0);
2281     CloseHandle(h);
2282 #endif
2283     return res;
2284 }
2285
2286 #if !defined(BPATCH_LIBRARY)
2287 rawTime64 process::getRawCpuTime_hw(int lwp_id) {
2288   lwp_id = 0;  // to turn off warning for now
2289   return 0;
2290 }
2291
2292 rawTime64
2293 FILETIME2rawTime64( FILETIME& ft )
2294 {
2295     return (((rawTime64)(ft).dwHighDateTime<<32) | 
2296             ((rawTime64)(ft).dwLowDateTime));
2297 }
2298
2299 /* return unit: nsecs */
2300 rawTime64 process::getRawCpuTime_sw(int lwp_id) {
2301   FILETIME kernelT, userT, creatT, exitT;
2302   rawTime64 now;
2303
2304   if(GetProcessTimes( (HANDLE)getProcFileDescriptor(),
2305       &creatT, &exitT, &kernelT,&userT)==0) {
2306     abort();
2307     return 0;
2308   }
2309
2310   // GetProcessTimes returns values in 100-ns units
2311   now = (FILETIME2rawTime64(userT)+FILETIME2rawTime64(kernelT));
2312
2313   // time shouldn't go backwards, but we'd better handle it if it does
2314   if (now < previous) {
2315      logLine("********* time going backwards in paradynd **********\n");
2316      now = previous;
2317   }
2318   else {
2319      previous = now;
2320   }
2321
2322   return now;
2323 }
2324
2325 bool process::catchupSideEffect(Frame &frame, instReqNode *inst)
2326 {
2327   return true;
2328 }
2329
2330 #endif
2331
2332 #ifdef mips_unknown_ce2_11 //ccw 2 aug 2000 : 29 mar 2001
2333
2334 #include "inst-mips.h"
2335 //this comes from irix.C
2336 bool process::heapIsOk(const vector<sym_data>&findUs)
2337
2338         
2339   //ccw 12 oct 2000 NEED TO FIND WinMain here or _WinMain then try to find main or _main
2340 //      DebugBreak();
2341
2342
2343   if (!(mainFunction = findOneFunction("WinMain")) &&
2344           !(mainFunction = findOneFunction("_WinMain"))) {
2345                 fprintf(stderr, "process::heapIsOk(): failed to find \"WinMain\"\n");
2346
2347                 if (!(mainFunction = findOneFunction("main")) &&
2348                 !(mainFunction = findOneFunction("_main"))) {
2349
2350                         //if (!(mainFunction = findOneFunction("CFrameWnd::OnCreate")) &&
2351                         //      !(mainFunction = findOneFunction("OnCreate"))) {
2352
2353                                 //the following is for MFC apps
2354                                 //what is wrong with M$? all these different names for main()
2355                                 if (!(mainFunction = findOneFunction("wWinMain")) &&
2356                                         !(mainFunction = findOneFunction("_wWinMain"))) {
2357
2358
2359                                         fprintf(stderr, "process::heapIsOk(): failed to find \"main\"\n");
2360                                         return false;
2361                                 }
2362                         //}
2363           }     
2364   }
2365
2366   for (unsigned i = 0; i < findUs.size(); i++) {
2367     const string &name = findUs[i].name;
2368     cerr << "Looking up symbol " << name << endl;
2369     /*
2370     Address addr = lookup_fn(this, name);
2371     if (!addr && findUs[i].must_find) {
2372       fprintf(stderr, "process::heapIsOk(): failed to find \"%s\"\n", name.c_str());
2373       return false;
2374     }
2375     */
2376   }
2377
2378   return true;
2379 }
2380 #endif
2381
2382
2383 fileDescriptor *getExecFileDescriptor(string filename, int &, bool)
2384 {
2385   fileDescriptor *desc = new fileDescriptor(filename);
2386   return desc;
2387 }
2388
2389 #ifndef BPATCH_LIBRARY
2390 void process::initCpuTimeMgrPlt() {
2391   cpuTimeMgr->installLevel(cpuTimeMgr_t::LEVEL_TWO, &process::yesAvail, 
2392                            timeUnit(fraction(100)), timeBase::bNone(), 
2393                            &process::getRawCpuTime_sw, "swCpuTimeFPtrInfo");
2394 }
2395 #endif
2396
2397 bool getLWPIDs(vector <unsigned> &LWPids)
2398 {
2399   assert (0 && "Not implemented");
2400   return false;
2401 }
2402
2403
2404
2405
2406 //
2407 // This function retrieves the name of a DLL that has been
2408 // loaded in an inferior process.  On the desktop flavors
2409 // of Windows, the debug event that we get for loaded DLLs
2410 // includes the location of a pointer to the DLL's image name.
2411 // (Note the indirection.)  On Windows CE, the event contains
2412 // the location of the image name string, with no indirection.
2413 //
2414 // There are several complications to overcome when reading this string:
2415 //
2416 // 1.  There is no guarantee that the image name is available.
2417 //     In this case, the location in the debug event may be NULL,
2418 //     or the pointer in the inferior process' address space may be NULL.
2419 // 2.  The image name string may be either ASCII or Unicode.  Most of
2420 //     the Windows system DLLs have Unicode strings, but many user-built
2421 //     DLLs use single-byte strings.  If the string is Unicode, we need
2422 //     to copy it to our address space and convert it to a single-byte
2423 //     string because the rest of Paradyn/Dyninst has no clue what to
2424 //     do with Unicode strings.
2425 // 3.  We don't know how long the string is.  We have a loose upper
2426 //     bound in that we know it is not more than MAX_PATH characters.
2427 //     Unfortunately, the call we use to read from the inferior
2428 //     process' address space will return failure if we ask for more
2429 //     bytes than it can actually read (so we can't just issue a read
2430 //     for MAX_PATH characters).  Given this limitation, we have to
2431 //     try a read and check whether the read succeeded *and* whether
2432 //     we read the entire image name string.  If not, we have to adjust
2433 //     the amount we read and try again.
2434 //
2435 static
2436 string
2437 GetLoadedDllImageName( process* p, const DEBUG_EVENT& ev )
2438 {
2439         string ret;
2440
2441
2442         if( ev.u.LoadDll.lpImageName == NULL )
2443         {
2444                 // there is no image name string for us to read
2445                 return ret;
2446         }
2447
2448         char* msgText = new char[1024]; // buffer for error messages
2449
2450 #if defined(mips_unknown_ce2_11)
2451
2452         // On Windows CE, the address given in the debug event struct
2453         // is the address of the DLL name string.
2454         void* pImageName = ev.u.LoadDll.lpImageName;
2455 #else // defined(ce)
2456         // On non-CE flavors of Windows, the address given in the debug
2457         // event struct is the address of a pointer to the DLL name string.
2458         void* pImageName = NULL;
2459         if( !p->readDataSpace( ev.u.LoadDll.lpImageName, 4, &pImageName, false ) )
2460         {
2461                 sprintf( msgText, "Failed to read DLL image name pointer: %d\n",
2462                         GetLastError() );
2463                 logLine( msgText );
2464         }
2465 #endif // defined(ce)
2466
2467         if( pImageName != NULL )
2468         {
2469                 // we have the pointer to the DLL image name -
2470                 // now read the name
2471
2472                 // allocate a conservatively-sized buffer
2473                 char* buf = new char[(MAX_PATH + 1) * sizeof(WCHAR)];
2474                 WCHAR* wbuf = (WCHAR*)buf;
2475
2476                 // We don't know how long the image name actually is, but
2477                 // we do know that they tend not to be very long.
2478                 // Therefore, we use a scheme to try to minimize the number
2479                 // of reads needed to get the image name.
2480                 // We do reads within ranges, starting with [1,128] bytes,
2481                 // then [129,256] bytes, etc. up to MAX_PATH if necessary.
2482                 // Within each range, we do reads following a binary search
2483                 // algorithm.  For example, for the [1,128] range, we start
2484                 // by trying to read 128 bytes.  If that read fails, we
2485                 // try to half the number of bytes (i.e., 64).  If that
2486                 // read also fails, we continue to halve the read requests 
2487                 // until we find one that succeeds.
2488                 //
2489                 // When a read succeeds, we still may not have gotten the
2490                 // entire string.  So when reads start succeeding, we have to
2491                 // check the data we got for a null-terimated string.  If we didn't
2492                 // get the full string, we change the byte count to either
2493                 // move into the next higher range (if we were already reading
2494                 // the max within the current range) or we set it to a factor
2495                 // of 1.5 of the current byte count to try a value between the
2496                 // current succeeding read and one that had failed.
2497                 unsigned int loRead = 1;                // range boundaries
2498                 unsigned int hiRead = 128;
2499                 unsigned int cbRead = 128;              // number of bytes to read
2500                 unsigned int chunkRead = 64;    // amount to change cbRead if we fail
2501                                                                                 // we will not halve this before we read
2502                 bool gotString = false;
2503                 bool doneReading = false;
2504                 while( !doneReading )
2505                 {
2506                         // try the read with the current byte count
2507                         if( p->readDataSpace( pImageName, cbRead, buf, false ) )
2508                         {
2509                                 // the read succeeded - 
2510                                 // did we get the full string?
2511                                 if( ev.u.LoadDll.fUnicode )
2512                                 {
2513                                         unsigned int cbReadIdx = cbRead / sizeof(WCHAR);
2514                                         wbuf[cbReadIdx] = L'\0';
2515                                         WCHAR* nulp = wcschr( wbuf, L'\0' );
2516                                         assert( nulp != NULL );                 // because we just NULL-terminated the string
2517                                         gotString = (nulp != &(wbuf[cbReadIdx]));
2518                                 }
2519                                 else
2520                                 {
2521                                         buf[cbRead] = '\0';
2522                                         char* nulp = strchr( buf, '\0' );
2523                                         assert( nulp != NULL );                 // because we just NULL-terminated the string
2524                                         gotString = (nulp != &(buf[cbRead]));
2525                                 }
2526
2527                                 if( gotString )
2528                                 {
2529                                         doneReading = true;
2530                                 }
2531                                 else
2532                                 {
2533                                         // we didn't get the full string
2534                                         // we need to try a larger read
2535                                         if( cbRead == hiRead )
2536                                         {
2537                                                 // we were at the high end of the current range -
2538                                                 // move to the next range
2539                                                 loRead = hiRead + 1;
2540                                                 hiRead = loRead + 128 - 1;
2541                                                 chunkRead = 128;                                // we will halve this before we read again
2542                                                 if( loRead > (MAX_PATH * sizeof(WCHAR)) )
2543                                                 {
2544                                                         // we've tried every range but still failed
2545                                                         doneReading = true;
2546                                                 }
2547                                                 else
2548                                                 {
2549                                                         cbRead = hiRead;
2550                                                 }
2551                                         }
2552                                         else
2553                                         {
2554                                                 // we were within the current range -
2555                                                 // try something higher but still within the range
2556                                                 cbRead = cbRead + chunkRead;
2557                                         }
2558                                 }
2559                         }
2560                         else
2561                         {
2562                                 // the read failed -
2563                                 // we need to try a smaller read
2564                                 if( cbRead > loRead )
2565                                 {
2566                                         unsigned int nextRead = cbRead - chunkRead;
2567                                         if( nextRead == cbRead )
2568                                         {
2569                                                 // we can't subdivide any further
2570                                                 doneReading = true;
2571                                         }
2572                                         else
2573                                         {
2574                                                 cbRead = nextRead;
2575                                         }
2576                                 }
2577                                 else
2578                                 {
2579                                         // there are no smaller reads to try in this range,
2580                                         // and by induction, in any range.
2581                                         doneReading = true;
2582                                 }
2583                         }
2584
2585                         // update the amount that we use to change the read request
2586                         chunkRead /= 2;
2587                 }
2588
2589                 if( !gotString )
2590                 {
2591                         // this is a serious problem because some read 
2592                         // should've succeeded
2593                         sprintf( msgText, "Failed to read DLL image name - no read succeeded\n" );
2594                         logLine( msgText );
2595                 }
2596                 else
2597                 {
2598                         if( ev.u.LoadDll.fUnicode )
2599                         {
2600                                 // the DLL path is a Unicode string
2601                                 // we have to convert it to single-byte characters
2602                                 char* tmpbuf = new char[MAX_PATH];
2603
2604                                 WideCharToMultiByte(CP_ACP,             // code page to use (ANSI)
2605                                                                         0,                      // flags
2606                                                                         wbuf,           // Unicode string
2607                                                                         -1,                     // length of Unicode string (-1 => null-terminated)
2608                                                                         tmpbuf,         // destination buffer
2609                                                                         MAX_PATH,       // size of destionation buffer
2610                                                                         NULL,           // default for unmappable chars
2611                                                                         NULL);          // var to set when defaulting a char
2612
2613                                 // swap buffers so that buf points to the single-byte string
2614                                 // when we're out of this code block
2615                                 delete[] buf;
2616                                 buf = tmpbuf;
2617                         }
2618                         ret = buf;
2619                 }
2620
2621                 delete[] buf;
2622         }
2623         else
2624         {
2625                 // we were given an image name pointer, but it was NULL
2626                 // this happens for some system DLLs, and if we attach to
2627                 // the process instead of creating it ourselves.
2628                 // However, it is very important for us to know about kernel32.dll,
2629                 // so we check for it specially.
2630                 //
2631                 // This call only changes the string parameter if the indicated file is
2632                 // actually kernel32.dll.
2633                 kludge_isKernel32Dll( ev.u.LoadDll.hFile, ret );
2634         }
2635
2636         // cleanup
2637         delete[] msgText;
2638
2639         return ret;
2640 }
2641