Added several calls to API (waitForStatusChange, BPatch_variableExpr
[dyninst.git] / dyninstAPI / src / pdwinnt.C
1 /*
2  * Copyright (c) 1996 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 #include "dyninstAPI/src/symtab.h"
43 #include "util/h/headers.h"
44 #include "dyninstAPI/src/os.h"
45 #include "dyninstAPI/src/process.h"
46 #include "dyninstAPI/src/pdThread.h"
47 #include "dyninstAPI/src/stats.h"
48 #include "util/h/Types.h"
49 #include "paradynd/src/showerror.h"
50
51 #ifndef BPATCH_LIBRARY
52 #include "paradynd/src/main.h"
53 #endif
54
55 #ifdef BPATCH_LIBRARY
56 /* XXX This is only needed for emulating signals. */
57 #include "BPatch_thread.h"
58 #include "nt_signal_emul.h"
59 #endif
60
61 extern bool isValidAddress(process *proc, Address where);
62 extern process *findProcess(int);
63
64 //HANDLE kludgeProcHandle;
65
66 void printSysError(unsigned errNo) {
67     char buf[1000];
68     FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, errNo, 
69                   MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
70                   buf, 1000, NULL);
71     fprintf(stderr, "*** System error [%d]: %s\n", errNo, buf);
72     fflush(stderr);
73 }
74
75
76 // check if a file handle is for kernel32.dll
77 static bool kludge_isKernel32Dll(HANDLE fileHandle, string &kernel32Name) {
78     static DWORD IndxHigh, IndxLow;
79     static bool firstTime = true;
80     BY_HANDLE_FILE_INFORMATION info;
81     static string kernel32Name_;
82
83     if (firstTime) {
84         HANDLE kernel32H;
85         firstTime = false;
86         char sysRootDir[MAX_PATH+1];
87         if (GetSystemDirectory(sysRootDir, MAX_PATH) == 0)
88           assert(0);
89         kernel32Name_ = string(sysRootDir) + "\\kernel32.dll";
90         kernel32H = CreateFile(kernel32Name_.string_of(), GENERIC_READ, 
91                                FILE_SHARE_READ, NULL, OPEN_EXISTING, NULL, NULL);
92         assert(kernel32H);
93         if (!GetFileInformationByHandle(kernel32H, &info)) {
94             printSysError(GetLastError());
95             assert(0);
96         }
97         IndxHigh = info.nFileIndexHigh;
98         IndxLow = info.nFileIndexLow;
99         CloseHandle(kernel32H);
100     }
101
102     if (!GetFileInformationByHandle(fileHandle, &info))
103         return false;
104
105     if (info.nFileIndexHigh==IndxHigh && info.nFileIndexLow==IndxLow) {
106       kernel32Name = kernel32Name_;
107       return true;
108     }
109     return false;
110 }
111
112
113 void dumpMem(process *p, void * addr, unsigned nbytes) {
114     unsigned char *buf = new unsigned char[nbytes];
115     memset(buf, 0, nbytes);
116     function_base *f;
117     assert(buf);
118
119     if (f = p->findFunctionIn((Address)addr))
120         printf("Function %s, addr=%x, sz=%d\n", 
121                f->prettyName().string_of(),
122                f->getAddress(p),
123                f->size());
124     p->readDataSpace((void *)((unsigned)addr-32), nbytes, buf, true);
125     printf("## %x:\n", (unsigned)addr-32);
126     for (unsigned u = 0; u < nbytes; u++)
127         printf(" %x", buf[u]);
128     p->readDataSpace(addr, nbytes, buf, true);
129     printf("## %x:\n", addr);
130     for (unsigned u1 = 0; u1 < nbytes; u1++)
131         printf(" %x", buf[u1]);
132 }
133
134
135
136 /***
137   process::walkStack - get a stack trace using the imagehlp function StackWalk
138   Because the compiler can do optimizations that omit the frame pointer,
139   it may not be possible to get a complete stack trace in some cases.
140   We assume that a trace is complete if we get to the main function (main or WinMain).
141   If we can't get a complete trace, we return an empty vector.
142 ***/
143 vector<Address> process::walkStack(bool noPause) {
144   vector<Address> pcs;
145   bool needToCont = noPause ? false : (status() == running);
146
147   if (!noPause && !pause()) {
148      // pause failed...give up
149      cerr << "walkStack: pause failed" << endl;
150      return pcs;
151   }
152
153   static STACKFRAME zero;
154   STACKFRAME sf = zero;
155   CONTEXT cont;
156
157   cont.ContextFlags = CONTEXT_FULL;
158   if (!GetThreadContext((HANDLE)threads[0]->get_handle(), &cont))
159      cerr << "walkStack: GetThreadContext failed\n";
160   //fprintf(stderr, "Context: EIP = %x, ESP = %x, EBP = %x\n",
161   //     cont.Eip, cont.Esp, cont.Ebp);
162   //fflush(stderr);
163
164   sf.AddrPC.Offset = cont.Eip;
165   sf.AddrPC.Mode = AddrModeFlat;
166   sf.AddrFrame.Offset = cont.Ebp;
167   sf.AddrFrame.Mode = AddrModeFlat;
168   sf.AddrStack.Offset = cont.Esp;
169   sf.AddrStack.Mode = AddrModeFlat;
170
171   sf.AddrReturn.Mode = AddrModeFlat;
172
173   bool res;
174   bool reachedMain = false; // set to true if we reach the main function
175   while (1) {
176     res = StackWalk(IMAGE_FILE_MACHINE_I386, (HANDLE)getProcFileDescriptor(), NULL,
177                     &sf, NULL,
178                     ReadProcessMemory, SymFunctionTableAccess, SymGetModuleBase,
179                     NULL);
180
181     if (!res && GetLastError() == 0) {
182       // reached end of stack
183       break;
184     } else if (!res && GetLastError() != 0) {
185       // error - can't complete stack walk
186       //fprintf(stderr, "error walking stack\n");
187       //printSysError(GetLastError());
188       break;
189     }
190     else {
191       if (findFunctionIn(sf.AddrPC.Offset)==getMainFunction())
192         reachedMain = true;
193
194       pcs += sf.AddrPC.Offset;
195     }
196
197     if (sf.AddrReturn.Offset == 0) {
198       pcs += 0;
199       break;
200     }
201
202   }
203
204   //for (unsigned u = 0; u < pcs.size(); u++) {
205   //  function_base *pdf = findFunctionIn(pcs[u]);
206   //  fprintf(stderr,"> %x (%s)\n", pcs[u], pdf ? pdf->prettyName().string_of() : "");
207   //  fflush(stderr);
208   //}
209
210   if (!reachedMain) {
211     // error - incomplete trace, return an empty vector
212     pcs.resize(0);
213     //fprintf(stderr, "****** walkStack failed\n"); fflush(stderr);
214   }
215
216   if (!noPause && needToCont) {
217      if (!continueProc()){
218         cerr << "walkStack: continueProc failed" << endl;
219      }
220   }  
221   return(pcs);
222 }
223
224
225
226 /* 
227    Loading libDyninstRT.dll
228
229    We load libDyninstRT.dll dynamically, by inserting code into the
230    application to call LoadLibraryA. We don't use the inferior RPC
231    mechanism from class process because it already assumes that
232    libdyninst is loaded (it uses the inferior heap).
233    Instead, we use a simple inferior call mechanism defined below
234    to insert the code to call LoadLibraryA("libdyninstRT.dll").
235  */
236
237 Address loadDyninstDll(process *p, char Buffer[LOAD_DYNINST_BUF_SIZE]) {
238     Address codeBase = p->getImage()->codeOffset();
239
240     Address LoadLibBase;
241     Address LoadLibAddr;
242     Symbol sym;
243     if (!p->getSymbolInfo("_LoadLibraryA@4", sym, LoadLibBase)) {
244         printf("unable to find function LoadLibrary\n");
245         assert(0);
246     }
247     LoadLibAddr = sym.addr() + LoadLibBase;
248     assert(LoadLibAddr);
249
250     char ibuf[LOAD_DYNINST_BUF_SIZE];
251     char *iptr = ibuf;
252
253     // push nameAddr ; 5 bytes
254     *iptr++ = (char)0x68; 
255     *(int *)iptr = codeBase + 14; 
256     iptr += sizeof(int);
257
258     // call LoadLibrary ; 5 bytes
259     *iptr++ = (char)0xe8;
260     // offset relative to next instruction (address codeBase+10)
261     *(int *)iptr = LoadLibAddr - (codeBase + 10);
262     iptr += sizeof(int);
263
264     // add sp, 4
265     *iptr++ = (char)0x83; *iptr++ = (char)0xc4; *iptr++ = (char)0x04;
266
267     // int3
268     *iptr++ = (char)0xcc;
269
270 #ifdef BPATCH_LIBRARY
271     strcpy(iptr, "libdyninstAPI_RT.dll");
272 #else
273     strcpy(iptr, "libdyninstRT.dll");
274 #endif
275
276     p->readDataSpace((void *)codeBase, LOAD_DYNINST_BUF_SIZE, Buffer, false);
277     p->writeDataSpace((void *)codeBase, LOAD_DYNINST_BUF_SIZE, ibuf);
278
279     return codeBase;
280 }
281
282
283
284 // osTraceMe is not needed in Windows NT
285 void OS::osTraceMe(void) {}
286
287
288 #ifndef BPATCH_LIBRARY
289 void checkProcStatus() {
290     int wait_status;
291     extern void doDeferredRPCs();
292
293     process::waitProcs(&wait_status);
294     doDeferredRPCs();
295 }
296 #endif
297
298 /*
299    wait for inferior processes to terminate or stop.
300 */
301 #ifdef BPATCH_LIBRARY
302 int process::waitProcs(int *status, bool block) {
303 #else
304 int process::waitProcs(int *status) {
305 #endif
306     DEBUG_EVENT debugEv;
307     process *p;
308 #ifdef BPATCH_LIBRARY
309     *status = 0;
310 #endif
311
312     // We wait for 1 milisecond here. On the Unix platforms, the wait
313     // happens on the select in controllerMainLoop. But on NT, because
314     // we have to handle traps, we set the timeout on the select as 0,
315     // so that we can check for traps quicly
316 #ifdef BPATCH_LIBRARY
317     DWORD milliseconds;
318     if (block) milliseconds = INFINITE;
319     else milliseconds = 1;
320     if (!WaitForDebugEvent(&debugEv, milliseconds))
321         return 0;
322 #else
323        if (!WaitForDebugEvent(&debugEv, 1))
324         return 0;
325 #endif
326
327     //printf("Debug event from process %d, tid %d\n", debugEv.dwProcessId,
328     //   debugEv.dwThreadId);
329
330     p = findProcess(debugEv.dwProcessId);
331     if (p == NULL) {
332         /* 
333            this case can happen when we create a process, but then are
334            unable to parse the symbol table, and so don't complete the
335            creation of the process. We just ignore the event here.  
336         */
337         ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
338                            DBG_CONTINUE);
339         return 0; 
340     }
341
342     switch (debugEv.dwDebugEventCode) {
343     case EXCEPTION_DEBUG_EVENT: {
344         DWORD exnCode = debugEv.u.Exception.ExceptionRecord.ExceptionCode;
345         switch(exnCode) {
346         case EXCEPTION_BREAKPOINT: {
347             //printf("Debug breakpoint exception, %d, addr = %x\n", 
348             //       debugEv.u.Exception.ExceptionRecord.ExceptionFlags,
349             //       debugEv.u.Exception.ExceptionRecord.ExceptionAddress);
350
351             if (!p->reachedFirstBreak) {
352
353                 if (!p->hasLoadedDyninstLib && !p->isLoadingDyninstLib) {
354                     Address addr = loadDyninstDll(p, p->savedData);
355                     p->savedRegs = p->getRegisters();
356                     p->changePC(addr);
357                     //p->LoadDyninstTrapAddr = addr + 0xd;
358                     p->isLoadingDyninstLib = true;
359                     break;
360                 } else if (p->isLoadingDyninstLib) {
361                     p->isLoadingDyninstLib = false;
362                     p->hasLoadedDyninstLib = true;
363                     p->restoreRegisters(p->savedRegs);
364                     delete p->savedRegs;
365                     p->writeDataSpace((void *)p->getImage()->codeOffset(),
366                                       LOAD_DYNINST_BUF_SIZE,
367                                       (void *)p->savedData);
368                 }
369
370                 p->reachedFirstBreak = true;
371       
372                 if (!p->createdViaAttach) {
373                     int pid = p->getPid();
374                     p->status_ = stopped;
375
376                     if (!p->initDyninstLib()) {
377                         OS::osKill(pid);
378                         handleProcessExit(p, -1);
379 #ifdef BPATCH_LIBRARY
380                         *status = SIGEM_SIGNALED | SIGTERM;
381                         return p->getPid();
382 #else
383                         return 0;
384 #endif
385                     }
386
387                     string buffer = string("PID=") + string(pid);
388                     buffer += string(", passed trap at start of program");
389                     statusLine(buffer.string_of());
390       
391                     buffer=string("PID=") + string(pid) 
392                          + ", installing call to DYNINSTinit()";
393                     statusLine(buffer.string_of());
394                     p->installBootstrapInst();
395       
396                     // now, let main() and then DYNINSTinit() get invoked.  As it
397                     // completes, DYNINSTinit() does a DYNINSTbreakPoint, at which time
398                     // we read bootstrap information "sent back" (in a global vrble),
399                     // propagate metric instances, do tp->newProgramCallbackFunc(), etc.
400                     break;
401                 } else {
402                     //printf("First breakpoint after attach\n");
403                     p->pause_();
404                     break;
405                 }
406             }
407
408             // the process has already been initialized
409             // First lookup in the tramp table, to see if the breakpoint
410             // is from an instrumentation point.
411
412             // lookup in tramp table
413             unsigned trampAddr = 0;
414             unsigned u; unsigned k;
415             unsigned key = 
416                 (unsigned)debugEv.u.Exception.ExceptionRecord.ExceptionAddress;
417             for (u = HASH1(key); 1; u = (u + HASH2(key)) % TRAMPTABLESZ) {
418                 k = p->trampTable[u].key;
419                 if (k == 0)
420                     break;
421                 else if (k == key) {
422                     trampAddr = p->trampTable[u].val;
423                     break;
424                 }
425             }
426             if (trampAddr) {
427                 // this is a trap from an instrumentation point
428                 // change the PC to the address of the base tramp
429
430                 for (unsigned i = 0; i < p->threads.size(); i++) {
431                     if (p->threads[i]->get_tid()==debugEv.dwThreadId) {
432                         HANDLE thrH = (HANDLE)p->threads[i]->get_handle();
433                         CONTEXT cont;
434                         cont.ContextFlags = CONTEXT_FULL;
435                         if (!GetThreadContext(thrH, &cont))
436                             assert(0);
437                         cont.Eip = trampAddr;
438                         if (!SetThreadContext(thrH, &cont))
439                             assert(0);
440                     }
441                 }
442
443                 break;
444             }
445
446             // If it is not from an instrumentation point,
447             // it could be from a call to DYNINSTbreakPoint
448             // or an inferior procedure call
449
450             p->status_ = stopped;
451             p->pause_();
452             int result = p->procStopFromDYNINSTinit();
453             assert(result >= 0 && result <= 2);
454             if (result != 0) {
455                 if (result == 1) {
456                     //p->pause_();
457                 } else {
458                     // procStopFromDYNINSTinit called continueProc()
459                     // What should we do here?
460                     break;
461                 }
462             } else if (p->handleTrapIfDueToRPC()) {
463                 //p->pause_();
464                 break;
465             } else {
466 #ifdef BPATCH_LIBRARY /* Don't ignore unknown bkpt in library; leave stopped. */
467                 *status = SIGEM_STOPPED | SIGTRAP;
468 #else
469                 // Unknown breakpoint: we just ignore it
470                 printf("Debug breakpoint exception, %d, addr = %x\n", 
471                        debugEv.u.Exception.ExceptionRecord.ExceptionFlags,
472                        debugEv.u.Exception.ExceptionRecord.ExceptionAddress);
473                 p->status_ = running;
474                 p->continueProc_();
475 #endif
476             }
477             break;
478         }
479         case EXCEPTION_ILLEGAL_INSTRUCTION:
480             //printf("Illegal instruction\n");
481             p->pause_();
482             p->status_ = stopped;
483             if (p->handleTrapIfDueToRPC()) {
484                 // handleTrapIfDueToRPC calls continueProc()
485                 break;
486             }
487             p->status_ = running;
488             p->continueProc_();
489             ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
490                                DBG_EXCEPTION_NOT_HANDLED);
491             return 0;
492         case EXCEPTION_ACCESS_VIOLATION:
493             printf("Access violation exception, %d, addr = %x\n", 
494                    debugEv.u.Exception.ExceptionRecord.ExceptionFlags,
495                    debugEv.u.Exception.ExceptionRecord.ExceptionAddress);
496             dumpMem(p, debugEv.u.Exception.ExceptionRecord.ExceptionAddress, 32);
497             //  ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
498             //                     DBG_EXCEPTION_NOT_HANDLED);
499             //  break;
500         default:
501             //printf("exeption %x, addr %x\n", exnCode, 
502             //   debugEv.u.Exception.ExceptionRecord.ExceptionAddress);
503             ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
504                                DBG_EXCEPTION_NOT_HANDLED);
505             return 0;
506         }
507     } break;
508
509     case CREATE_THREAD_DEBUG_EVENT: {
510         //printf("create thread, tid = %d\n", debugEv.dwThreadId);
511         assert(p->threads.size() > 0); // main thread should be already defined
512         pdThread *t = new pdThread(p, debugEv.dwThreadId,
513                                    debugEv.u.CreateThread.hThread);
514         p->threads += t;
515     } break;
516
517     case CREATE_PROCESS_DEBUG_EVENT: {
518         CREATE_PROCESS_DEBUG_INFO info = debugEv.u.CreateProcessInfo;
519         //printf("CREATE_PROCESS event: %d\n", debugEv.dwProcessId);
520         p = findProcess(debugEv.dwProcessId);
521         if (p) {
522             //fprintf(stderr,"create process: base = %x\n", info.lpBaseOfImage);
523             if (p->threads.size() == 0) {
524                 // define the main thread
525                 p->threads += new pdThread(p);
526             }
527             p->threads[0]->update_handle(debugEv.dwThreadId, 
528                                          debugEv.u.CreateProcessInfo.hThread);
529             
530         }
531     } break;
532
533     case EXIT_THREAD_DEBUG_EVENT: {
534         //printf("exit thread, tid = %d\n", debugEv.dwThreadId);
535         unsigned nThreads = p->threads.size();
536         // start from one to skip main thread
537         for (unsigned u = 1; u < nThreads; u++) {
538             if (p->threads[u]->get_tid() == debugEv.dwThreadId) {
539                 delete p->threads[u];
540                 p->threads[u] = p->threads[nThreads-1];
541                 p->threads.resize(nThreads-1);
542                 break;
543             }
544         }
545     } break;
546
547     case EXIT_PROCESS_DEBUG_EVENT:
548         p = findProcess(debugEv.dwProcessId);
549         if (p) {
550             //printf("process %d exited\n", p->getPid());
551             handleProcessExit(p, debugEv.u.ExitProcess.dwExitCode);
552         }
553 #ifdef BPATCH_LIBRARY
554         *status = SIGEM_EXITED;
555 #else
556         break;
557 #endif
558
559     case LOAD_DLL_DEBUG_EVENT: {
560         //printf("load dll: hFile=%x, base=%x, debugOff=%x, debugSz=%d lpname=%x, %d\n",
561         //       debugEv.u.LoadDll.hFile, debugEv.u.LoadDll.lpBaseOfDll,
562         //       debugEv.u.LoadDll.dwDebugInfoFileOffset,
563         //       debugEv.u.LoadDll.nDebugInfoSize,
564         //       debugEv.u.LoadDll.lpImageName,
565         //       /*debugEv.u.LoadDll.fUnicode*/
566         //       GetFileSize(debugEv.u.LoadDll.hFile,NULL));
567
568         // We are currently not handling dynamic libraries loaded after the
569         // application starts.
570         if (p->isBootstrappedYet())
571           break;
572
573         if (!SymLoadModule((HANDLE)p->getProcFileDescriptor(),
574                            debugEv.u.LoadDll.hFile,
575                            NULL, NULL, 0, 0)) {
576           printf("SymLoadModule failed, %x\n", GetLastError());
577         }
578
579         // set the proc handle for the process that is loading the library
580         // This is need when we use the imagehelp library to get the
581         // symbols for the dll.
582         // kludgeProcHandle = (HANDLE)p->getProcFileDescriptor();
583
584         void *addr = debugEv.u.LoadDll.lpImageName;
585         int ptr = 0;
586         if (addr) {
587             /***
588               addr is a pointer to the image name (in the application address space)
589               There is a problem here, because this pointer can be null and it is
590               null in some cases (in particular, if we attach to a running process
591               it is always null). This means that it can be difficult to find
592               the name of an image. 
593
594               Currently, if we can't find the name, we just ignore the
595               image.  However, we need to at least be able to parse
596               kernel32.dll, because this library contains some very
597               important functions, including LoadLibrary, which we
598               need to call to load libdyninstRT.dll. We use the following
599               kludge to find if a library is kernel32.dll: the function
600               klugde_isKernel32Dll open a handle to kernel32.dll. We then
601               find if the handle we get from the LOAD_DLL_DEBUG_EVENT
602               is for the same file.
603             ***/
604
605             p->readDataSpace_(addr, 4, &ptr);
606             //printf("ptr = %x\n", ptr);
607             char buffer[MAX_PATH];
608             string kernel32Path;
609             if (ptr) {
610                 if (debugEv.u.LoadDll.fUnicode) {
611                     unsigned short wbuffer[128];
612                     p->readDataSpace_((void *)ptr, 128*sizeof(short), wbuffer);
613                     WideCharToMultiByte(CP_ACP, 0, wbuffer, 128,
614                                         buffer, 128, NULL, NULL);
615                 } else {
616                     p->readDataSpace_((void *)ptr, 128, buffer);
617                 }
618                 //printf("Dll name: %s, base = %x\n", buffer, debugEv.u.LoadDll.lpBaseOfDll);
619             }
620             else if (kludge_isKernel32Dll(debugEv.u.LoadDll.hFile, kernel32Path)) {
621                 assert(kernel32Path.length() > 0);
622                 assert(kernel32Path.length() < sizeof(buffer));
623                 strcpy(buffer, kernel32Path.string_of());
624             } else
625                 break;
626             shared_object *so = 
627               new shared_object(string(buffer), 0, false, true, true, 0);
628             assert(p->dyn);
629             p->dyn->sharedObjects += so;
630             if (!p->shared_objects) {
631               p->shared_objects = new vector<shared_object *>;
632             }
633             *(p->shared_objects) += so;
634 #ifndef BPATCH_LIBRARY
635             tp->resourceBatchMode(true);
636 #endif 
637             p->addASharedObject(*so);
638 #ifndef BPATCH_LIBRARY
639             tp->resourceBatchMode(false);
640 #endif 
641             p->setDynamicLinking();
642           }
643       }
644     break;
645     case UNLOAD_DLL_DEBUG_EVENT:
646         // TODO
647         //printf("unload dll\n");
648         break;
649     case OUTPUT_DEBUG_STRING_EVENT:
650         //printf("output debug string\n");
651         break;
652     case RIP_EVENT:
653         //printf("rip event\n");
654         break;
655     default:
656         ;
657         //printf("unknown debug event\n");
658         
659     }
660     
661     if (!ContinueDebugEvent(debugEv.dwProcessId, debugEv.dwThreadId, 
662                             DBG_CONTINUE)) {
663         printf("ContinueDebugEvent failed\n");
664         printSysError(GetLastError());
665     }
666
667 #ifdef BPATCH_LIBRARY
668     if (*status)
669         return debugEv.dwProcessId;
670     else
671         return 0;
672 #else
673     return 0;
674 #endif
675 }
676
677
678 // already setup on this FD.
679 // disconnect from controlling terminal 
680 void OS::osDisconnect(void) {
681 #ifdef notdef
682   int ttyfd = open ("/dev/tty", O_RDONLY);
683   ioctl (ttyfd, TIOCNOTTY, NULL); 
684   P_close (ttyfd);
685 #endif
686 }
687
688
689 bool process::attach() {
690     if (createdViaAttach) {
691         if (!DebugActiveProcess(getPid())) {
692             //printf("Error: DebugActiveProcess failed\n");
693             return false;
694         }
695     }
696     proc_fd = (int)OpenProcess(PROCESS_ALL_ACCESS, false, getPid());
697     if (proc_fd == NULL) {
698         //printf("Error: OpenProcess failed\n");
699         assert(0);
700     }
701
702     void initSymbols(HANDLE procH, const string file, const string dir);
703     initSymbols((HANDLE)proc_fd, symbols->file(), "");
704     if (createdViaAttach) {
705         //
706         //void initSymbols(HANDLE procH, const string file, const string dir);
707         //initSymbols((HANDLE)proc_fd, symbols->file(), "");
708     }
709     return true;
710 }
711
712 /* continue a process that is stopped */
713 bool process::continueProc_() {
714     if (hasNewPC) {
715       changePC(currentPC_);
716       hasNewPC = false;
717     }
718     for (unsigned u = 0; u < threads.size(); u++) {
719         unsigned count = ResumeThread((HANDLE)threads[u]->get_handle());
720         if (count == 0xFFFFFFFF) {
721             printSysError(GetLastError());
722             return false;
723         }
724     }
725     return true;
726 }
727
728
729 #ifdef BPATCH_LIBRARY
730 /*
731    terminate execution of a process
732  */
733 bool process::terminateProc_()
734 {
735     OS::osKill(pid);
736     handleProcessExit(this, -1);
737     return true;
738 }
739 #endif
740
741
742 /*
743    pause a process that is running
744 */
745 bool process::pause_() {
746     for (unsigned u = 0; u < threads.size(); u++) {
747         unsigned count = SuspendThread((HANDLE)threads[u]->get_handle());
748         if (count == 0xFFFFFFFF) {
749             printf("pause_: %d\n", threads[u]->get_tid());
750             printSysError(GetLastError());
751             return false;
752         } 
753     }
754     return true;
755 }
756
757 /*
758    close the file descriptor for the file associated with a process
759 */
760 bool process::detach_() {
761     return false;
762 }
763
764
765 #ifdef BPATCH_LIBRARY
766 /*
767    detach from thr process, continuing its execution if the parameter "cont"
768    is true.
769  */
770 bool process::API_detach_(const bool cont)
771 {
772     // XXX Not yet implemented
773     assert(false);
774     return false;
775 }
776 #endif
777
778
779 bool process::dumpCore_(const string) {
780     return false;
781 }
782
783 bool process::writeTextWord_(caddr_t inTraced, int data) {
784     return writeDataSpace_(inTraced, sizeof(int), (caddr_t) &data);
785 }
786
787 bool process::writeTextSpace_(void *inTraced, int amount, const void *inSelf) {
788     return writeDataSpace_(inTraced, amount, inSelf);
789 }
790
791 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
792 bool process::readTextSpace_(void *inTraced, int amount, const void *inSelf) {
793   return readDataSpace_(inTraced, amount, (void *)inSelf);
794 }
795 #endif
796
797 bool process::writeDataSpace_(void *inTraced, int amount, const void *inSelf) {
798     DWORD nbytes;
799
800     //printf("write %d bytes, %x\n", amount, inTraced);
801
802     bool res = WriteProcessMemory((HANDLE)proc_fd, (LPVOID)inTraced, 
803                                   (LPVOID)inSelf, (DWORD)amount, &nbytes);
804     if (!res) {
805         char buf[1000];
806         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 
807                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
808                       buf, 1000, NULL);
809         printf(">>> %d %s\n", GetLastError(), buf);
810         printf("WriteProcessMem: %d bytes, addr = %x, %d\n", 
811                amount, inTraced, res);
812     }
813     return res && (nbytes == amount);
814 }
815
816
817 bool process::readDataSpace_(const void *inTraced, int amount, void *inSelf) {
818     DWORD nbytes;
819     bool res = ReadProcessMemory((HANDLE)proc_fd, (LPVOID)inTraced, 
820                                  (LPVOID)inSelf, (DWORD)amount, &nbytes);
821     if (!res) {
822         char buf[1000];
823         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), 
824                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
825                       buf, 1000, NULL);
826         printf(">>> %d %s\n", GetLastError(), buf);
827         printf("ReadProcessMem: %d bytes, addr = %x, %d\n", 
828                amount, inTraced, res);
829     }
830     return res && (nbytes == amount);
831 }
832
833
834 bool process::loopUntilStopped() { assert(0); return false; }
835
836 float OS::compute_rusage_cpu() { return 0.0; }
837 float OS::compute_rusage_sys() { return 0.0; }
838 float OS::compute_rusage_min() { return 0.0; }
839 float OS::compute_rusage_maj() { return 0.0; }
840 float OS::compute_rusage_swap() { return 0.0; }
841 float OS::compute_rusage_io_in() { return 0.0; }
842 float OS::compute_rusage_io_out() { return 0.0; }
843 float OS::compute_rusage_msg_send() { return 0.0; }
844 float OS::compute_rusage_msg_recv() { return 0.0; }
845 float OS::compute_rusage_sigs() { return 0.0; }
846 float OS::compute_rusage_vol_cs() { return 0.0; }
847 float OS::compute_rusage_inv_cs() { return 0.0; }
848
849
850 int getNumberOfCPUs() {
851     SYSTEM_INFO info;
852     GetSystemInfo(&info);
853     return info.dwNumberOfProcessors;
854 }  
855
856
857 bool process::getActiveFrame(int *fp, int *pc) {
858     CONTEXT cont;
859
860     // we must set ContextFlags to indicate the registers we want returned,
861     // in this case, the control registers.
862     // The values for ContextFlags are defined in winnt.h
863     cont.ContextFlags = CONTEXT_CONTROL;
864     if (GetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
865         *fp = cont.Ebp;
866         *pc = cont.Eip;
867         return true;
868     }
869     printSysError(GetLastError());
870     return false;
871 }
872
873
874 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool ) {
875     bool readOK=true;
876     struct {
877         int fp;
878         int rtn;
879     } addrs;
880
881     //
882     // for the x86, the frame-pointer (EBP) points to the previous frame-pointer,
883     // and the saved return address is in EBP-4.
884     //
885
886     if (readDataSpace((caddr_t) (currentFP),
887                       sizeof(int)*2, (caddr_t) &addrs, true)) {
888         // this is the previous frame pointer
889         *fp = addrs.fp;
890         // return address
891         *rtn = addrs.rtn;
892
893         // if pc==0, then we are in the outermost frame and we should stop. We
894         // do this by making fp=0.
895         
896         if ( (addrs.rtn == 0) || !isValidAddress(this,(Address) addrs.rtn) ) {
897             readOK=false;
898         }
899     }
900     else {
901         readOK=false;
902     }
903
904     return(readOK);
905 }
906
907
908 void *process::getRegisters() {
909     CONTEXT *cont = new CONTEXT;
910     if (!cont)
911         return NULL;
912     // we must set ContextFlags to indicate the registers we want returned,
913     // in this case, the control registers.
914     // The values for ContextFlags are defined in winnt.h
915     cont->ContextFlags = CONTEXT_FULL;
916     if (!GetThreadContext((HANDLE)threads[0]->get_handle(), cont)) {
917         delete cont;
918         return NULL;
919     }
920     return (void *)cont;
921 }
922
923 bool process::changePC(unsigned addr, const void *savedRegs) {
924     assert(status_ == stopped);
925
926     CONTEXT cont = *(CONTEXT *)savedRegs;
927     cont.Eip = addr;
928     if (!SetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
929         printf("SethreadContext failed\n");
930         return false;
931     }
932     return true;
933 }
934
935 bool process::changePC(unsigned addr) {
936     assert(status_ == stopped || status_ == neonatal); 
937     CONTEXT cont;
938     cont.ContextFlags = CONTEXT_FULL;
939     if (!GetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
940         printf("GetThreadContext failed\n");
941         return false;
942     }
943     cont.Eip = addr;
944     if (!SetThreadContext((HANDLE)threads[0]->get_handle(), &cont)) {
945         printf("SethreadContext failed\n");
946         return false;
947     }
948     return true;
949 }
950
951 bool process::restoreRegisters(void *buffer) {
952     if (!SetThreadContext((HANDLE)threads[0]->get_handle(), (CONTEXT *)buffer)) {
953         //printf("SetThreadContext failed\n");
954         return false;
955     }
956     return true;
957 }
958
959 bool process::isRunning_() const {
960     // TODO
961     printf("process::isRunning_() returning true\n");
962     return true;
963 }
964
965
966 string process::tryToFindExecutable(const string& iprogpath, int pid) {
967   return iprogpath;
968 }
969
970 bool process::set_breakpoint_for_syscall_completion() {
971    /* Can assume: (1) process is paused and (2) in a system call.
972       We want to set a TRAP for the syscall exit, and do the
973       inferiorRPC at that time.  We'll use /proc PIOCSEXIT.
974       Returns true iff breakpoint was successfully set. */
975
976     // This is never called on Windows NT
977     assert(false);
978     return false;
979 }
980
981 unsigned process::read_inferiorRPC_result_register(reg) {
982     CONTEXT *cont = new CONTEXT;
983     if (!cont)
984         return NULL;
985     // we must set ContextFlags to indicate the registers we want returned,
986     // in this case, the control registers.
987     // The values for ContextFlags are defined in winnt.h
988     cont->ContextFlags = CONTEXT_FULL;
989     if (!GetThreadContext((HANDLE)threads[0]->get_handle(), cont)) {
990         //printf("GetThreadContext failed\n");
991         delete cont;
992         return NULL;
993     }
994     return cont->Eax;
995 }
996
997 bool process::executingSystemCall() {
998    // TODO
999    return false;
1000 }
1001
1002 // TODO
1003 bool process::needToAddALeafFrame(Frame , Address &) {
1004   return false;
1005 }
1006
1007
1008 void initSymbols(HANDLE procH, const string file, const string dir) {
1009   string searchPath;
1010   char sysRootDir[MAX_PATH+1];
1011   if (GetSystemDirectory(sysRootDir, MAX_PATH) == 0)
1012      assert(0);
1013   string sysSymsDir = string(sysRootDir) + "\\..\\symbols";
1014   if (dir.length())
1015     searchPath = dir + ";";
1016   searchPath = searchPath + sysSymsDir + ";" + sysSymsDir + "\\dll";
1017   if (!SymInitialize(procH, (char *)searchPath.string_of(), 0)) {
1018     fprintf(stderr,"SymInitialize failed, %x\n", GetLastError()); fflush(stderr);
1019     return;
1020   }
1021   if (!SymLoadModule(procH, NULL, (char *)file.string_of(), NULL, 0, 0)) {
1022     printf("SymLoadModule failed for \"%s\", %x\n",
1023             file.string_of(), GetLastError());
1024     return;
1025   }
1026 }
1027
1028
1029
1030
1031
1032 /*****************************************************************************
1033  * forkNewProcess: starts a new process, setting up trace and io links between
1034  *                the new process and the daemon
1035  * Returns true if succesfull.
1036  * 
1037  * Arguments:
1038  *   file: file to execute
1039  *   dir: working directory for the new process
1040  *   argv: arguments to new process
1041  *   envp: environment **** not in use
1042  *   inputFile: where to redirect standard input
1043  *   outputFile: where to redirect standard output
1044  *   traceLink: handle or file descriptor of trace link (read only)
1045  *   ioLink: handle or file descriptor of io link (read only)
1046  *   pid: process id of new process
1047  *   tid: thread id for main thread (needed by WindowsNT)
1048  *   procHandle: handle for new process (needed by WindowsNT)
1049  *   thrHandle: handle for main thread (needed by WindowsNT)
1050  ****************************************************************************/
1051 bool forkNewProcess(string file, string dir, vector<string> argv, 
1052                     vector<string>envp, string inputFile, string outputFile,
1053                     int &traceLink, int &ioLink, 
1054                     int &pid, int &tid, 
1055                     int &procHandle, int &thrHandle) {
1056 #ifndef BPATCH_LIBRARY
1057     HANDLE rTracePipe;
1058     HANDLE wTracePipe;
1059     HANDLE rIoPipe;
1060     HANDLE wIoPipe;
1061 #ifdef notdef
1062     // security attributes to make handles inherited
1063     SECURITY_ATTRIBUTES sa;
1064     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
1065     sa.bInheritHandle = true;
1066     sa.lpSecurityDescriptor = NULL;
1067     
1068     // create trace pipe
1069     if (!CreatePipe(&rTracePipe, &wTracePipe, &sa, 0)) {
1070         string msg = string("Unable to create trace pipe for program '") + File +
1071             string("': ") + string(sys_errlist[errno]);
1072         showErrorCallback(68, msg);
1073         return(NULL);
1074     }
1075     
1076     // create IO pipe
1077     // ioPipe is used to redirect the child's stdout & stderr to a pipe which is in
1078     // turn read by the parent via the process->ioLink socket.
1079     if (!CreatePipe(&rIoPipe, &wIoPipe, &sa, 0)) {
1080         string msg = string("Unable to create IO pipe for program '") + File +
1081             string("': ") + string(sys_errlist[errno]);
1082         showErrorCallback(68, msg);
1083         return(NULL);
1084     }
1085     printf("tracepipe = %d\n", (unsigned)wTracePipe);
1086     // enter trace and IO pipes in child's environment
1087     SetEnvironmentVariable("PARADYN_TRACE_PIPE", 
1088                            string((unsigned)wTracePipe).string_of());
1089     SetEnvironmentVariable("PARADYN_IO_PIPE",
1090                            string((unsigned)wIoPipe).string_of());
1091 #endif
1092     //  extern int traceSocket;
1093     //  SetEnvironmentVariable("PARADYND_TRACE_SOCKET", string((unsigned)traceSocket).string_of());
1094 #endif /* BPATCH_LIBRARY */
1095     
1096     // create the child process
1097     
1098     string args;
1099     for (unsigned ai=0; ai<argv.size(); ai++) {
1100         args += argv[ai];
1101         args += " ";
1102     }
1103     
1104     STARTUPINFO stinfo;
1105     memset(&stinfo, 0, sizeof(STARTUPINFO));
1106     stinfo.cb = sizeof(STARTUPINFO);
1107     
1108     PROCESS_INFORMATION procInfo;
1109     if (CreateProcess(file.string_of(), (char *)args.string_of(), 
1110                       NULL, NULL, false,
1111                       DEBUG_PROCESS /* | CREATE_SUSPENDED */,
1112                       NULL, dir == "" ? NULL : dir.string_of(), 
1113                       &stinfo, &procInfo)) {
1114         procHandle = (Word)procInfo.hProcess;
1115         thrHandle = (Word)procInfo.hThread;
1116         pid = (Word)procInfo.dwProcessId;
1117         tid = (Word)procInfo.dwThreadId;
1118         /*
1119           traceLink = (Word)rTracePipe;
1120           ioLink = (Word)rIoPipe;
1121           */
1122         traceLink = -1;
1123         ioLink = -1;
1124         //    CloseHandle(wTracePipe);
1125         //    CloseHandle(wIoPipe);
1126         //initSymbols((HANDLE)procHandle, file, dir);
1127         return true;
1128     }
1129    
1130 #ifndef BPATCH_LIBRARY
1131     CloseHandle(rTracePipe);
1132     CloseHandle(wTracePipe);
1133     CloseHandle(rIoPipe);
1134     CloseHandle(wIoPipe);
1135 #endif /* BPATCH_LIBRARY */
1136
1137     // Output failure message
1138     LPVOID lpMsgBuf;
1139
1140     if (FormatMessage( 
1141             FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
1142             NULL,
1143             GetLastError(),
1144             MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
1145             (LPTSTR) &lpMsgBuf,
1146             0,
1147             NULL 
1148         ) > 0) {
1149         char *errorLine = (char *)malloc(strlen((char *)lpMsgBuf) +
1150                                          file.length() + 64);
1151         if (errorLine != NULL) {
1152             sprintf(errorLine, "Unable to start %s: %s\n", file.string_of(),
1153                     (char *)lpMsgBuf);
1154             logLine(errorLine);
1155             showErrorCallback(68, (const char *) errorLine);
1156
1157             free(errorLine);
1158         }
1159
1160         // Free the buffer returned by FormatMsg
1161         LocalFree(lpMsgBuf);
1162     } else {
1163         char errorLine[512];
1164         sprintf(errorLine, "Unable to start %s: unknown error\n",
1165                 file.string_of());
1166         logLine(errorLine);
1167         showErrorCallback(68, (const char *) errorLine);
1168     }
1169
1170     return false;
1171 }
1172
1173 char *cplus_demangle(char *c, int) { 
1174     char buf[1000];
1175     if (UnDecorateSymbolName(c, buf, 1000, UNDNAME_NAME_ONLY)) {
1176         //printf("Undecorate: %s = %s\n", c, buf);
1177
1178         // many symbols have a name like foo@4, we must remove the @4
1179         // just searching for an @ is not enough,
1180         // as it may occur on other positions. We search for the last one
1181         // and check that it is followed only by digits.
1182         char *p = strrchr(buf, '@');
1183         if (p) {
1184           char *q = p+1;
1185           strtoul(p+1, &q, 10);
1186           if (q > p+1 && *q == '\0') {
1187             *p = '\0';
1188           }
1189         }
1190         return strdup(buf);
1191     }
1192     return 0;
1193 }
1194
1195 bool OS::osKill(int pid) {
1196     bool res;
1197     HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, false, pid);
1198     if (h == NULL) {
1199         return false;
1200     }
1201     res = TerminateProcess(h,0);
1202     CloseHandle(h);
1203     return res;
1204 }