2 * Copyright (c) 1996 Barton P. Miller
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.
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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
42 #include "util/h/headers.h"
43 #include "dyninstAPI/src/os.h"
44 #include "dyninstAPI/src/process.h"
45 #include "dyninstAPI/src/symtab.h"
46 #include "dyninstAPI/src/stats.h"
47 #include "util/h/Types.h"
48 #include "util/h/Object.h"
49 #include "util/h/Dictionary.h"
50 #include "dyninstAPI/src/instP.h" // class instInstance
51 #include "util/h/pathName.h"
53 #include <sys/ioctl.h>
54 #include <sys/types.h>
68 #include <sys/ptrace.h>
69 #include <procinfo.h> // struct procsinfo
70 #include <sys/types.h>
72 #include "paradynd/src/showerror.h"
73 #include "util/h/debugOstream.h"
76 extern int ioctl(int, int, ...);
79 // The following vrbles were defined in process.C:
80 extern debug_ostream attach_cerr;
81 extern debug_ostream inferiorrpc_cerr;
82 extern debug_ostream shmsample_cerr;
83 extern debug_ostream forkexec_cerr;
84 extern debug_ostream metric_cerr;
86 extern process* findProcess(int);
88 unsigned AIX_TEXT_OFFSET_HACK;
89 unsigned AIX_DATA_OFFSET_HACK;
93 static bool haltProcess(process *p);
94 static bool deliverPtrace(process *p, int req, void *addr,
95 int data, void *addr2);
96 static void continueProcess(process *p, const bool halted);
99 bool ptraceKludge::haltProcess(process *p) {
100 bool wasStopped = (p->status() == stopped);
101 if (p->status() != neonatal && !wasStopped) {
102 if (!p->loopUntilStopped()) {
103 cerr << "error in loopUntilStopped\n";
110 // what is the top most frame.
111 static int firstFrame;
114 // returns the current frame pointer (fp) and program counter (pc).
115 // returns true if we are able to read the registers.
117 bool process::getActiveFrame(int *fp, int *pc)
124 sp = P_ptrace(PT_READ_GPR, pid, (int *) STKP, 0, 0); // aix 4.1 likes int *
125 if (errno != 0) return false;
128 *pc = P_ptrace(PT_READ_GPR, pid, (int *) IAR, 0, 0); // aix 4.1 likes int *
129 if (errno != 0) return false;
131 // now we need to read the first frame from memory.
132 // The first frame pointer in in the memory location pointed to be sp
133 // However, there is no pc stored there, its the place to store a pc
134 // if the current function makes a call.
135 ret = readDataFromFrame(sp, fp, &dummy);
141 bool process::needToAddALeafFrame(Frame,unsigned int &){
147 // given the pointer to a frame (currentFP), return
148 // (1) the saved frame pointer (fp)
149 // NULL -> that currentFP is the bottom (last) frame.
150 // (2) the return address of the function for that frame (rtn).
151 // (3) return true if we are able to read the frame.
153 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool /*uppermost*/)
156 // define the linkage area of an activation record.
157 // This information is based on the data obtained from the
158 // info system (search for link area). - jkh 4/5/96
164 unsigned compilerInfo;
169 if (readDataSpace((caddr_t) currentFP,
173 *fp = linkArea.oldFp;
174 *rtn = linkArea.savedLR;
176 if (currentFP == firstFrame) {
177 // use the value stored in the link register instead.
179 *rtn = P_ptrace(PT_READ_GPR, pid, (int *)LR, 0, 0); // aix 4.1 likes int *
180 if (errno != 0) return false;
188 void *process::getRegisters() {
189 // assumes the process is stopped (ptrace requires it)
190 assert(status_ == stopped);
192 const int num_bytes = 32 * 4 // 32 general purpose integer registers
193 + 32 * 8 // 32 floating point registers @ 8 bytes each
194 + 9 * 4; // 9 special registers
195 // special registers are:
196 // IAR (instruction address register)
197 // MSR (machine state register)
198 // CR (condition register)
199 // LR (link register)
200 // CTR (count register)
201 // XER (fixed point exception)
202 // MQ (multiply quotient)
205 // FPINFO (fp info) [no, out of range of what ptrace can access (why?)]
206 // FPSCRX (fp sreg ext.) [no, out of range, too]
208 void *buffer = new char[num_bytes];
211 unsigned *bufferPtr = (unsigned *)buffer;
213 // First, the general-purpose integer registers:
215 // Format of PT_READ_GPR ptrace call:
216 // -- pass the reg number (see <sys/reg.h>) as the 'addr' (3d param)
217 // -- last 2 params (4th and 5th) ignored
218 // -- returns the value, or -1 on error
219 // but this leaves the question: what if the register really did contain -1; why
220 // should that be an error? So, we ignore what the man page says here, and
221 // instead look at 'errno'
223 // EIO --> 3d arg didn't specify a valid register (must be 0-31 or 128-136)
225 for (unsigned i=0; i < 32; i++) {
227 unsigned value = P_ptrace(PT_READ_GPR, pid, (void *)i, 0, 0);
229 perror("ptrace PT_READ_GPR");
230 cerr << "regnum was " << i << endl;
234 *bufferPtr++ = value;
237 // Next, the general purpose floating point registers.
239 // Format of PT_READ_FPR ptrace call: (it differs greatly from PT_READ_GPR,
240 // probably because the FPR registers are 64 bits instead of 32)
241 // -- 3d param ('address') is the location where ptrace will store the reg's value.
242 // -- 4th param ('data') specifies the fp reg (see <sys/reg.h>)
243 // -- last param (5th) to ptrace ignored
244 // Errors: returns -1 on error
245 // EIO --> 4th arg didn't specify a valid fp register (must be 256-287)
246 // Note: don't ask me why, but apparantly a return value of -1 doesn't seem
247 // to properly indicate an error; check errno instead.
249 for (unsigned i=0; i < 32; i++) {
251 assert(sizeof(double)==8); // make sure it's big enough!
254 P_ptrace(PT_READ_FPR, pid, &value,
255 FPR0 + i, // see <sys/reg.h>
258 perror("ptrace PT_READ_FPR");
259 cerr << "regnum was " << FPR0 + i << "; FPR0=" << FPR0 << endl;
263 memcpy(bufferPtr, &value, sizeof(value));
265 unsigned *oldBufferPtr = bufferPtr;
266 bufferPtr += 2; // 2 unsigned's --> 8 bytes
267 assert((char*)bufferPtr - (char*)oldBufferPtr == 8); // just for fun
269 assert(2*sizeof(unsigned) == 8);
272 // Finally, the special registers.
273 // (See the notes on PT_READ_GPR above: pass reg # as 3d param, 4th & 5th ignored)
274 // (Only reg numbered 0-31 or 128-136 are valid)
275 const int special_register_codenums [] = {IAR, MSR, CR, LR, CTR, XER, MQ, TID, FPSCR};
276 // see <sys/reg.h>; FPINFO and FPSCRX are out of range, so we can't use them!
277 const int num_special_registers = 9;
279 for (unsigned i=0; i < num_special_registers; i++) {
281 unsigned value = P_ptrace(PT_READ_GPR, pid, (void *)special_register_codenums[i], 0, 0);
283 perror("ptrace PT_READ_GPR for a special register");
284 cerr << "regnum was " << special_register_codenums[i] << endl;
288 *bufferPtr++ = value;
291 assert((unsigned)bufferPtr - (unsigned)buffer == num_bytes);
293 // Whew, finally done.
297 static bool executeDummyTrap(process *theProc) {
298 assert(theProc->status_ == stopped);
300 unsigned tempTramp = inferiorMalloc(theProc, 8, textHeap);
303 unsigned theInsns[2];
304 theInsns[0] = BREAK_POINT_INSN;
305 theInsns[1] = 0; // illegal insn, just to make sure we never exec past the trap
306 if (!theProc->writeDataSpace((void *)tempTramp, sizeof(theInsns), &theInsns)) {
307 cerr << "executeDummyTrap failed because writeTextSpace failed" << endl;
311 // Okay, the temp tramp has been set up. Let's set the PC there
313 unsigned oldpc = P_ptrace(PT_READ_GPR, theProc->getPid(), (void *)IAR, 0, 0);
317 P_ptrace(PT_WRITE_GPR, theProc->getPid(), (void *)IAR, tempTramp, 0);
320 if ((unsigned)P_ptrace(PT_READ_GPR, theProc->getPid(), (void *)IAR, 0, 0) != tempTramp) {
321 cerr << "executeDummyTrap failed because PT_READ_GPR of IAR register failed" << endl;
325 // We bypass continueProc() because continueProc() changes theProc->status_, which
326 // we don't want to do here
328 P_ptrace(PT_CONTINUE, theProc->getPid(), (void *)1, 0, 0);
329 // what if there are any pending signals? Don't we lose the chance to forward
336 // cerr << "doing a wait" << endl; cerr.flush();
337 pid = waitpid(theProc->getPid(), &status, WUNTRACED);
339 cerr << "waitpid returned special case of 0 (?)" << endl;
340 else if (pid == -1) {
342 // the child has died
345 perror("executeDummyTrap waitpid()");
348 // cerr << "waitpid result was " << pid << endl;
349 // if (pid == theProc->getPid())
350 // cerr << "which was the pid, as expected" << endl;
353 // cerr << "did a wait" << endl; cerr.flush();
354 } while (pid != theProc->getPid());
356 if (WIFEXITED(status))
360 assert(WIFSTOPPED(status));
362 int sig = WSTOPSIG(status);
363 if (sig == SIGTRAP) {
364 #ifdef INFERIOR_RPC_DEBUG
365 cerr << "executeDummyTrap: got SIGTRAP, as expected!" << endl;
370 // handle an 'ordinary' signal, e.g. SIGALRM
371 #ifdef INFERIOR_RPC_DEBUG
372 cerr << "executeDummyTrap: got unexpected signal " << sig << "...ignoring" << endl;
375 // We bypass continueProc() because continueProc() changes theProc->status_, which
376 // we don't want to do here
378 P_ptrace(PT_CONTINUE, theProc->getPid(), (void *)1, 0, 0);
379 // what if there are any pending signals? Don't we lose the chance to forward
383 // extern int handleSigChild(int, int);
384 // (void)handleSigChild(pid, status);
388 // Restore the old PC register value
390 P_ptrace(PT_WRITE_GPR, theProc->getPid(), (void *)IAR, oldpc, 0);
393 // delete the temp tramp now (not yet implemented)
395 #ifdef INFERIOR_RPC_DEBUG
396 cerr << "leaving executeDummyTrap now" << endl;
403 bool process::executingSystemCall() {
404 // this is not implemented yet - naim 5/15/97
408 bool process::changePC(unsigned loc) {
409 return changePC(loc, NULL);
412 bool process::changePC(unsigned loc, const void *) {
413 // compare to write_pc() of gdb (findvar.c)
414 // 2d arg (saved regs) of this routine isn't needed for aix, since it
415 // has the option to write just 1 register with a ptrace call.
417 // Format of PT_WRITE_GPR call:
418 // 3d param ('address'): the register to modify
419 // 4th param ('data'): the value to store
421 // Returns -1 on failure; else, returns the 'data' parameter
423 // EIO: 3d param not a valid register; must be 0-31 or 128-136
425 #ifdef INFERIOR_RPC_DEBUG
426 cerr << "welcome to changePC with loc=" << (void *)loc << endl;
429 // gdb hack: execute 1 dummy insn
430 #ifdef INFERIOR_RPC_DEBUG
431 cerr << "changePC: about to exec dummy trap" << endl;
433 if (!executeDummyTrap(this)) {
434 cerr << "changePC failed because executeDummyTrap failed" << endl;
439 P_ptrace(PT_WRITE_GPR, pid, (void *)IAR, loc, 0);
441 perror("changePC (PT_WRITE_GPR) failed");
445 // Double-check that the change was made by reading the IAR register
447 if (P_ptrace(PT_READ_GPR, pid, (void *)IAR, 0, 0) != (int)loc) {
448 cerr << "changePC failed because couldn't re-read IAR register" << endl;
456 bool process::restoreRegisters(void *buffer) {
457 // assumes process is stopped (ptrace requires it)
458 assert(status_ == stopped);
460 // WARNING: gdb has indications that one should execute a dummy instr (breakpoint)
461 // in order to let the kernel do housekeeping necessary to avoid corruption of
462 // the user stack (rs6000-nat.c). Should we worry about that?
463 // gdb's method (exec_one_dummy_insn()) works as follows: put a breakpoint
464 // instruction somewhere in the inferior, save the PC, write the PC to
465 // this dummy instr location, do a ptrace PT_CONTINUE, wait() for the signal,
466 // restore the PC, free up the breakpoint. But again, why is this needed?
468 unsigned *bufferPtr = (unsigned *)buffer;
470 // First, the general-purpose registers:
471 // Format for PT_WRITE_GPR:
472 // 3d param ('address'): specifies the register (must be 0-31 or 128-136)
473 // 4th param ('data'): specifies value to store
474 // 5th param ignored.
475 // Returns 3d param on success else -1 on error.
477 // EIO: address must be 0-31 or 128-136
479 for (unsigned i=GPR0; i <= GPR31; i++) {
481 P_ptrace(PT_WRITE_GPR, pid, (void *)i, *bufferPtr++, 0);
483 perror("ptrace PT_WRITE_GPR");
484 cerr << "regnum was " << i << endl;
489 // Next, the floating-point registers:
490 // Format of PT_WRITE_FPR: (it differs from PT_WRITE_GPR, probably because
491 // FP registers are 8 bytes instead of 4)
492 // 3d param ('address'): address of the value to store
493 // 4th param ('data'): reg num (256-287)
495 // returns -1 on error
497 // EIO: reg num must be 256-287
499 for (unsigned i=FPR0; i <= FPR31; i++) {
501 P_ptrace(PT_WRITE_FPR, pid, (void *)bufferPtr, i, 0);
502 // don't ask me why args 3,4 are reversed from the PT_WRITE_GPR case.,
503 // or why param 4 is a ptr to data instead of just data.
505 perror("ptrace PT_WRITE_FPR");
506 cerr << "regnum was " << i << endl;
510 const unsigned *oldBufferPtr = bufferPtr;
511 bufferPtr += 2; // 2 unsigned's == 8 bytes
512 assert((unsigned)bufferPtr - (unsigned)oldBufferPtr == 8); // just for fun
515 // Finally, special registers:
516 // Remeber, PT_WRITE_GPR gives an EIO error if the reg num isn't in range 128-136
517 const int special_register_codenums [] = {IAR, MSR, CR, LR, CTR, XER, MQ, TID, FPSCR};
518 // I'd like to add on FPINFO and FPSCRX, but their code nums in <sys/reg.h> (138, 148)
519 // make PT_WRITE_GPR give an EIO error...
520 const int num_special_registers = 9;
522 for (unsigned i=0; i < num_special_registers; i++) {
524 P_ptrace(PT_WRITE_GPR, pid, (void *)(special_register_codenums[i]), *bufferPtr++, 0);
526 perror("ptrace PT_WRITE_GPR for a special register");
527 cerr << "regnum was " << special_register_codenums[i] << endl;
532 return true; // success
536 bool process::emitInferiorRPCheader(void *insnPtr, unsigned &baseBytes) {
538 instruction *insn = (instruction *)insnPtr;
539 unsigned baseInstruc = baseBytes / sizeof(instruction);
541 // extern void generateBreakPoint(instruction &);
542 // generateBreakPoint(insn[baseInstruc++]);
543 // extern void generateIllegalInsn(instruction &);
544 // generateIllegalInsn(insn[baseInstruc++]);
546 // MT_AIX: since we don't have a base-trampoline here, we need to save
547 // registers before we can continue - naim
548 instruction *tmp_insn = (instruction *) (&insn[baseInstruc]);
549 extern void saveAllRegistersThatNeedsSaving(instruction *, unsigned &);
550 saveAllRegistersThatNeedsSaving(tmp_insn,baseInstruc);
553 baseBytes = baseInstruc * sizeof(instruction);
558 // note: the following should be moved to inst-power.C, since it's
559 // specific to an instruction set and not an OS, right?
560 bool process::emitInferiorRPCtrailer(void *insnPtr, unsigned &baseBytes,
561 unsigned &breakOffset,
563 unsigned &stopForResultOffset,
564 unsigned &justAfter_stopForResultOffset) {
565 // The sequence we want is: (restore), trap, illegal,
566 // where (restore) undoes anything done in emitInferiorRPCheader(), above.
568 instruction *insn = (instruction *)insnPtr;
569 unsigned baseInstruc = baseBytes / sizeof(instruction);
571 extern void generateBreakPoint(instruction &);
574 generateBreakPoint(insn[baseInstruc]);
575 stopForResultOffset = baseInstruc * sizeof(instruction);
578 justAfter_stopForResultOffset = baseInstruc * sizeof(instruction);
581 // MT_AIX: restoring previosly saved registers - naim
582 instruction *tmp_insn = (instruction *) (&insn[baseInstruc]);
583 extern void restoreAllRegistersThatNeededSaving(instruction *, unsigned &);
584 restoreAllRegistersThatNeededSaving(tmp_insn,baseInstruc);
586 // Trap instruction (breakpoint):
587 generateBreakPoint(insn[baseInstruc]);
588 breakOffset = baseInstruc * sizeof(instruction);
591 // And just to make sure that we don't continue, we put an illegal
593 extern void generateIllegalInsn(instruction &);
594 generateIllegalInsn(insn[baseInstruc++]);
596 baseBytes = baseInstruc * sizeof(instruction); // convert back
601 bool ptraceKludge::deliverPtrace(process *p, int req, void *addr,
602 int data, void *addr2) {
606 if (req != PT_DETACH) halted = haltProcess(p);
607 if (ptrace(req, p->getPid(), (int *)addr, data, (int *)addr2) == -1) // aix 4.1 likes int *
611 if (req != PT_DETACH) continueProcess(p, halted);
615 void ptraceKludge::continueProcess(process *p, const bool wasStopped) {
616 if ((p->status() != neonatal) && (!wasStopped)) {
618 /* Choose either one of the following methods to continue a process.
619 * The choice must be consistent with that in process::continueProc_ and stop_
622 #ifndef PTRACE_ATTACH_DETACH
623 if (ptrace(PT_CONTINUE, p->pid, (int *) 1, SIGCONT, NULL) == -1) {
625 //if (ptrace(PT_DETACH, p->pid, (int *) 1, SIGCONT, NULL) == -1) {
626 if (ptrace(PT_DETACH, p->pid, (int *) 1, SIGCONT, NULL) == -1) {
627 // aix 4.1 likes int *
629 logLine("Error in continueProcess\n");
635 // already setup on this FD.
636 // disconnect from controlling terminal
637 void OS::osDisconnect(void) {
638 int ttyfd = open ("/dev/tty", O_RDONLY);
639 ioctl (ttyfd, TIOCNOTTY, NULL);
643 bool process::stop_() {
644 /* Choose either one of the following methods for stopping a process,
646 * The choice must be consistent with that in process::continueProc_
647 * and ptraceKludge::continueProcess
649 #ifndef PTRACE_ATTACH_DETACH
650 return (P_kill(pid, SIGSTOP) != -1);
652 // attach generates a SIG TRAP which we catch
654 if (kill(pid, SIGSTOP) == -1)
661 bool process::continueWithForwardSignal(int sig) {
662 #if defined(PTRACE_ATTACH_DETACH)
664 ptrace(PT_DETACH, pid, (int*)1, stat, 0);
667 return (ptrace(PT_CONTINUE, pid, (int*)1, 0, 0) != -1);
670 return (ptrace(PT_CONTINUE, pid, (int*)1, sig, NULL) != -1);
674 void OS::osTraceMe(void)
678 ret = ptrace(PT_TRACE_ME, 0, 0, 0, 0);
683 // wait for a process to terminate or stop
684 #ifdef BPATCH_LIBRARY
685 int process::waitProcs(int *status, bool block) {
687 if (block) options = 0;
688 else options = WNOHANG;
689 return waitpid(0, status, options);
692 int process::waitProcs(int *status) {
693 return waitpid(0, status, WNOHANG);
698 // attach to an inferior process.
699 bool process::attach() {
700 // we only need to attach to a process that is not our direct children.
701 #ifdef BPATCH_LIBRARY
702 if (parent != 0 || createdViaAttach) {
705 // Get the initial trap
706 bool gotTrap = false;
709 int ret = waitpid(pid, &waitStatus, WUNTRACED);
710 if ((ret == -1) && (errno == EINTR)) continue;
711 if ((ret == -1) && (errno == ECHILD)) return false;
712 if(WIFEXITED(waitStatus)) {
713 // the child is gone.
715 handleProcessExit(this, WEXITSTATUS(waitStatus));
718 if (!WIFSTOPPED(waitStatus) && !WIFSIGNALED(waitStatus))
720 int sig = WSTOPSIG(waitStatus);
721 if (sig != SIGTRAP) {
722 extern int handleSigChild(int, int);
723 if (handleSigChild(pid, waitStatus) < 0)
724 cerr << "handleSigChild failed for pid " << pid << endl;
725 } else { //Process stopped by our attach
741 bool process::attach_() {
742 // formerly OS::osAttach()
743 int ret = ptrace(PT_ATTACH, getPid(), (int *)0, 0, 0);
745 ret = ptrace(PT_REATT, getPid(), (int *)0, 0, 0);
750 bool process::isRunning_() const {
751 // determine if a process is running by doing low-level system checks, as
752 // opposed to checking the 'status_' member vrble. May assume that attach()
753 // has run, but can't assume anything else.
755 assert(false); // not yet implemented!
758 // TODO is this safe here ?
759 bool process::continueProc_() {
764 ptraceOps++; ptraceOtherOps++;
766 /* Choose either one of the following methods to continue a process.
767 * The choice must be consistent with that in process::continueProc_ and stop_
770 #ifndef PTRACE_ATTACH_DETACH
771 if (!ptraceKludge::deliverPtrace(this, PT_CONTINUE, (char*)1, 0, NULL))
775 // switch these to not detach after every call.
776 //ret = ptrace(PT_CONTINUE, pid, (int *)1, 0, NULL);
778 ret = ptrace(PT_DETACH, pid, (int *)1, 0, NULL);
784 #ifdef BPATCH_LIBRARY
785 bool process::terminateProc_()
790 if (P_ptrace(PT_KILL, pid, NULL, NULL, NULL) != 0)
798 bool process::pause_() {
801 ptraceOps++; ptraceOtherOps++;
802 bool wasStopped = (status() == stopped);
803 if (status() != neonatal && !wasStopped)
804 return (loopUntilStopped());
809 bool process::detach_() {
811 ptraceOps++; ptraceOtherOps++;
812 if (!ptraceKludge::deliverPtrace(this,PT_DETACH,(char*)1,SIGSTOP, NULL))
814 sprintf(errorLine, "Unable to detach %d\n", getPid());
816 showErrorCallback(40, (const char *) errorLine);
819 // always return true since we report the error condition.
823 #ifdef BPATCH_LIBRARY
824 bool process::API_detach_(const bool cont) {
827 ptraceOps++; ptraceOtherOps++;
828 return (ptraceKludge::deliverPtrace(this,PT_DETACH,(char*)1, cont ? 0 : SIGSTOP,NULL));
832 // temporarily unimplemented, PT_DUMPCORE is specific to sunos4.1
833 bool process::dumpCore_(const string coreFile) {
836 ptraceOps++; ptraceOtherOps++;
838 #ifdef BPATCH_LIBRARY
839 if (!dumpImage(coreFile)) {
842 // if (!OS::osDumpImage(symbols->file(), pid, symbols->codeOffset()))
848 (void) ptrace(PT_CONTINUE, pid, (int*)1, SIGBUS, NULL);
853 bool process::writeTextWord_(caddr_t inTraced, int data) {
856 ptraceBytes += sizeof(int); ptraceOps++;
857 return (ptraceKludge::deliverPtrace(this, PT_WRITE_I, inTraced, data, NULL));
860 bool process::writeTextSpace_(void *inTraced, int amount, const void *inSelf) {
863 ptraceBytes += amount; ptraceOps++;
864 return (ptraceKludge::deliverPtrace(this, PT_WRITE_BLOCK, inTraced,
868 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
869 bool process::readTextSpace_(void *inTraced, int amount, const void *inSelf) {
872 ptraceOps++; ptraceBytes += amount;
873 return (ptraceKludge::deliverPtrace(this, PT_READ_BLOCK, inTraced, amount,
878 bool process::writeDataSpace_(void *inTraced, int amount, const void *inSelf) {
882 ptraceOps++; ptraceBytes += amount;
884 return (ptraceKludge::deliverPtrace(this, PT_WRITE_BLOCK, inTraced, amount, inSelf));
887 bool process::readDataSpace_(const void *inTraced, int amount, void *inSelf) {
890 ptraceOps++; ptraceBytes += amount;
891 return (ptraceKludge::deliverPtrace(this, PT_READ_BLOCK, inTraced, amount, inSelf));
894 bool process::loopUntilStopped() {
895 /* make sure the process is stopped in the eyes of ptrace */
896 stop_(); //Send the process a SIGSTOP
898 bool isStopped = false;
901 int ret = waitpid(pid, &waitStatus, WUNTRACED);
902 if ((ret == -1) && (errno == EINTR)) continue;
903 // these two ifs (ret==-1&&errno==ECHILD)||(WIF..) used to be together
904 // but had to seperate them, we were receiving ECHILD in a different
905 // situation, for some reason..
906 // if ((ret == -1 && errno == ECHILD) || (WIFEXITED(waitStatus))) {
907 if ((ret == -1) && (errno == ECHILD)) return true;
908 if(WIFEXITED(waitStatus)) {
909 // the child is gone.
911 handleProcessExit(this, WEXITSTATUS(waitStatus));
914 if (!WIFSTOPPED(waitStatus) && !WIFSIGNALED(waitStatus)) {
915 printf("problem stopping process\n");
918 int sig = WSTOPSIG(waitStatus);
919 if ((sig == SIGTRAP) || (sig == SIGSTOP) || (sig == SIGINT)) {
920 if (sig != SIGSTOP) { //Process already stopped, but not by our SIGSTOP
921 extern int handleSigChild(int, int);
922 if (handleSigChild(pid, waitStatus) < 0)
923 cerr << "handleSigChild failed for pid " << pid << endl;
924 } else { //Process stopped by our SIGSTOP
928 if (ptrace(PT_CONTINUE, pid, (int*)1, sig, 0) == -1) {
929 logLine("Ptrace error in PT_CONTINUE, loopUntilStopped\n");
940 // Write out the current contents of the text segment to disk. This is useful
941 // for debugging dyninst.
943 #ifdef BPATCH_LIBRARY
944 bool process::dumpImage(string outFile) {
946 bool process::dumpImage() {
948 // formerly OS::osDumpImage()
949 const string &imageFileName = symbols->file();
950 // const Address codeOff = symbols->codeOffset();
963 #ifndef BPATCH_LIBRARY
969 struct scnhdr *sectHdr;
970 bool needsCont = false;
971 struct ld_info info[64];
973 ifd = open(imageFileName.string_of(), O_RDONLY, 0);
975 sprintf(errorLine, "Unable to open %s\n", imageFileName.string_of());
977 showErrorCallback(41, (const char *) errorLine);
982 rd = fstat(ifd, &statBuf);
985 sprintf(errorLine, "Unable to stat %s\n", imageFileName.string_of());
987 showErrorCallback(72, (const char *) errorLine);
990 length = statBuf.st_size;
991 #ifdef BPATCH_LIBRARY
992 ofd = open(outFile.string_of(), O_WRONLY|O_CREAT, 0777);
994 sprintf(outFile, "%s.real", imageFileName.string_of());
995 sprintf(errorLine, "Saving program to %s\n", outFile);
998 ofd = open(outFile, O_WRONLY|O_CREAT, 0777);
1005 /* read header and section headers */
1006 cnt = read(ifd, &hdr, sizeof(struct filehdr));
1007 if (cnt != sizeof(struct filehdr)) {
1008 sprintf(errorLine, "Error reading header\n");
1010 showErrorCallback(44, "");
1014 cnt = read(ifd, &aout, sizeof(struct aouthdr));
1016 sectHdr = (struct scnhdr *) calloc(sizeof(struct scnhdr), hdr.f_nscns);
1017 cnt = read(ifd, sectHdr, sizeof(struct scnhdr) * hdr.f_nscns);
1018 if ((unsigned) cnt != sizeof(struct scnhdr)* hdr.f_nscns) {
1019 sprintf(errorLine, "Section headers\n");
1024 /* now copy the entire file */
1025 lseek(ofd, 0, SEEK_SET);
1026 lseek(ifd, 0, SEEK_SET);
1027 for (i=0; i < length; i += 4096) {
1028 rd = read(ifd, buffer, 4096);
1029 write(ofd, buffer, rd);
1034 // make sure it is stopped.
1035 findProcess(pid)->stop_();
1037 waitpid(pid, NULL, WUNTRACED);
1041 ret = ptrace(PT_LDINFO, pid, (int *) &info, sizeof(info), (int *) &info);
1043 statusLine("Unable to get loader info about process");
1044 showErrorCallback(43, "Unable to get loader info about process");
1048 baseAddr = (unsigned)info[0].ldinfo_textorg + (unsigned)aout.text_start;
1049 sprintf(errorLine, "seeking to %ld as the offset of the text segment \n",
1052 sprintf(errorLine, "Code offset = %d\n", baseAddr);
1055 /* seek to the text segment */
1056 lseek(ofd, aout.text_start, SEEK_SET);
1057 for (i=0; i < aout.tsize; i+= 1024) {
1059 length = ((i + 1024) < aout.tsize) ? 1024 : aout.tsize -i;
1060 ptrace(PT_READ_BLOCK, pid, (int*) (baseAddr + i), length, (int *)buffer);
1065 write(ofd, buffer, length);
1069 ptrace(PT_CONTINUE, pid, (int*) 1, SIGCONT, 0);
1079 // Seek to the desired offset and read the passed length of the file
1080 // into dest. If any errors are detected, log a message and return false.
1082 bool seekAndRead(int fd, int offset, void **dest, int length, bool allocate)
1087 *dest = malloc(length);
1091 sprintf(errorLine, "Unable to parse executable file\n");
1093 showErrorCallback(42, (const char *) errorLine);
1097 cnt = lseek(fd, offset, SEEK_SET);
1098 if (cnt != offset) {
1099 sprintf(errorLine, "Unable to parse executable file\n");
1101 showErrorCallback(42, (const char *) errorLine);
1104 cnt = read(fd, *dest, length);
1105 if (cnt != length) {
1106 sprintf(errorLine, "Unable to parse executable file\n");
1108 showErrorCallback(42, (const char *) errorLine);
1114 unsigned long roundup4(unsigned long val) {
1115 while (val % 4 != 0)
1120 void Object::load_object()
1122 // all these vrble declarations need to be up here due to the gotos,
1123 // which mustn't cross vrble initializations. Too bad.
1134 struct aouthdr aout;
1135 union auxent *csect;
1136 char *stringPool=NULL;
1137 Symbol::SymbolType type;
1138 int *lengthPtr = &poolLength;
1139 struct syment *symbols = NULL;
1140 struct scnhdr *sectHdr = NULL;
1141 Symbol::SymbolLinkage linkage;
1142 unsigned toc_offset = 0;
1145 fd = open(file_.string_of(), O_RDONLY, 0);
1147 sprintf(errorLine, "Unable to open executable file %s\n",
1149 statusLine(errorLine);
1150 showErrorCallback(27,(const char *) errorLine);
1154 cnt = read(fd, &hdr, sizeof(struct filehdr));
1155 if (cnt != sizeof(struct filehdr)) {
1156 sprintf(errorLine, "Error reading executable file %s\n",
1158 statusLine(errorLine);
1159 showErrorCallback(49,(const char *) errorLine);
1163 cnt = read(fd, &aout, sizeof(struct aouthdr));
1164 if (cnt != sizeof(struct aouthdr)) {
1165 sprintf(errorLine, "Error reading executable file %s\n",
1167 statusLine(errorLine);
1168 showErrorCallback(49,(const char *) errorLine);
1172 sectHdr = (struct scnhdr *) malloc(sizeof(struct scnhdr) * hdr.f_nscns);
1174 cnt = read(fd, sectHdr, sizeof(struct scnhdr) * hdr.f_nscns);
1175 if ((unsigned) cnt != sizeof(struct scnhdr)* hdr.f_nscns) {
1176 sprintf(errorLine, "Error reading executable file %s\n",
1178 statusLine(errorLine);
1179 showErrorCallback(49,(const char *) errorLine);
1183 // fprintf(stderr, "symbol table has %d entries starting at %d\n",
1184 // (int) hdr.f_nsyms, (int) hdr.f_symptr);
1186 if (!seekAndRead(fd, hdr.f_symptr, (void**) &symbols,
1187 hdr.f_nsyms * SYMESZ, true)) {
1192 * Get the string pool
1194 poolOffset = hdr.f_symptr + hdr.f_nsyms * SYMESZ;
1195 /* length is stored in the first 4 bytes of the string pool */
1196 if (!seekAndRead(fd, poolOffset, (void**) &lengthPtr, sizeof(int), false)) {
1200 if (!seekAndRead(fd, poolOffset, (void**) &stringPool, poolLength, true)) {
1204 // identify the code region.
1205 if ((unsigned) aout.tsize != sectHdr[aout.o_sntext-1].s_size) {
1206 // consistantcy check failed!!!!
1208 "Executable header file internal error: text segment size %s\n",
1210 statusLine(errorLine);
1211 showErrorCallback(45,(const char *) errorLine);
1215 if (!seekAndRead(fd, roundup4(sectHdr[aout.o_sntext-1].s_scnptr),
1216 (void **) &code_ptr_, aout.tsize, true)) {
1220 //code_off_ = aout.text_start + AIX_TEXT_OFFSET_HACK; (OLD, pre-4.1)
1221 code_off_ = aout.text_start;
1222 if (aout.text_start < TEXTORG) {
1223 code_off_ += AIX_TEXT_OFFSET_HACK;
1225 AIX_TEXT_OFFSET_HACK = 0;
1228 code_len_ = aout.tsize;
1230 // now the init data segment (as opposed to .bss, the uninitialized data segment)
1231 if ((unsigned long) aout.dsize != sectHdr[aout.o_sndata-1].s_size) {
1232 // consistantcy check failed!!!!
1234 "Executable header file interal error: data segment size %s\n",
1236 statusLine(errorLine);
1237 showErrorCallback(45,(const char *) errorLine);
1240 if (!seekAndRead(fd, roundup4(sectHdr[aout.o_sndata-1].s_scnptr),
1241 (void **) &data_ptr_, aout.dsize, true)) {
1242 cerr << "seekAndRead for initialized data section failed!" << endl;
1246 // data_off_ = sectHdr[aout.o_sndata-1].s_vaddr + AIX_DATA_OFFSET_HACK;
1248 data_off_ = aout.data_start;
1249 if (aout.data_start < DATAORG) {
1250 data_off_ += AIX_DATA_OFFSET_HACK;
1252 AIX_DATA_OFFSET_HACK = 0;
1254 // cerr << "load_object for aix: data_off=" << (void*)data_off_ << endl;
1255 // cerr << "after an original aout.data_start of " << (void*)aout.data_start << endl;
1256 // cerr << "and a DATAORG of " << (void*)DATAORG << endl;
1257 // cerr << "and an AIX_DATA_OFFSET_HACK of " << (void*)AIX_DATA_OFFSET_HACK << endl;
1258 // cerr << "aout.dsize is " << (void*)aout.dsize << endl;
1260 data_len_ = aout.dsize;
1262 // Now the symbol table itself:
1263 for (i=0; i < hdr.f_nsyms; i++) {
1264 /* do the pointer addition by hand since sizeof(struct syment)
1265 * seems to be 20 not 18 as it should be */
1266 sym = (struct syment *) (((unsigned) symbols) + i * SYMESZ);
1267 if (sym->n_sclass & DBXMASK)
1270 if ((sym->n_sclass == C_HIDEXT) ||
1271 (sym->n_sclass == C_EXT) ||
1272 (sym->n_sclass == C_FILE)) {
1273 if (!sym->n_zeroes) {
1274 name = string(&stringPool[sym->n_offset]);
1277 memset(tempName, 0, 9);
1278 strncpy(tempName, sym->n_name, 8);
1279 name = string(tempName);
1283 if ((sym->n_sclass == C_HIDEXT) || (sym->n_sclass == C_EXT)) {
1284 if (sym->n_sclass == C_HIDEXT) {
1285 linkage = Symbol::SL_LOCAL;
1287 linkage = Symbol::SL_GLOBAL;
1290 if (sym->n_scnum == aout.o_sntext) {
1291 type = Symbol::PDST_FUNCTION;
1292 // XXX - Hack for AIX loader.
1293 value = sym->n_value + AIX_TEXT_OFFSET_HACK;
1296 csect = (union auxent *)
1297 ((char *) sym + sym->n_numaux * SYMESZ);
1299 if (csect->x_csect.x_smclas == XMC_TC0) {
1301 logLine("Found more than one XMC_TC0 entry.");
1302 toc_offset = sym->n_value;
1306 if ((csect->x_csect.x_smclas == XMC_TC) ||
1307 (csect->x_csect.x_smclas == XMC_DS)) {
1308 // table of contents related entry not a real symbol.
1309 //dump << " toc entry -- ignoring" << endl;
1312 type = Symbol::PDST_OBJECT;
1313 // XXX - Hack for AIX loader.
1314 value = sym->n_value + AIX_DATA_OFFSET_HACK;
1318 // skip .text entries
1319 if (name == ".text") continue;
1320 if (name.prefixed_by(".")) {
1321 // XXXX - Hack to make names match assumptions of symtab.C
1322 name = string(name.string_of()+1);
1324 else if (type == Symbol::PDST_FUNCTION) {
1325 // text segment without a leady . is a toc item
1326 //dump << " (no leading . so assuming toc item & ignoring)" << endl;
1330 //dump << "name \"" << name << "\" in module \"" << modName << "\" value=" << (void*)value << endl;
1332 //fprintf(stderr, "Found symbol %s in (%s) at %x\n",
1333 // name.string_of(), modName.string_of(), value);
1334 Symbol sym(name, modName, type, linkage, value, false);
1335 symbols_[name] = sym;
1337 if (symbols_.defines(modName)) {
1338 // Adjust module's address, if necessary, to ensure that it's <= the
1339 // address of this new symbol
1340 Symbol &mod_symbol = symbols_[modName];
1341 if (value < mod_symbol.addr()) {
1342 //cerr << "adjusting addr of module " << modName
1343 // << " to " << value << endl;
1344 mod_symbol.setAddr(value);
1347 } else if (sym->n_sclass == C_FILE) {
1348 if (!strcmp(name.string_of(), ".file")) {
1350 /* has aux record with additional information. */
1351 for (j=1; j <= sym->n_numaux; j++) {
1352 aux = (union auxent *) ((char *) sym + j * SYMESZ);
1353 if (aux->x_file._x.x_ftype == XFT_FN) {
1354 // this aux record contains the file name.
1355 if (!aux->x_file._x.x_zeroes) {
1357 string(&stringPool[aux->x_file._x.x_offset]);
1359 // x_fname is 14 bytes
1361 memset(tempName, 0, 15);
1362 strncpy(tempName, aux->x_file.x_fname, 14);
1363 name = string(tempName);
1368 //dump << "found module \"" << name << "\"" << endl;
1372 const Symbol modSym(modName, modName,
1373 Symbol::PDST_MODULE, linkage,
1374 UINT_MAX, // dummy address for now!
1376 symbols_[modName] = modSym;
1382 // cout << "The value of TOC is: " << toc_offset << endl;
1383 //extern void initTocOffset(int);
1384 //initTocOffset(toc_offset);
1385 // this value is now defined per object. toc_offset_ is a private member
1386 // of class Object in Object-aix.h - naim
1387 toc_offset_ = toc_offset;
1391 if (sectHdr) free(sectHdr);
1392 if (stringPool) free(stringPool);
1393 if (symbols) free(symbols);
1399 Object::Object(const string file, void (*err_func)(const char *))
1400 : AObject(file, err_func) {
1404 Object::Object(const Object& obj)
1409 // for shared object files: not currently implemented
1410 // this should call a load_shared_object routine to parse the shared obj. file
1411 Object::Object(const string file,u_int,void (*err_func)(const char *))
1412 : AObject(file, err_func) {
1416 Object::~Object() { }
1418 Object& Object::operator=(const Object& obj) {
1419 (void) AObject::operator=(obj);
1424 // Verify that that program is statically linked, and establish the text
1425 // and data segments starting addresses.
1427 bool establishBaseAddrs(int pid, int &status, bool waitForTrap)
1430 struct ld_info *ptr;
1431 struct ld_info info[64];
1433 // check that the program was loaded at the correct address.
1434 //logLine("welcome to establishBaseAddrs\n");
1436 // wait for the TRAP point.
1438 waitpid(pid, &status, WUNTRACED);
1440 /* It seems that AIX has some timing problems and
1441 when the user stack grows, the kernel doesn't update the stack info in time
1442 and ptrace calls step on user stack. This is the reason why call sleep
1443 here, giving the kernel some time to update its internals. */
1446 ret = ptrace(PT_LDINFO, pid, (int *) &info, sizeof(info), (int *) &info);
1448 statusLine("Unable to get loader info about process, application aborted");
1449 showErrorCallback(43, "Unable to get loader info about process, application aborted");
1454 if (ptr->ldinfo_next) {
1455 statusLine("ERROR: program not statically linked");
1456 logLine("ERROR: program not statically linked");
1457 showErrorCallback(46, "Program not statically linked");
1462 AIX_TEXT_OFFSET_HACK = (unsigned) ptr->ldinfo_textorg + 0x200;
1463 AIX_DATA_OFFSET_HACK = (unsigned) ptr->ldinfo_dataorg;
1465 // turn on 'multiprocess debugging', which allows ptracing of both the
1466 // parent and child after a fork. In particular, both parent & child will
1467 // TRAP after a fork. Also, a process will TRAP after an exec (after the
1468 // new image has loaded but before it has started to execute at all).
1469 // Note that turning on multiprocess debugging enables two new values to be
1470 // returned by wait(): W_SEWTED and W_SFWTED, which indicate stops during
1471 // execution of exec and fork, respectively.
1472 ptrace(PT_MULTI, pid, 0, 1, 0);
1474 // cerr << "done with establishBaseAddrs; DATA hack=" << (void*)AIX_DATA_OFFSET_HACK
1481 // dummy versions of OS statistics.
1483 float OS::compute_rusage_cpu() { return(0.0); }
1484 float OS::compute_rusage_sys() { return(0.0); }
1485 float OS::compute_rusage_min() { return(0.0); }
1486 float OS::compute_rusage_maj() { return(0.0); }
1487 float OS::compute_rusage_swap() { return(0.0); }
1488 float OS::compute_rusage_io_in() { return(0.0); }
1489 float OS::compute_rusage_io_out() { return(0.0); }
1490 float OS::compute_rusage_msg_send() { return(0.0); }
1491 float OS::compute_rusage_sigs() { return(0.0); }
1492 float OS::compute_rusage_vol_cs() { return(0.0); }
1493 float OS::compute_rusage_inv_cs() { return(0.0); }
1494 float OS::compute_rusage_msg_recv() { return(0.0); }
1496 int getNumberOfCPUs()
1501 // #include "paradynd/src/metric.h"
1502 // #include "paradynd/src/costmetrics.h"
1506 // the following MUST become process member vrbles, since paradynd can have
1507 // more than one process active doing a fork!!!
1508 static bool seenForkTrapForParent = false;
1509 static bool seenForkTrapForChild = false;
1510 static pid_t pidForParent;
1511 static pid_t pidForChild;
1513 extern bool completeTheFork(process *, int);
1514 // in inst-power.C since class instPoint is too
1516 static void process_whenBothForkTrapsReceived() {
1517 assert(seenForkTrapForParent);
1518 assert(seenForkTrapForChild);
1520 forkexec_cerr << "welcome to: process_whenBothForkTrapsReceived" << endl;
1522 process *parent = findProcess(pidForParent);
1525 // complete the fork!
1527 forkexec_cerr << "calling completeTheFork" << endl;
1529 if (!completeTheFork(parent, pidForChild))
1532 // let's continue both processes
1534 if (!parent->continueProc())
1537 // Note that we use PT_CONTINUE on the child instead of kill(pid, SIGSTOP).
1538 // Is this right? (I think so)
1540 // int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, 0, 0);
1541 int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, SIGCONT, 0);
1545 seenForkTrapForParent = seenForkTrapForChild = false;
1547 forkexec_cerr << "leaving process_whenBothForkTrapsReceived (parent & "
1548 << "child running and should execute DYNINSTfork soon)"
1552 //////////////////////////////////////////////////////////////////////////
1553 //Restore the base trampolines after they have been cleared by an AIX load
1555 void resurrectBaseTramps(process *p)
1559 vector<const instPoint*> allInstPoints = p->baseMap.keys();
1561 extern void findAndReinstallBaseTramps(process *, vector<const instPoint*> &);
1562 findAndReinstallBaseTramps(p, allInstPoints);
1564 vector<instInstance*> allInstInstances; //Get all mini trampolines
1565 getAllInstInstancesForProcess(p, allInstInstances);
1567 extern void reattachMiniTramps(process *, vector<instInstance*> &);
1568 reattachMiniTramps(p, allInstInstances);
1572 bool handleAIXsigTraps(int pid, int status) {
1573 process *curr = findProcess(pid); // NULL for child of a fork
1575 // see man page for "waitpid" et al for descriptions of constants such
1576 // as W_SLWTED, W_SFWTED, etc.
1578 if (WIFSTOPPED(status) && (WSTOPSIG(status)==SIGTRAP)
1579 && ((status & 0x7f) == W_SLWTED)) {
1580 //Process is stopped on a load. AIX has reloaded the process image and
1581 // the text segment heap has been cleared.
1583 curr->status_ = stopped;
1584 //fprintf(stderr, "Got load SIGTRAP from pid %d, PC=%x\n", pid,
1585 // curr->currentPC());
1586 resurrectBaseTramps(curr); //Restore base trampolines
1587 curr->continueProc();
1590 } // W_SLWTED (stopped-on-load)
1592 // On AIX the processes will get a SIGTRAP when they execute a fork.
1593 // (Both the parent and the child will get this TRAP).
1594 // we must check for the SIGTRAP here, and handle the fork.
1595 // On aix the instrumentation on the parent will not be duplicated on
1596 // the child, so we need to insert instrumentation again.
1598 if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP
1599 && ((status & 0x7f) == W_SFWTED)) {
1601 // parent process. Stay stopped until the child process has completed
1602 // calling "completeTheFork()".
1603 forkexec_cerr << "AIX: got fork SIGTRAP from parent process " << pid << endl;
1605 curr->status_ = stopped;
1607 seenForkTrapForParent = true;
1608 pidForParent = curr->getPid();
1610 if (seenForkTrapForChild)
1611 process_whenBothForkTrapsReceived();
1616 forkexec_cerr << "AIX: got SIGTRAP from forked (child) process " << pid << endl;
1619 struct procsinfo psinfo;
1620 pid_t process_pid = pid;
1621 if (getprocs(&psinfo, sizeof(psinfo), NULL, 0, &process_pid, 1) == -1) {
1626 assert((pid_t)psinfo.pi_pid == pid);
1628 //string str = string("Parent of process ") + string(pid) + " is " +
1629 // string(psinfo.pi_ppid) + "\n";
1630 //logLine(str.string_of());
1632 seenForkTrapForChild = true;
1634 if (seenForkTrapForParent) {
1635 assert((pid_t) pidForParent == (pid_t) psinfo.pi_ppid);
1637 process_whenBothForkTrapsReceived();
1642 } // W_SFWTED (stopped-on-fork)
1647 string process::tryToFindExecutable(const string &progpath, int pid) {
1648 // returns empty string on failure
1650 if (progpath.length() == 0)
1653 if (exists_executable(progpath)) // util lib
1656 return ""; // failure
1659 unsigned process::read_inferiorRPC_result_register(reg returnValReg) {
1660 return P_ptrace(PT_READ_GPR, pid, (void *)returnValReg, 0, 0);
1663 bool process::set_breakpoint_for_syscall_completion() {
1664 // We don't know how to do this on AIX
1668 vector<int> process::getTOCoffsetInfo() const
1671 toc_offset = ((getImage())->getObject()).getTOCoffset();
1673 // st r2,20(r1) ; 0x90410014 save toc register
1674 dummy += 0x90410014;
1676 // liu r2, 0x0000 ;0x3c40abcd reset the toc value to 0xabcdefgh
1677 dummy += (0x3c400000 | (toc_offset >> 16));
1679 // oril r2, r2,0x0000 ;0x6042efgh
1680 dummy += (0x60420000 | (toc_offset & 0x0000ffff));