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