- Modified to use PTRACE_PEEKUSER and PTRACE_POKEUSER, which are more
[dyninst.git] / dyninstAPI / src / linux.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 // $Id: linux.C,v 1.5 1999/02/23 22:13:40 nash Exp $
43
44 #include <fstream.h>
45
46 #include "dyninstAPI/src/process.h"
47
48 //extern "C" {
49 //extern int ioctl(int, int, ...);
50 //extern int getrusage(int, struct rusage*);
51 //#include <a.out.h>
52 //#include <sys/exec.h>
53 //#include <stab.h>
54 //extern struct rusage *mapUarea();
55
56 //#include <machine/reg.h> // for ptrace_getregs call
57 //};
58
59 #include <sys/ptrace.h>
60 #include <asm/ptrace.h>
61 #include <sys/ioctl.h>
62 #include <fcntl.h>
63 #include <dlfcn.h>
64 #include <sys/user.h> // for u-area stuff
65 #include <sys/time.h>
66 #include <sys/resource.h>
67
68 #include "dyninstAPI/src/symtab.h"
69 #include "dyninstAPI/src/instPoint.h"
70 #include "util/h/headers.h"
71 #include "dyninstAPI/src/os.h"
72 #include "dyninstAPI/src/stats.h"
73 #include "util/h/Types.h"
74 #include "dyninstAPI/src/showerror.h"
75 #include "dyninstAPI/src/util.h" // getCurrWallTime
76 #include "util/h/pathName.h"
77 #include "dyninstAPI/src/inst-x86.h"
78
79 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
80
81 // The following were defined in process.C
82 extern debug_ostream attach_cerr;
83 extern debug_ostream inferiorrpc_cerr;
84 extern debug_ostream shmsample_cerr;
85 extern debug_ostream forkexec_cerr;
86 extern debug_ostream metric_cerr;
87 extern debug_ostream signal_cerr;
88
89 extern bool isValidAddress(process *proc, Address where);
90 extern void generateBreakPoint(instruction &insn);
91
92 extern struct rusage *mapUarea();
93
94 const char DYNINST_LOAD_HIJACK_FUNCTIONS[][15] = {
95   "_start",
96   "_init"
97 };
98 const int N_DYNINST_LOAD_HIJACK_FUNCTIONS = 2;
99
100 const char DL_OPEN_FUNC_NAME[] = "_dl_open";
101
102 #ifdef PTRACEDEBUG
103 static bool debug_ptrace = false;
104 #endif
105
106 /* ********************************************************************** */
107
108 /* this table must line up with REGISTER_NAMES */
109 /* symbols like 'EAX' come from <sys/reg.h> */
110 static int regmap[] = 
111 {
112   EAX, ECX, EDX, EBX,
113   UESP, EBP, ESI, EDI,
114   EIP, EFL, CS, SS,
115   DS, ES, FS, GS,
116 };
117
118 #define FP0_REGNUM 16
119 #define FP7_REGNUM (FP0_REGNUM+7)
120 #define NUM_FREGS 8
121 #define NUM_REGS (16 /*+ NUM_FREGS*/)
122
123 #define INTREGSIZE (sizeof(int))
124 #define FPREGSIZE 10
125 #define MAX_REGISTER_RAW_SIZE 10
126
127 #define REGISTER_RAW_SIZE(N) (((N) < FP0_REGNUM) ? INTREGSIZE : FPREGSIZE)
128 #define REGS_SIZE ( NUM_REGS * REGISTER_RAW_SIZE(0) + NUM_FREGS * REGISTER_RAW_SIZE(FP0_REGNUM) )
129 #define REGS_INTS ( REGS_SIZE / INTREGSIZE )
130
131 int register_addr (int regno )
132 {
133   int addr;
134
135   if ( (regno < 0 || regno >= NUM_REGS)
136        && (regno < FP0_REGNUM || regno > FP7_REGNUM) )
137     {
138       fprintf ( stderr, "Invalid register number %d.", regno);
139       assert(0);
140       return -1;
141     }
142
143   if (regno >= FP0_REGNUM && regno <= FP7_REGNUM) 
144     {
145       int fpstate;
146       struct user *u = NULL;
147       fpstate = (int)(&u->i387.st_space);
148       addr = fpstate + 10 * (regno - FP0_REGNUM);
149     }
150   else
151     addr = INTREGSIZE * regmap[regno];
152
153   return addr;
154 }
155
156 class ptraceKludge {
157 private:
158   static bool haltProcess(process *p);
159   static void continueProcess(process *p, const bool halted);
160
161 public:
162   static bool deliverPtrace(process *p, int req, int addr, int data);
163   static int deliverPtraceReturn(process *p, int req, int addr, int data);
164 };
165
166 bool ptraceKludge::haltProcess(process *p) {
167   bool wasStopped = (p->status() == stopped);
168   if (p->status() != neonatal && !wasStopped) {
169     if (!p->loopUntilStopped()) {
170       cerr << "error in loopUntilStopped\n";
171       assert(0);
172     }
173   }  return wasStopped;
174 }
175
176 void ptraceKludge::continueProcess(process *p, const bool wasStopped) {
177   // First handle the cases where we shouldn't issue a PTRACE_CONT:
178   if (p->status() == neonatal) return;
179   if (wasStopped) return;
180
181   // Choose either one of the following methods to continue a process.
182   // The choice must be consistent with that in process::continueProc_ and stop_
183
184 #ifndef PTRACE_ATTACH_DETACH
185   if (P_ptrace(PTRACE_CONT, p->pid, 1, SIGCONT) == -1) {
186 #else
187   if (P_ptrace(PTRACE_DETACH, p->pid, 1, SIGCONT) == -1) {
188 #endif
189       perror("error in continueProcess");
190       assert(0);
191   }
192 }
193
194 bool ptraceKludge::deliverPtrace(process *p, int req, int addr,
195                                  int data ) {
196   bool halted = true;
197
198   if (req != PTRACE_DETACH)
199      halted = haltProcess(p);
200
201   bool ret = (P_ptrace(req, p->getPid(), addr, data) != -1);
202
203   if (req != PTRACE_DETACH)
204      continueProcess(p, halted);
205
206   return ret;
207 }
208
209
210 // Some ptrace requests in Linux return the value rather than storing at the address in data
211 // (especially PEEK requests)
212 // -DAN
213 int ptraceKludge::deliverPtraceReturn(process *p, int req, int addr,
214                                  int data ) {
215   bool halted = true;
216
217   if (req != PTRACE_DETACH)
218      halted = haltProcess(p);
219
220   int ret = P_ptrace(req, p->getPid(), addr, data);
221
222   if (req != PTRACE_DETACH)
223      continueProcess(p, halted);
224
225   return ret;
226 }
227
228 /* ********************************************************************** */
229
230 void *process::getRegisters() {
231    // assumes the process is stopped (ptrace requires it)
232    assert(status_ == stopped);
233
234    // Cycle through all registers, reading each from the
235    // process user space with ptrace(PTRACE_PEEKUSER ...
236    int regaddr, regno;
237    int *buffer = new int[ REGS_INTS ];
238
239    for (regno = 0; regno < NUM_REGS; regno++) {
240      regaddr = register_addr (regno);
241      buffer[ regno ] = P_ptrace (PTRACE_PEEKUSER, pid, regaddr, 0);
242      if( errno ) {
243        perror("process::getRegisters PTRACE_PEEKUSER");
244        return NULL;
245      }
246    }
247
248    int baddr = register_addr ( FP0_REGNUM );
249    int eaddr = register_addr ( FP7_REGNUM ) + REGISTER_RAW_SIZE( FP7_REGNUM );
250    int count;
251    for (regaddr = baddr, count = NUM_REGS; regaddr < eaddr; regaddr += sizeof(int), count++ ) {
252      buffer[ count ] = P_ptrace( PTRACE_PEEKUSER, pid, regaddr, 0);
253      if( errno ) {
254        perror("process::getRegisters PTRACE_PEEKUSER fp");
255        return NULL;
256      }
257    }
258
259    return (void*)buffer;
260 }
261
262 static bool changePC(int pid, Address loc) {
263   Address regaddr = EIP * INTREGSIZE;
264   if (0 != P_ptrace (PTRACE_POKEUSER, pid, regaddr, loc )) {
265     perror( "process::changePC - PTRACE_POKEUSER" );
266     return false;
267   }
268
269   return true;
270 }
271
272  Address getPC(int pid) {
273    Address regaddr = EIP * INTREGSIZE;
274    int res;
275    res = P_ptrace (PTRACE_PEEKUSER, pid, regaddr, 0);
276    if( errno ) {
277      perror( "getPC" );
278      exit(-1);
279      return 0; // Shut up the compiler
280    } else
281      return (Address)res;
282  }
283
284 bool process::executingSystemCall() {
285   // this is not implemented yet - I don't know how in Linux
286   // we assume we're not in a syscall - 7/28/98
287   // Another note: there is a PTRACE_SYSCALL to wait for the
288   // inferior process to return from a system call, but I
289   // don't know how to find out if it's in one to begin with. - DAN
290   return false;
291 }
292
293 bool process::changePC(Address loc, const void * /* savedRegs */ ) {
294   assert(status_ == stopped);
295
296   return ::changePC(pid, loc);
297 }
298
299 bool process::changePC(Address loc) {
300   assert(status_ == stopped);
301
302   return ::changePC(pid, loc);
303 }
304
305
306 bool process::restoreRegisters(void *buffer) {
307    // assumes the process is stopped (ptrace requires it)
308    assert(status_ == stopped);
309
310    // Cycle through all registers, writing each from the
311    // buffer with ptrace(PTRACE_POKEUSER ...
312    int regaddr, regno;
313    int *buf = (int*)buffer;
314
315    for (regno = 0; regno < NUM_REGS; regno++) {
316      regaddr = register_addr (regno);
317      if( P_ptrace (PTRACE_POKEUSER, pid, regaddr, buf[regno] ) ) {
318        perror("process::restoreRegisters PTRACE_POKEUSER");
319        return false;
320      }
321    }
322
323    // Cycle through all 20 words making up the 8 fp registers
324    int baddr = register_addr ( FP0_REGNUM );
325    int eaddr = register_addr ( FP7_REGNUM ) + REGISTER_RAW_SIZE( FP7_REGNUM );
326    int count;
327    for (regaddr=baddr, count=NUM_REGS; regaddr<eaddr; regaddr+= sizeof(int), count++ ) {
328      if( P_ptrace (PTRACE_POKEUSER, pid, regaddr, buf[count] ) ) {
329        perror("process::restoreRegisters PTRACE_POKEUSER fp");
330        return false;
331      }
332    }
333
334    return true;
335 }
336
337 bool process::getActiveFrame(Address *fp, Address *pc)
338 {
339   *fp = ptraceKludge::deliverPtraceReturn(this, PTRACE_PEEKUSER, 0 + EBP * INTREGSIZE, 0);
340   if( errno )
341     return false;
342
343   *pc = ptraceKludge::deliverPtraceReturn(this, PTRACE_PEEKUSER, 0 + EIP * INTREGSIZE, 0);
344   if( errno )
345     return false;
346
347   return true;
348 }
349
350 // TODO: implement this
351 bool process::needToAddALeafFrame(Frame,Address &){
352     return false;
353 }
354
355 // already setup on this FD.
356 // disconnect from controlling terminal 
357 void OS::osDisconnect(void) {
358   int ttyfd = open ("/dev/tty", O_RDONLY);
359   ioctl (ttyfd, TIOCNOTTY, NULL);
360   P_close (ttyfd);
361 }
362
363 bool process::stop_() {
364    // formerly OS::osStop()
365
366 /* Choose either one of the following methods for stopping a process, but not both. 
367  * The choice must be consistent with that in process::continueProc_ 
368  * and ptraceKludge::continueProcess
369  */
370
371 #ifndef PTRACE_ATTACH_DETACH
372         return (P_kill(getPid(), SIGSTOP) != -1); 
373 #else
374         return attach_();
375 #endif
376 }
377
378 bool process::continueWithForwardSignal(int sig) {
379    // formerly OS::osForwardSignal
380    return (P_ptrace(PTRACE_CONT, pid, 1, sig) != -1);
381 }
382
383 void OS::osTraceMe(void) { P_ptrace(PTRACE_TRACEME, 0, 0, 0); }
384
385 process *findProcess(int);  // In process.C
386
387 // wait for a process to terminate or stop
388 // We only want to catch SIGSTOP and SIGILL
389 #ifdef BPATCH_LIBRARY
390 int process::waitProcs(int *status, bool block) {
391   int options = 0;
392   if( !block )
393     options |= WNOHANG;
394 #else
395 int process::waitProcs(int *status) {
396   int options = WNOHANG;
397 #endif
398   int result, sig;
399   bool ignore;
400   do {
401     ignore = false;
402     result = waitpid( -1, status, options );
403
404     // If the process stopped on a signal, and it's not SIGSTOP or SIGILL,
405     // send the signal back and wait for another.
406     if( result > 0 && !WIFSIGNALED(*status) && !WIFEXITED(*status) && WIFSTOPPED(*status) ) {
407                 sig = WSTOPSIG(*status);
408                 if( sig != SIGSTOP && sig != SIGILL /* && sig != SIGTRAP */ ) {
409                         ignore = true;
410 //#ifdef notdef
411                         signal_cerr << "Signal " << sig << " in " << result << ", resignalling the process" << endl;
412 //#endif
413                         if( P_ptrace(PTRACE_CONT, result, 1, sig) == -1 ) {
414                                 if( errno == ESRCH )
415                                         ignore = false;
416                                 else
417                                         cerr << "ERROR -- process::waitProcs forwarding signal " << sig << " -- " << sys_errlist[errno] << endl;
418                         }
419 //#ifdef notdef
420                         else
421                                 signal_cerr << "Signal " << sig << " in " << result << endl;
422 //#endif
423                 }
424     }
425         
426   } while ( ignore );
427
428   if( result > 0 ) {
429           if( WIFSTOPPED(*status) ) {
430 #if defined(USES_LIBDYNINSTRT_SO)
431                   process *curr = findProcess( result );
432                   if (!curr->dyninstLibAlreadyLoaded() && curr->wasCreatedViaAttach())
433                   {
434                           // make sure we are stopped in the eyes of paradynd - naim
435                           bool wasRunning = (curr->status() == running);
436                           if (curr->status() != stopped)
437                                   curr->Stopped();   
438                           if(curr->isDynamicallyLinked()) {
439                                   curr->handleIfDueToSharedObjectMapping();
440                           }
441                           if (curr->trapDueToDyninstLib()) {
442                                   // we need to load libdyninstRT.so.1 - naim
443                                   curr->handleIfDueToDyninstLib();
444                           }
445                           if (wasRunning) 
446                                   if (!curr->continueProc()) assert(0);
447                   }
448 #endif
449           }
450   }// else if( errno )
451     //perror( "process::waitProcs - waitpid" );
452   return result;
453 }
454
455 // attach to an inferior process.
456 bool process::attach() {
457   char procName[128];
458
459   bool running;
460   if( createdViaAttach )
461     running = isRunning_();
462
463   proc_fd = -1;
464
465   // QUESTION: does this attach operation lead to a SIGTRAP being forwarded
466   // to paradynd in all cases?  How about when we are attaching to an
467   // already-running process?  (Seems that in the latter case, no SIGTRAP
468   // is automatically generated)
469
470   // step 1) /proc open: attach to the inferior process memory file
471   sprintf(procName,"/proc/%05d/mem", (int)getPid());
472   int fd = P_open(procName, O_RDWR, 0);
473   if (fd < 0 ) {
474     fprintf(stderr, "attach: open failed on %s: %s\n", procName, sys_errlist[errno]);
475     return false;
476   }
477
478   proc_fd = fd;
479
480   // Only if we are really attaching rather than spawning the inferior
481   // process ourselves do we need to call PTRACE_ATTACH
482   if( createdViaAttach ) {
483     if( -1 == P_ptrace(PTRACE_ATTACH, getPid(), 0, 0) )
484       { perror( "process::attach - PTRACE_ATTACH" ); return false; }
485
486     // If the process was running, it will need to be restarted, as
487     // PTRACE_ATTACH kills it
488     // Actually, the attach process contructor assumes that the process is
489     // running.  While this is foolish, let's play along for now.
490     if( true /* running */ ) {
491       if( -1 == kill( getPid(), SIGCONT ) )
492         //if( -1 == P_ptrace(PTRACE_CONT, getPid(), 1, 0) )
493         { perror( "process::attach - SIGCONT" ); return false; }
494     }
495   }
496
497   return true;
498 }
499
500 bool process::attach_() {
501   return false; // (P_ptrace(PTRACE_ATTACH, getPid(), 0, 0) != -1);
502 }
503
504 #if defined(USES_LIBDYNINSTRT_SO)
505 bool process::trapAtEntryPointOfMain()
506 {
507   // is the trap instr at main_brk_addr?
508   if( getPC(getPid()) == (Address)main_brk_addr)
509     return(true);
510   else
511     return(false);
512 }
513
514 bool process::trapDueToDyninstLib()
515 {
516   // is the trap instr at dyninstlib_brk_addr?
517   if( getPC(getPid()) == (Address)dyninstlib_brk_addr)
518     return(true);
519   else
520     return(false);
521 }
522
523 void process::handleIfDueToDyninstLib() 
524 {
525   // rewrite original instructions in the text segment we use for 
526   // the inferiorRPC - naim
527   unsigned count = sizeof(savedCodeBuffer);
528   //Address codeBase = getImage()->codeOffset();
529
530   Address codeBase = 0;
531   int i;
532
533   for( i = 0; i < N_DYNINST_LOAD_HIJACK_FUNCTIONS; i++ ) {
534     function_base *tmpFunc = symbols->findOneFunctionFromAll(DYNINST_LOAD_HIJACK_FUNCTIONS[i]);
535     if( tmpFunc )
536       codeBase = tmpFunc->getAddress(this);
537     if( codeBase )
538       break;
539   }
540   assert( codeBase );
541
542   writeDataSpace((void *)codeBase, count, (char *)savedCodeBuffer);
543
544   // restore registers
545   restoreRegisters(savedRegs); 
546
547   // restore the stack frame of _start()
548   int *theIntRegs = (int *)savedRegs;
549   Address theEBP = theIntRegs[EBP];
550   assert (theEBP);
551   // this is pretty kludge. if the stack frame of _start is not the right
552   // size, this would break.
553   writeDataSpace ((void*)(theEBP-6*sizeof(int)),6*sizeof(int),savedStackFrame);
554
555   delete[] savedRegs;
556   savedRegs = NULL;
557 }
558
559 void process::handleTrapAtEntryPointOfMain()
560 {
561   function_base *f_main = findOneFunction("main");
562   assert(f_main);
563   Address addr = f_main->addr();
564   // restore original instruction 
565   writeDataSpace((void *)addr, 2, (char *)savedCodeBuffer);
566 }
567
568 void process::insertTrapAtEntryPointOfMain()
569 {
570   function_base *f_main = findOneFunction("main");
571   if (!f_main) {
572     // we can't instrument main - naim
573     showErrorCallback(108,"");
574     extern void cleanUpAndExit(int);
575     cleanUpAndExit(-1); 
576     return;
577   }
578   assert(f_main);
579   Address addr = f_main->addr();
580
581   // save original instruction first
582   readDataSpace((void *)addr, 2, savedCodeBuffer, true);
583
584   // and now, insert trap
585   instruction insnTrap;
586   generateBreakPoint(insnTrap);
587
588   // x86. have to use SIGILL instead of SIGTRAP
589   writeDataSpace((void *)addr, 2, insnTrap.ptr());  
590
591   main_brk_addr = addr;
592 }
593
594 bool process::dlopenDYNINSTlib() {
595 /*#ifdef PTRACEDEBUG
596   debug_ptrace = true;
597   #endif*/
598   // we will write the following into a buffer and copy it into the
599   // application process's address space
600   // [....LIBRARY's NAME...|code for DLOPEN]
601
602   // write to the application at codeOffset. This won't work if we
603   // attach to a running process.
604   //Address codeBase = this->getImage()->codeOffset();
605   // ...let's try "_start" instead
606   //  Address codeBase = (this->findOneFunctionFromAll(DYNINST_LOAD_HIJACK_FUNCTION))->getAddress(this);
607   Address codeBase = (Address)NULL;
608   int i;
609
610   for( i = 0; i < N_DYNINST_LOAD_HIJACK_FUNCTIONS; i++ ) {
611     function_base *tmpFunc = symbols->findOneFunctionFromAll(DYNINST_LOAD_HIJACK_FUNCTIONS[i]);
612     if( tmpFunc )
613       codeBase = tmpFunc->getAddress(this);
614         if( codeBase )
615           break;
616   }
617
618   if( !codeBase || i >= N_DYNINST_LOAD_HIJACK_FUNCTIONS )
619     return false;
620
621   attach_cerr << "Inserting dlopen call in " << DYNINST_LOAD_HIJACK_FUNCTIONS[i] << " at "
622                           << (void*)codeBase << endl;
623
624   // Or should this be readText... it seems like they are identical
625   // the remaining stuff is thanks to Marcelo's ideas - this is what 
626   // he does in NT. The major change here is that we use AST's to 
627   // generate code for dlopen.
628
629   // savedCodeBuffer[BYTES_TO_SAVE] is declared in process.h
630
631   readDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer, true);
632
633   unsigned char scratchCodeBuffer[BYTES_TO_SAVE];
634   vector<AstNode*> dlopenAstArgs(2);
635
636   unsigned count = 0;
637
638   AstNode *dlopenAst;
639
640   // deadList and deadListSize are defined in inst-sparc.C - naim
641   extern Register deadList[];
642   extern int deadListSize;
643   registerSpace *dlopenRegSpace = new registerSpace(deadListSize/sizeof(int), deadList, 0, NULL);
644   dlopenRegSpace->resetSpace();
645
646   // we need to make 1 call to dlopen, to load libdyninst.so.1 - nash
647
648   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void*)0);
649   // library name. We use a scratch value first. We will update this parameter
650   // later, once we determine the offset to find the string - naim
651   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE); // mode
652   dlopenAst = new AstNode(DL_OPEN_FUNC_NAME,dlopenAstArgs);
653   removeAst(dlopenAstArgs[0]);
654   removeAst(dlopenAstArgs[1]);
655
656   Address dyninst_count = 0;
657   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
658                           dyninst_count, true, true);
659   writeDataSpace((void *)(codeBase+count), dyninst_count, (char *)scratchCodeBuffer);
660   count += dyninst_count;
661
662   instruction insnTrap;
663   generateBreakPoint(insnTrap);
664   writeDataSpace((void *)(codeBase + count), 2, insnTrap.ptr());
665   dyninstlib_brk_addr = codeBase + count;
666   count += 2;
667
668   char libname[256];
669 #ifdef BPATCH_LIBRARY  /* dyninst API loads a different run-time library */
670   if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
671     strcpy((char*)libname,(char*)getenv("DYNINSTAPI_RT_LIB"));
672   } else {
673     string msg = string("Environment variable DYNINSTAPI_RT_LIB is not defined, should be set to the pathname of DynintAPI runtime library");
674     showErrorCallback(101, msg);
675     return false;
676   }
677 #else
678   if (getenv("PARADYN_LIB") != NULL) {
679     strcpy((char*)libname,(char*)getenv("PARADYN_LIB"));
680   } else {
681     string msg = string("PARADYN_LIB has not been defined for ") +
682                  string("process") + string(pid);
683     showErrorCallback(101, msg);
684     return false;
685   }
686 #endif
687
688   Address dyninstlib_addr = (Address) (codeBase + count);
689
690   writeDataSpace((void *)(codeBase + count), strlen(libname)+1,
691                  (caddr_t)libname);
692   count += strlen(libname)+1;
693   // we have now written the name of the library after the trap - naim
694
695   assert(count<=BYTES_TO_SAVE);
696
697   count = 0; // reset count
698
699   // at this time, we know the offset for the library name, so we fix the
700   // call to dlopen and we just write the code again! This is probably not
701   // very elegant, but it is easy and it works - naim
702   removeAst(dlopenAst); // to avoid leaking memory
703   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void *)(dyninstlib_addr));
704   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE);
705   dlopenAst = new AstNode(DL_OPEN_FUNC_NAME,dlopenAstArgs);
706   removeAst(dlopenAstArgs[0]);
707   removeAst(dlopenAstArgs[1]);
708   dyninst_count = 0; // reset count
709   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
710                           dyninst_count, true, true);
711   writeDataSpace((void *)(codeBase+count), dyninst_count, (char *)scratchCodeBuffer);
712   removeAst(dlopenAst);
713
714   // save registers
715   savedRegs = getRegisters();
716   assert((savedRegs!=NULL) && (savedRegs!=(void *)-1));
717   // save the stack frame of _start()
718   int *regs = (int*)savedRegs;
719   Address theEBP = regs[EBP];
720   if( theEBP ) {
721   //assert (theEBP);
722   // this is pretty kludge. if the stack frame of _start is not the right
723   // size, this would break.
724   readDataSpace((void*)(theEBP-6*sizeof(int)),6*sizeof(int), savedStackFrame, true);
725   }
726   isLoadingDyninstLib = true;
727
728   if (!changePC(codeBase,savedRegs))
729   {
730     logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
731     assert(0);
732   }
733
734 /*#ifdef PTRACEDEBUG
735   debug_ptrace = false;
736   #endif*/
737
738   return true;
739 }
740
741 Address process::get_dlopen_addr() const {
742   if (dyn != NULL)
743     return(dyn->get_dlopen_addr());
744   else 
745     return(0);
746 }
747 #endif
748
749 bool process::isRunning_() const {
750    // determine if a process is running by doing low-level system checks, as
751    // opposed to checking the 'status_' member vrble.  May assume that attach()
752    // has run, but can't assume anything else.
753
754   char procName[64];
755   char sstat[132];
756   char *token;
757
758   sprintf(procName,"/proc/%d/stat", (int)pid);
759   FILE *sfile = P_fopen(procName, "r");
760   fread( sstat, 128, 1, sfile );
761   fclose( sfile );
762
763   char status;
764   if( !( strtok( sstat, " (" ) && strtok( NULL, " )" ) && ( token = strtok( NULL, " " ) ) ) )
765     assert( false && "Shouldn't happen" );
766   status = token[0];
767
768   if( status == 'T' )
769     return false;
770   else
771     return true;
772 }
773
774
775 // TODO is this safe here ?
776 bool process::continueProc_() {
777   int ret;
778
779   if (!checkStatus()) 
780     return false;
781
782   ptraceOps++; ptraceOtherOps++;
783
784 /* choose either one of the following ptrace calls, but not both. 
785  * The choice must be consistent with that in stop_ and
786  * ptraceKludge::continueProcess.
787  */
788 #ifndef PTRACE_ATTACH_DETACH
789   //#ifdef PTRACEDEBUG
790   //fprintf(stderr,"child (%d), stop paradynd (%d)\n", getPid(), getpid() );
791   //  P_ptrace(PTRACE_DETACH, pid, (char*)1, 0 );
792   //kill( getpid(), SIGSTOP );
793   //#endif
794   if (!ptraceKludge::deliverPtrace(this, PTRACE_CONT, 1, 0))
795     ret = -1;
796   else
797     ret = 0;
798   //ret = P_ptrace(PTRACE_CONT, pid, (char*)1, 0);
799 #else
800   ret = P_ptrace(PTRACE_DETACH, pid, (char*)1, SIGCONT);
801 #endif
802
803   if (ret == -1)
804      perror("continueProc_()");
805
806   return ret != -1;
807 }
808
809 #ifdef BPATCH_LIBRARY
810 bool process::terminateProc_()
811 {
812   if (!checkStatus()) 
813     return false;
814
815   if (P_ptrace(PTRACE_KILL, pid, 0, 0) != 0)
816     return false;
817   else
818     return true;
819 }
820 #endif
821
822 // TODO ??
823 bool process::pause_() {
824   if (!checkStatus()) 
825     return false;
826   ptraceOps++; ptraceOtherOps++;
827   bool wasStopped = (status() == stopped);
828   if (status() != neonatal && !wasStopped)
829     return (loopUntilStopped());
830   else
831     return true;
832 }
833
834 bool process::detach_() {
835   if (!checkStatus())
836     return false;
837   ptraceOps++; ptraceOtherOps++;
838   close( proc_fd );
839   return (ptraceKludge::deliverPtrace(this, PTRACE_DETACH, 1, SIGCONT));
840 }
841
842 #ifdef BPATCH_LIBRARY
843 bool process::API_detach_(const bool cont) {
844 //  assert(cont);
845   if (!checkStatus())
846     return false;
847   ptraceOps++; ptraceOtherOps++;
848   close( proc_fd );
849   if (!cont) P_kill(pid, SIGSTOP);
850   return (ptraceKludge::deliverPtrace(this, PTRACE_DETACH, 1, SIGCONT));
851 }
852 #endif
853
854 bool process::dumpCore_(const string/* coreFile*/) { return false; }
855
856 bool process::writeTextWord_(caddr_t inTraced, int data) {
857 //  cerr << "writeTextWord @ " << (void *)inTraced << endl; cerr.flush();
858   return writeDataSpace_(inTraced, sizeof(int), (caddr_t) &data);
859 }
860
861 bool process::writeTextSpace_(void *inTraced, u_int amount, const void *inSelf) {
862 //  cerr << "writeTextSpace pid=" << getPid() << ", @ " << (void *)inTraced << " len=" << amount << endl; cerr.flush();
863   return writeDataSpace_(inTraced, amount, inSelf);
864 }
865
866 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
867 bool process::readTextSpace_(void *inTraced, u_int amount, const void *inSelf) {
868   return readDataSpace_( inTraced, amount, inSelf );
869 }
870 #endif
871
872 bool process::writeDataSpace_(void *inTraced, u_int amount, const void *inSelf) {
873   ptraceOps++; ptraceBytes += amount;
874
875 #if defined(PTRACEDEBUG_EXCESSIVE)
876   int check;
877 #if !defined(PTRACEDEBUG_ALWAYS)
878   if( debug_ptrace )
879 #endif
880     fprintf( stderr, "(linux)writeDataSpace_  amount=%d  %#.8x -> %#.8x data=0x", amount, (int)inSelf, (int)inTraced );
881 #elif defined(PTRACEDEBUG)
882 #if !defined(PTRACEDEBUG_ALWAYS)
883   if( debug_ptrace )
884 #endif
885     fprintf( stderr, "(linux)writeDataSpace_  amount=%d  %#.8x -> %#.8x\n", amount, (int)inSelf, (int)inTraced );
886 #endif
887   unsigned char buf[sizeof(int)];
888   int count, off, addr = (int)inTraced, dat = (int)inSelf, tmp;
889
890   off = addr % sizeof(int);
891   if( off != 0 || amount < sizeof(int) ) {
892     addr -= off;
893     // This is what I did originally
894     /*if( -1 == P_ptrace( PTRACE_PEEKTEXT, getPid(), addr, (int)buf ) ) {
895       char errb[150];
896       sprintf( errb, "process::writeDataSpace_, ptrace( PEEKTXT, %d, %#.8x, &tmp )", getPid(), addr );
897       perror( errb );
898       return false;
899       }*/
900     // Unfortunately, PEEKTEXT doesn't work as advertised, it seems to return
901     // the read value rather than putting it in *data.  I'll use /proc instead
902     assert( proc_fd != -1 );
903     if( ((lseek(proc_fd, (off_t)addr, SEEK_SET)) != (off_t)addr) ||
904         read(proc_fd, (char*)buf, sizeof(int)) != sizeof(int) ) {
905       printf("writeDataSpace_: error in read word addr = 0x%x\n",addr);
906       return false;
907     }
908 #ifdef PTRACEDEBUG_EXCESSIVE
909 #if !defined(PTRACEDEBUG_ALWAYS)
910     if( debug_ptrace )
911 #endif
912       fprintf( stderr, "%.8x:0x", *((int*)buf) );
913 #endif
914   }
915
916   for( count = 0; count < amount; count++ ) {
917     //int le_off;
918     //le_off = sizeof(int) - off - 1;
919     /*    switch (off) {
920     case 0: le_off = 0; break;
921     case 1: le_off = 1; break;
922     case 2: le_off = 3; break;
923     case 3: le_off = 2; break;
924     default: assert( false );
925     } */
926     buf[off] = *((unsigned char*)(dat+count));
927 #ifdef PTRACEDEBUG_EXCESSIVE
928 #if !defined(PTRACEDEBUG_ALWAYS)
929     if( debug_ptrace )
930 #endif
931       fprintf( stderr, "%.2x", 0x0000 | *((unsigned char*)(dat+count)) );
932 #endif
933     off++; off %= sizeof(int);
934     if( !off || (count == amount-1) ) {
935       if( -1 == P_ptrace( PTRACE_POKETEXT, getPid(), addr, *((int*)buf) ) ) {
936         perror( "process::writeDataSpace, ptrace PTRACE_POKETXT" );
937         return false;
938       }
939       off = amount - count - 1;
940 #ifdef PTRACEDEBUG_EXCESSIVE
941 #if !defined(PTRACEDEBUG_ALWAYS)
942       if( debug_ptrace ) {
943 #endif
944         check = P_ptrace( PTRACE_PEEKTEXT, getPid(), addr, 0 );
945         fprintf( stderr, ":%#.8x", check );
946         if( off > 0 )
947           fprintf( stderr, " | 0x" );
948 #if !defined(PTRACEDEBUG_ALWAYS)
949       }
950 #endif
951 #endif
952       addr += sizeof(int);
953       if( off < sizeof(int) && off > 0 ) {
954         /*if( -1 == P_ptrace( PTRACE_PEEKTEXT, getPid(), addr, (int)buf ) ) {
955           perror( "process::writeDataSpace, ptrace PTRACE_PEEKTXT" );
956           return false;
957           }*/
958         assert( proc_fd != -1 );
959         if( ((lseek(proc_fd, (off_t)addr, SEEK_SET)) != (off_t)addr) ||
960             read(proc_fd, (char*)buf, sizeof(int)) != sizeof(int) ) {
961           printf("writeDataSpace_: error in read word addr = 0x%x\n",addr);
962           return false;
963         }
964
965 #ifdef PTRACEDEBUG_EXCESSIVE
966 #if !defined(PTRACEDEBUG_ALWAYS)
967         if( debug_ptrace ) {
968 #endif
969           check = P_ptrace( PTRACE_PEEKTEXT, getPid(), addr, 0 );
970           fprintf( stderr, "%.8x:0x", check );
971 #if !defined(PTRACEDEBUG_ALWAYS)
972         }
973 #endif
974 #endif
975       }
976       off = 0;
977     }
978   }
979
980 #ifdef PTRACEDEBUG_EXCESSIVE
981   fprintf( stderr, "\n" );
982 #endif
983
984   return true;
985 }
986
987 bool process::readDataSpace_(const void *inTraced, u_int amount, void *inSelf) {
988   ptraceOps++; ptraceBytes += amount;
989
990 #ifdef PTRACEDEBUG
991 #if !defined(PTRACEDEBUG_ALWAYS)
992   if( debug_ptrace )
993 #endif
994     fprintf( stderr, "(linux)readDataSpace_  amount=%d  %#.8x <- %#.8x\n", amount, (int)inSelf, (int)inTraced );
995 #endif
996
997   if( proc_fd != -1 ) {
998     while (true) {
999       if((lseek(proc_fd, (off_t)inTraced, SEEK_SET)) != (off_t)inTraced) {
1000         fprintf( stderr, "(linux)readDataSpace_: error in lseek addr = 0x%x amount = %d\n",(u_int)inTraced,amount);
1001         return false;
1002       }
1003       int result = read(proc_fd, inSelf, amount);
1004       if( result < 0 ) {
1005         fprintf( stderr, "(linux)readDataSpace_  amount=%d  %#.8x <- %#.8x\n", amount, (int)inSelf, (int)inTraced );
1006         perror( "process::readDataSpace_ - read" );
1007         return false;
1008       } else if( result == 0 ) {
1009         if( errno )
1010           perror( "process::readDataSpace_" );
1011         fprintf( stderr, "process::readDataSpace_ -- Failed to read( /proc/*/mem ), trying ptrace\n" );
1012         break;
1013       }
1014       assert( result <= amount );
1015       if( result == amount )
1016         return true;
1017       // We weren't able to read atomically, so reseek and reread.
1018 #ifdef PDYN_DEBUG
1019           fprintf( stderr, "process::readDataSpace_ -- Failed atomic read, reseeking and rereading\n" );
1020 #endif
1021     }
1022   }
1023
1024   // For some reason we couldn't or didn't open /proc/*/mem, so use ptrace
1025   // Should I remove this part? - DAN
1026
1027   // Well, since you sometimes don't seem to be able to read from the fd
1028   // maybe we do need to keep this - DAN
1029
1030   if( amount % sizeof(int) != 0 ||
1031       (int)inTraced % sizeof(int) != 0 ||
1032       (int)inSelf % sizeof(int) != 0 ) {
1033 #ifdef PTRACEDEBUG
1034     fprintf( stderr, "couldn't do (linux)readDataSpace_  amount=%d  %#.8x <- %#.8x\n", amount, (int)inSelf, (int)inTraced );
1035 #endif
1036     return false;
1037   }
1038
1039   int count, result, *dst = (int*)inSelf;
1040   const int *addr = (const int*)inTraced;
1041
1042   for( count = 0; count < amount; count += sizeof(int), addr++, dst++ ) {
1043     result = P_ptrace( PTRACE_PEEKTEXT, getPid(), (int)addr, 0 );
1044     if( errno ) {
1045       perror( "process::writeDataSpace, ptrace PTRACE_POKETXT" );
1046       return false;
1047     }
1048     *dst = result;
1049   }
1050   
1051   return true;
1052 }
1053
1054 /*
1055 bool process::findCallee(instPoint &instr, function_base *&target){
1056   fprintf( stderr, "findCallee not implemented\n" );
1057   return false;
1058 }
1059 */
1060
1061 bool process::readDataFromFrame(Address currentFP, Address *fp, Address *rtn, bool )
1062 {
1063   bool readOK=true;
1064   struct {
1065     int fp;
1066     int rtn;
1067   } addrs;
1068
1069   //
1070   // for the x86, the frame-pointer (EBP) points to the previous frame-pointer,
1071   // and the saved return address is in EBP-4.
1072   //
1073
1074   if (readDataSpace((caddr_t) (currentFP),
1075                     sizeof(int)*2, (caddr_t) &addrs, true)) {
1076     // this is the previous frame pointer
1077     *fp = addrs.fp;
1078     // return address
1079     *rtn = addrs.rtn;
1080
1081     // if pc==0, then we are in the outermost frame and we should stop. We
1082     // do this by making fp=0.
1083
1084     if ( (addrs.rtn == 0) || !isValidAddress(this,(Address) addrs.rtn) ) {
1085       readOK=false;
1086     }
1087   }
1088   else {
1089     readOK=false;
1090   }
1091
1092   return(readOK);
1093 }
1094
1095 // You know, /proc/*/exe is a perfectly good link (directly to the inode) to
1096 // the executable file, who cares where the executable really is, we can open
1097 // this link. - DAN
1098 string process::tryToFindExecutable(const string & /* iprogpath */, int pid) {
1099   return string("/proc/") + string(pid) + "/exe";
1100 }
1101
1102 /*
1103  * The old, ugly version that we don't need but can waste space anyhow
1104  * /
1105 string process::tryToFindExecutable(const string &iprogpath, int pid) {
1106    // returns empty string on failure.
1107    // Otherwise, returns a full-path-name for the file.  Tries every
1108    // trick to determine the full-path-name, even though "progpath" may be
1109    // unspecified (empty string).
1110    
1111    // Remember, we can always return the empty string...no need to
1112    // go nuts writing the world's most complex algorithm.
1113
1114    attach_cerr << "welcome to tryToFindExecutable; progpath=" << iprogpath << ", pid=" << pid << endl;
1115
1116    const string progpath = expand_tilde_pathname(iprogpath);
1117
1118    // Trivial case: if "progpath" is specified and the file exists then nothing needed
1119    if (exists_executable(progpath)) {
1120      attach_cerr << "tryToFindExecutable succeeded immediately, returning "
1121                  << progpath << endl;
1122      return progpath;
1123    }
1124
1125    attach_cerr << "tryToFindExecutable failed on filename " << progpath << endl;
1126
1127    string argv0, path, cwd;
1128
1129    char buffer[128];
1130    sprintf(buffer, "/proc/%d/environ", pid);
1131    int procfd = open(buffer, O_RDONLY, 0);
1132    if (procfd == -1) {
1133      attach_cerr << "tryToFindExecutable failed since open of /proc/* /environ failed" << endl;
1134      return "";
1135    }
1136    attach_cerr << "tryToFindExecutable: opened /proc/* /environ okay" << endl;
1137
1138    int strptr = 0;
1139    while( true ) {
1140      string env_value = extract_string( procfd, (char*)strptr );
1141      if( !env_value.length() )
1142        break;
1143
1144      if (env_value.prefixed_by("PWD=") || env_value.prefixed_by("CWD=")) {
1145        cwd = env_value.string_of() + 4; // skip past "PWD=" or "CWD="
1146        attach_cerr << "get_ps_stuff: using PWD value of: " << cwd << endl;
1147        if( path.length() )
1148          break;
1149      } else if (env_value.prefixed_by("PATH=")) {
1150        path = env_value.string_of() + 5; // skip past the "PATH="
1151        attach_cerr << "get_ps_stuff: using PATH value of: " << path << endl;
1152        if( cwd.length() )
1153          break;
1154      }
1155
1156      strptr += env_value.length() + 1;
1157    }
1158
1159    close( procfd );
1160
1161    sprintf(buffer, "/proc/%d/cmdline", pid);
1162    procfd = open(buffer, O_RDONLY, 0);
1163    if (procfd == -1) {
1164      attach_cerr << "tryToFindExecutable failed since open of /proc/* /cmdline failed" << endl;
1165      return "";
1166    }
1167    attach_cerr << "tryToFindExecutable: opened /proc/* /cmdline okay" << endl;
1168
1169    argv0 = extract_string( procfd, (char*)0 );
1170    close( procfd );
1171
1172    if ( argv0.length() && path.length() && cwd.length() ) {
1173      // the following routine is implemented in the util lib.
1174      string result;
1175      if (executableFromArgv0AndPathAndCwd(result, argv0, path, cwd)) {
1176        attach_cerr << "tryToFindExecutable: returning " << result << endl;
1177
1178        // I feel picky today, let's make certain that /proc agrees that
1179        // this is the executable by checking the inode number of
1180        // /proc/ * /exe against the inode number of result
1181
1182        sprintf(buffer, "/proc/%d/exe", pid);
1183        struct stat t_stat;
1184        int t_inode;
1185        if( stat( buffer, &t_stat ) ) {
1186          t_inode = t_stat.st_ino;
1187          if( stat( buffer, &t_stat ) && t_inode != t_stat.st_ino )
1188            cerr << "tryToFindExecutable: WARNING - found executable does not match /proc" << endl;
1189        }
1190
1191        return result;
1192      }
1193    }
1194
1195    attach_cerr << "tryToFindExecutable: giving up" << endl;
1196
1197    return "";
1198 }
1199 */
1200
1201 #ifdef SHM_SAMPLING
1202 time64 process::getInferiorProcessCPUtime() /* const */ {
1203   /*
1204   rusage usage;
1205   time64 now;
1206   if( getrusage( RUSAGE_CHILDREN, &usage ) ) {
1207     perror( "process::getInferiorProcessCPUtime" );
1208     return 0;
1209   }
1210   now = usage.ru_utime.tv_sec*1000000 + usage.ru_utime.tv_usec + usage.ru_stime.tv_sec*1000000 + usage.ru_stime.tv_usec;
1211
1212   return now;
1213   */
1214
1215   time64 now = 0;
1216   char buf[80], *buf2;
1217   int bufsize = 80, utime, stime;
1218   static int realHZ = 0;
1219   // Determine the number of jiffies/sec by checking the clock idle time in
1220   // /proc/uptime against the jiffies idle time in /proc/stat
1221   if( realHZ == 0 ) {
1222     double uptimeReal;
1223     int uptimeJiffies;
1224     FILE *tmp = P_fopen( "/proc/uptime", "r" );
1225     assert( tmp );
1226     assert( 1 == fscanf( tmp, "%*f %lf", &uptimeReal ) );
1227     fclose( tmp );
1228     tmp = P_fopen( "/proc/stat", "r" );
1229     assert( tmp );
1230     assert( 1 == fscanf( tmp, "%*s %*d %*d %*d %d", &uptimeJiffies ) );
1231     fclose( tmp );
1232     realHZ = (int)floor( (double)uptimeJiffies / uptimeReal );
1233     printf( "Determined jiffies/sec as %d\n", realHZ );
1234   }
1235
1236   sprintf( buf, "/proc/%d/stat", getPid() );
1237
1238   int fd;
1239
1240   // The reason for this complicated method of reading and sseekf-ing is
1241   // to ensure that we read enough of the buffer 'atomically' to make sure
1242   // the data is consistent.  Is this necessary?  I *think* so. - DAN
1243   do {
1244     fd = P_open(buf, O_RDONLY, 0);
1245     if (fd < 0) {
1246       shmsample_cerr << "getInferiorProcessCPUtime: open failed: " << sys_errlist[errno] << endl;
1247       return false;
1248     }
1249
1250     buf2 = new char[ bufsize ];
1251
1252     size_t rsize = P_read( fd, buf2, bufsize-1 );
1253
1254     if( 2 == sscanf( buf2, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %d %d ", &utime, &stime ) ) {
1255       // These numbers are in 'jiffies' or clock ticks.  For now, we
1256       // check at the beginning the ratio between the idle seconds in
1257       // /proc/uptime and the idle jiffies in /proc/stat, and later we can
1258       // use some kind of gethrvptime for the whole thing. - DAN
1259       // Oh, and I'm also assuming that process time includes system time
1260       now = ( (time64)1000000 * ( (time64)utime + (time64)stime ) ) / (time64)realHZ;
1261       break;
1262     }
1263
1264     delete [] buf2;
1265     shmsample_cerr << "Inferior CPU time buffer expansion (" << bufsize << ")" << endl;
1266     bufsize = bufsize * 2;
1267
1268     P_close( fd );
1269   } while ( true );
1270
1271   delete [] buf2;
1272   P_close(fd);
1273
1274   return now;
1275 }
1276 /*
1277 user *process::tryToMapChildUarea(int childpid) {
1278    // a static member fn
1279    // see DYNINSTprobeUarea of rtinst/src/sunos.c
1280
1281 assert(0);
1282
1283    kvm_t *kvmfd = kvm_open(0, 0, 0, O_RDONLY, 0);
1284    if (kvmfd == NULL) {
1285       perror("could not map child's uarea because kvm_open failed");
1286       return NULL;
1287    }
1288
1289    // kvm_getproc returns a ptr to a _copy_ of the proc structure
1290    // in static memory.
1291    time64 wall1 = getCurrWallTime();
1292    proc *p = kvm_getproc(kvmfd, childpid);
1293    if (p == NULL) {
1294       perror("could not map child's uarea because kvm_getproc failed");
1295       return NULL;
1296    }
1297    time64 wall2 = getCurrWallTime();
1298    time64 difference = wall2-wall1;
1299    unsigned long difference_long = difference;
1300    cout << "took " << difference_long << " usecs to kvm_getproc" << endl;
1301  
1302    // kvm_getu returns a copy to a _copy_ of the process' uarea
1303    // in static memory.
1304    user *u = kvm_getu(kvmfd, p);
1305    if (u == NULL) {
1306       perror("could not map child's uarea because kvm_getu failed");
1307       return NULL;
1308    }
1309
1310    kvm_close(kvmfd);
1311
1312    void *uareaPtr = p->p_uarea;
1313
1314    int kmemfd = open("/dev/kmem", O_RDONLY, 0);
1315    if (kmemfd == -1) {
1316       perror("could not map child's uarea because could not open /dev/kmem for reading");
1317       return NULL;
1318    }
1319
1320    void *result = P_mmap(NULL, sizeof(user), PROT_READ, MAP_SHARED, kmemfd,
1321                          (off_t)uareaPtr);
1322    if (result == (void *)-1) {
1323       perror("could not map child's uarea because could not mmap /dev/kmem");
1324       close(kmemfd);
1325       return NULL;
1326    }
1327
1328    cout << "mmap of child's uarea succeeded!" << endl;
1329
1330    return (user *)result;
1331 } */
1332 #endif
1333
1334 //time64 process::getInferiorProcessCPUtime() const {
1335 //   // We get the inferior process's cpu time via a ptrace() of the u-area
1336 //   // of the inferior process, though it should be possible to mmap()
1337 //   // the inferior process's uarea into paradynd if we really want to...
1338 //
1339 //   // UH OH: this will only work if the inferior process has been stopped!!!
1340 //
1341 //   static time64 prevResult = 0;
1342 //
1343 //   while (true) {
1344 //      // assumes child process has been stopped
1345 //      user childUareaPtr; // just a dummy
1346 //      unsigned addrOffset = (void *)&childUareaPtr.u_ru.ru_utime - (void *)&childUareaPtr;
1347 //      unsigned numBytesNeeded = (void *)&childUareaPtr.u_ru.ru_maxrss -
1348 //                                (void *)&childUareaPtr.u_ru.ru_utime;
1349 //      assert(numBytesNeeded % 4 == 0);
1350 //
1351 //      rusage theUsage; // we'll write into the first few bytes of this structure
1352 //      void *ptr = &theUsage.ru_utime;
1353 //
1354 //      cout << "peeking from uarea for pid " << this->getPid() << endl; cout.flush();
1355 //      while (numBytesNeeded) {
1356 //         errno = 0;
1357 //         unsigned result = P_ptrace(PTRACE_PEEKUSER, this->getPid(),
1358 //                                  (char*)addrOffset, 0, NULL);
1359 //         if (errno != 0) {
1360 //            perror("could not getChildCPUtimeViaPtraceOfUarea: ptrace()");
1361 //            exit(5);
1362 //         }
1363 //
1364 //         memcpy(ptr, &result, 4);
1365 //         ptr += 4;
1366 //         addrOffset += 4;
1367 //         numBytesNeeded -= 4;
1368 //      }
1369 //
1370 //      time64 result = userAndSysTime2uSecs(theUsage.ru_utime, theUsage.ru_stime);
1371 //      if (result < prevResult) {
1372 //         cout << "process::getInferiorProcessCPUtime() retrying due to rollback!" << endl;
1373 //         continue;
1374 //      }
1375 //      else {
1376 //         prevResult = result;
1377 //         return result;
1378 //      }
1379 //   }
1380 //}
1381
1382 bool process::loopUntilStopped() {
1383   /* make sure the process is stopped in the eyes of ptrace */
1384   stop_(); // sends SIGSTOP signal to the process
1385
1386   while (true) {
1387     int waitStatus;
1388     int ret = P_waitpid(getPid(), &waitStatus, WUNTRACED);
1389     if ((ret == -1 && errno == ECHILD) || (WIFEXITED(waitStatus))) {
1390       // the child is gone.
1391       handleProcessExit(this, WEXITSTATUS(waitStatus));
1392       return(false);
1393     } else if (WIFSIGNALED(waitStatus)) {
1394       handleProcessExit(this, WTERMSIG(waitStatus));
1395       return false;
1396     } else if (WIFSTOPPED(waitStatus)) {
1397       int sig = WSTOPSIG(waitStatus);
1398       if (sig == SIGSTOP) {
1399         break; // success
1400       } else {
1401         extern int handleSigChild(int, int);
1402         handleSigChild(pid, waitStatus);
1403       }
1404     }
1405     else {
1406       logLine("Problem stopping process\n");
1407       abort();
1408     }
1409   }
1410   return true;
1411 }
1412
1413 #ifndef BPATCH_LIBRARY
1414 bool process::dumpImage() {return false;}
1415 #else
1416 bool process::dumpImage(string imageFileName) 
1417 {
1418     int newFd;
1419     image *im;
1420     int length;
1421     string command;
1422
1423     im = getImage();
1424     string origFile = im->file();
1425
1426
1427     // first copy the entire image file
1428     command = "cp ";
1429     command += origFile;
1430     command += " ";
1431     command += imageFileName;
1432     system(command.string_of());
1433
1434     // now open the copy
1435     newFd = open(imageFileName.string_of(), O_RDWR, 0);
1436     if (newFd < 0) {
1437         // log error
1438         return false;
1439     }
1440
1441     Elf *elfp = elf_begin(newFd, ELF_C_READ, 0);
1442     Elf_Scn *scn = 0;
1443     u_int baseAddr;
1444     int offset;
1445
1446     Elf32_Ehdr* ehdrp;
1447     Elf_Scn* shstrscnp  = 0;
1448     Elf_Data* shstrdatap = 0;
1449     Elf32_Shdr* shdrp;
1450
1451     assert(ehdrp = elf32_getehdr(elfp));
1452     assert(((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) != 0) &&
1453            ((shstrdatap = elf_getdata(shstrscnp, 0)) != 0));
1454     const char* shnames = (const char *) shstrdatap->d_buf;
1455
1456     while ((scn = elf_nextscn(elfp, scn)) != 0) {
1457         const char* name;
1458
1459         shdrp = elf32_getshdr(scn);
1460         name = (const char *) &shnames[shdrp->sh_name];
1461         if (!strcmp(name, ".text")) {
1462             offset = shdrp->sh_offset;
1463             length = shdrp->sh_size;
1464             baseAddr = shdrp->sh_addr;
1465             break;
1466         }
1467     }
1468
1469
1470     char tempCode[length];
1471
1472
1473     bool ret = readTextSpace_((void *) baseAddr, length, tempCode);
1474     if (!ret) {
1475        // log error
1476        return false;
1477     }
1478
1479     lseek(newFd, offset, SEEK_SET);
1480     write(newFd, tempCode, length);
1481     close(newFd);
1482
1483     return true;
1484 }
1485 #endif
1486
1487 #ifndef BPATCH_LIBRARY
1488
1489 float OS::compute_rusage_cpu() { return 0; }
1490
1491 float OS::compute_rusage_sys() { return 0; }
1492
1493 float OS::compute_rusage_min() { return 0; }
1494
1495 float OS::compute_rusage_maj() { return 0; }
1496
1497 float OS::compute_rusage_swap() { return 0; }
1498
1499 float OS::compute_rusage_io_in() { return 0; }
1500
1501 float OS::compute_rusage_io_out() { return 0; }
1502
1503 float OS::compute_rusage_msg_send() { return 0; }
1504
1505 float OS::compute_rusage_msg_recv() { return 0; }
1506
1507 float OS::compute_rusage_sigs() { return 0; }
1508
1509 float OS::compute_rusage_vol_cs() { return 0; }
1510
1511 float OS::compute_rusage_inv_cs() { return 0; }
1512
1513 #endif
1514
1515 int getNumberOfCPUs()
1516 {
1517   return(1);
1518 }
1519
1520 Address process::read_inferiorRPC_result_register(Register reg) {
1521    // On x86, the result is always stashed in %EAX; at least, it is under Solaris
1522    // We'll see about Linux -- DAN
1523
1524    int raddr = EAX * 4;
1525    int eaxval = ptraceKludge::deliverPtrace(this, PTRACE_PEEKUSER, raddr, 0);
1526    if( errno ) {
1527      perror( "process::read_inferiorRPC_result_register; ptrace PEEKUSER" );
1528      assert(false);
1529    }
1530    return eaxval;
1531 }
1532
1533 bool process::set_breakpoint_for_syscall_completion() {
1534   // SUNos can't do this (as far as I know)
1535
1536   // I wonder if linux can? -- DAN
1537    return false;
1538 }
1539
1540
1541 void print_read_error_info(const relocationEntry entry, 
1542       pd_Function *&target_pdf, Address base_addr) {
1543
1544     sprintf(errorLine, "  entry      : target_addr 0x%x\n",
1545             entry.target_addr());
1546     logLine(errorLine);
1547     sprintf(errorLine, "               rel_addr 0x%x\n", entry.rel_addr());
1548     logLine(errorLine);
1549     sprintf(errorLine, "               name %s\n", (entry.name()).string_of());
1550     logLine(errorLine);
1551
1552     sprintf(errorLine, "  target_pdf : symTabName %s\n",
1553             (target_pdf->symTabName()).string_of());
1554     logLine(errorLine);    
1555     sprintf(errorLine , "              prettyName %s\n",
1556             (target_pdf->symTabName()).string_of());
1557     logLine(errorLine);
1558     sprintf(errorLine , "              size %i\n",
1559             target_pdf->size());
1560     logLine(errorLine);
1561     sprintf(errorLine , "              addr 0x%x\n",
1562             target_pdf->addr());
1563     logLine(errorLine);
1564
1565     sprintf(errorLine, "  base_addr  0x%x\n", base_addr);
1566     logLine(errorLine);
1567 }
1568
1569 // findCallee: finds the function called by the instruction corresponding
1570 // to the instPoint "instr". If the function call has been bound to an
1571 // address, then the callee function is returned in "target" and the 
1572 // instPoint "callee" data member is set to pt to callee's function_base.  
1573 // If the function has not yet been bound, then "target" is set to the 
1574 // function_base associated with the name of the target function (this is 
1575 // obtained by the PLT and relocation entries in the image), and the instPoint
1576 // callee is not set.  If the callee function cannot be found, (ex. function
1577 // pointers, or other indirect calls), it returns false.
1578 // Returns false on error (ex. process doesn't contain this instPoint).
1579 //
1580 // The assumption here is that for all processes sharing the image containing
1581 // this instPoint they are going to bind the call target to the same function. 
1582 // For shared objects this is always true, however this may not be true for
1583 // dynamic executables.  Two a.outs can be identical except for how they are
1584 // linked, so a call to fuction foo in one version of the a.out may be bound
1585 // to function foo in libfoo.so.1, and in the other version it may be bound to 
1586 // function foo in libfoo.so.2.  We are currently not handling this case, since
1587 // it is unlikely to happen in practice.
1588 bool process::findCallee(instPoint &instr, function_base *&target){
1589     
1590     if((target = (function_base *)instr.iPgetCallee())) {
1591         return true; // callee already set
1592     }
1593
1594     // find the corresponding image in this process  
1595     const image *owner = instr.iPgetOwner();
1596     bool found_image = false;
1597     Address base_addr = 0;
1598     if(symbols == owner) {  found_image = true; } 
1599     else if(shared_objects){
1600         for(u_int i=0; i < shared_objects->size(); i++){
1601             if(owner == ((*shared_objects)[i])->getImage()) {
1602                 found_image = true;
1603                 base_addr = ((*shared_objects)[i])->getBaseAddress();
1604                 break;
1605             }
1606         }
1607     } 
1608     if(!found_image) {
1609         target = 0;
1610         return false; // image not found...this is bad
1611     }
1612
1613     // get the target address of this function
1614     Address target_addr = 0;
1615 //    Address insn_addr = instr.iPgetAddress(); 
1616     target_addr = instr.getTargetAddress();
1617
1618     if(!target_addr) {  
1619         // this is either not a call instruction or an indirect call instr
1620         // that we can't get the target address
1621         target = 0;
1622         return false;
1623     }
1624
1625     // see if there is a function in this image at this target address
1626     // if so return it
1627     pd_Function *pdf = 0;
1628     if( (pdf = owner->findFunctionInInstAndUnInst(target_addr,this)) ) {
1629         target = pdf;
1630         instr.set_callee(pdf);
1631         return true; // target found...target is in this image
1632     }
1633
1634     // else, get the relocation information for this image
1635     const Object &obj = owner->getObject();
1636     const vector<relocationEntry> *fbt;
1637     if(!obj.get_func_binding_table_ptr(fbt)) {
1638         target = 0;
1639         return false; // target cannot be found...it is an indirect call.
1640     }
1641
1642     // find the target address in the list of relocationEntries
1643     for(u_int i=0; i < fbt->size(); i++) {
1644         if((*fbt)[i].target_addr() == target_addr) {
1645             // check to see if this function has been bound yet...if the
1646             // PLT entry for this function has been modified by the runtime
1647             // linker
1648             pd_Function *target_pdf = 0;
1649             if(hasBeenBound((*fbt)[i], target_pdf, base_addr)) {
1650                 target = target_pdf;
1651                 instr.set_callee(target_pdf);
1652                 return true;  // target has been bound
1653             } 
1654             else {
1655                 // just try to find a function with the same name as entry 
1656                 target = findOneFunctionFromAll((*fbt)[i].name());
1657                 if(target){
1658                     return true;
1659                 }
1660                 else {  
1661                     // KLUDGE: this is because we are not keeping more than
1662                     // one name for the same function if there is more
1663                     // than one.  This occurs when there are weak symbols
1664                     // that alias global symbols (ex. libm.so.1: "sin" 
1665                     // and "__sin").  In most cases the alias is the same as 
1666                     // the global symbol minus one or two leading underscores,
1667                     // so here we add one or two leading underscores to search
1668                     // for the name to handle the case where this string 
1669                     // is the name of the weak symbol...this will not fix 
1670                     // every case, since if the weak symbol and global symbol
1671                     // differ by more than leading underscores we won't find
1672                     // it...when we parse the image we should keep multiple
1673                     // names for pd_Functions
1674
1675                     string s = string("_");
1676                     s += (*fbt)[i].name();
1677                     target = findOneFunctionFromAll(s);
1678                     if(target){
1679                         return true;
1680                     }
1681                     s = string("__");
1682                     s += (*fbt)[i].name();
1683                     target = findOneFunctionFromAll(s);
1684                     if(target){
1685                         return true;
1686                     }
1687                 }
1688             }
1689             target = 0;
1690             return false;
1691         }
1692     }
1693     target = 0;
1694     return false;  
1695 }
1696
1697
1698 // hasBeenBound: returns true if the runtime linker has bound the
1699 // function symbol corresponding to the relocation entry in at the address
1700 // specified by entry and base_addr.  If it has been bound, then the callee 
1701 // function is returned in "target_pdf", else it returns false.
1702 bool process::hasBeenBound(const relocationEntry entry, 
1703                            pd_Function *&target_pdf, Address base_addr) {
1704
1705     if (status() == exited) return false;
1706
1707     // if the relocationEntry has not been bound yet, then the value
1708     // at rel_addr is the address of the instruction immediately following
1709     // the first instruction in the PLT entry (which is at the target_addr) 
1710     // The PLT entries are never modified, instead they use an indirrect 
1711     // jump to an address stored in the _GLOBAL_OFFSET_TABLE_.  When the 
1712     // function symbol is bound by the runtime linker, it changes the address
1713     // in the _GLOBAL_OFFSET_TABLE_ corresponding to the PLT entry
1714
1715     Address got_entry = entry.rel_addr() + base_addr;
1716     Address bound_addr = 0;
1717     if(!readDataSpace((const void*)got_entry, sizeof(Address), 
1718                         &bound_addr, true)){
1719         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%x, pid=%d\n (readDataSpace returns 0)",got_entry,pid);
1720         logLine(errorLine);
1721         print_read_error_info(entry, target_pdf, base_addr);
1722         return false;
1723     }
1724
1725     if( !( bound_addr == (entry.target_addr()+6+base_addr)) ) {
1726         // the callee function has been bound by the runtime linker
1727         // find the function and return it
1728         target_pdf = findpdFunctionIn(bound_addr);
1729         if(!target_pdf){
1730             return false;
1731         }
1732         return true;    
1733     }
1734     return false;
1735 }