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