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.
44 * Revision 1.10 1996/05/12 05:12:57 tamches
46 * Added ability to process aix 4.1-linked files.
48 * Revision 1.9 1996/05/08 23:54:33 mjrg
49 * added support for handling fork and exec by an application
50 * use /proc instead of ptrace on solaris
53 * Revision 1.8 1996/04/06 21:25:24 hollings
54 * Fixed inst free to work on AIX (really any platform with split I/D heaps).
55 * Removed the Line class.
56 * Removed a debugging printf for multiple function returns.
58 * Revision 1.7 1996/03/12 20:48:16 mjrg
59 * Improved handling of process termination
60 * New version of aggregateSample to support adding and removing components
62 * Added error messages
64 * Revision 1.6 1996/02/13 16:23:22 hollings
65 * Move Object class constructors to this file.
67 * Revision 1.5 1996/02/12 16:46:06 naim
68 * Updating the way we compute number_of_cpus. On solaris we will return the
69 * number of cpus; on sunos, hp, aix 1 and on the CM-5 the number of processes,
70 * which should be equal to the number of cpus - naim
75 #include "util/h/headers.h"
76 #include "dyninstAPI/src/os.h"
77 #include "dyninstAPI/src/process.h"
78 #include "dyninstAPI/src/symtab.h"
79 #include "dyninstAPI/src/stats.h"
80 #include "util/h/Types.h"
81 #include "util/h/Object.h"
82 #include "util/h/Dictionary.h"
83 #include "dyninstAPI/src/instP.h" // class instInstance
84 #include "util/h/pathName.h"
86 #include <sys/ioctl.h>
87 #include <sys/types.h>
100 #include <sys/wait.h>
101 #include <sys/ptrace.h>
102 #include <procinfo.h> // struct procsinfo
103 #include <sys/types.h>
105 #include "paradynd/src/showerror.h"
106 #include "util/h/debugOstream.h"
109 extern int ioctl(int, int, ...);
112 // The following vrbles were defined in process.C:
113 extern debug_ostream attach_cerr;
114 extern debug_ostream inferiorrpc_cerr;
115 extern debug_ostream shmsample_cerr;
116 extern debug_ostream forkexec_cerr;
117 extern debug_ostream metric_cerr;
119 extern process* findProcess(int);
121 unsigned AIX_TEXT_OFFSET_HACK;
122 unsigned AIX_DATA_OFFSET_HACK;
126 static bool haltProcess(process *p);
127 static bool deliverPtrace(process *p, int req, void *addr,
128 int data, void *addr2);
129 static void continueProcess(process *p, const bool halted);
132 bool ptraceKludge::haltProcess(process *p) {
133 bool wasStopped = (p->status() == stopped);
134 if (p->status() != neonatal && !wasStopped) {
135 if (!p->loopUntilStopped()) {
136 cerr << "error in loopUntilStopped\n";
143 // what is the top most frame.
144 static int firstFrame;
147 // returns the current frame pointer (fp) and program counter (pc).
148 // returns true if we are able to read the registers.
150 bool process::getActiveFrame(int *fp, int *pc)
157 sp = P_ptrace(PT_READ_GPR, pid, (int *) STKP, 0, 0); // aix 4.1 likes int *
158 if (errno != 0) return false;
161 *pc = P_ptrace(PT_READ_GPR, pid, (int *) IAR, 0, 0); // aix 4.1 likes int *
162 if (errno != 0) return false;
164 // now we need to read the first frame from memory.
165 // The first frame pointer in in the memory location pointed to be sp
166 // However, there is no pc stored there, its the place to store a pc
167 // if the current function makes a call.
168 ret = readDataFromFrame(sp, fp, &dummy);
174 bool process::needToAddALeafFrame(Frame,unsigned int &){
180 // given the pointer to a frame (currentFP), return
181 // (1) the saved frame pointer (fp)
182 // NULL -> that currentFP is the bottom (last) frame.
183 // (2) the return address of the function for that frame (rtn).
184 // (3) return true if we are able to read the frame.
186 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool /*uppermost*/)
189 // define the linkage area of an activation record.
190 // This information is based on the data obtained from the
191 // info system (search for link area). - jkh 4/5/96
197 unsigned compilerInfo;
202 if (readDataSpace((caddr_t) currentFP,
206 *fp = linkArea.oldFp;
207 *rtn = linkArea.savedLR;
209 if (currentFP == firstFrame) {
210 // use the value stored in the link register instead.
212 *rtn = P_ptrace(PT_READ_GPR, pid, (int *)LR, 0, 0); // aix 4.1 likes int *
213 if (errno != 0) return false;
221 void *process::getRegisters() {
222 // assumes the process is stopped (ptrace requires it)
223 assert(status_ == stopped);
225 const int num_bytes = 32 * 4 // 32 general purpose integer registers
226 + 32 * 8 // 32 floating point registers @ 8 bytes each
227 + 9 * 4; // 9 special registers
228 // special registers are:
229 // IAR (instruction address register)
230 // MSR (machine state register)
231 // CR (condition register)
232 // LR (link register)
233 // CTR (count register)
234 // XER (fixed point exception)
235 // MQ (multiply quotient)
238 // FPINFO (fp info) [no, out of range of what ptrace can access (why?)]
239 // FPSCRX (fp sreg ext.) [no, out of range, too]
241 void *buffer = new char[num_bytes];
244 unsigned *bufferPtr = (unsigned *)buffer;
246 // First, the general-purpose integer registers:
248 // Format of PT_READ_GPR ptrace call:
249 // -- pass the reg number (see <sys/reg.h>) as the 'addr' (3d param)
250 // -- last 2 params (4th and 5th) ignored
251 // -- returns the value, or -1 on error
252 // but this leaves the question: what if the register really did contain -1; why
253 // should that be an error? So, we ignore what the man page says here, and
254 // instead look at 'errno'
256 // EIO --> 3d arg didn't specify a valid register (must be 0-31 or 128-136)
258 for (unsigned i=0; i < 32; i++) {
260 unsigned value = P_ptrace(PT_READ_GPR, pid, (void *)i, 0, 0);
262 perror("ptrace PT_READ_GPR");
263 cerr << "regnum was " << i << endl;
267 *bufferPtr++ = value;
270 // Next, the general purpose floating point registers.
272 // Format of PT_READ_FPR ptrace call: (it differs greatly from PT_READ_GPR,
273 // probably because the FPR registers are 64 bits instead of 32)
274 // -- 3d param ('address') is the location where ptrace will store the reg's value.
275 // -- 4th param ('data') specifies the fp reg (see <sys/reg.h>)
276 // -- last param (5th) to ptrace ignored
277 // Errors: returns -1 on error
278 // EIO --> 4th arg didn't specify a valid fp register (must be 256-287)
279 // Note: don't ask me why, but apparantly a return value of -1 doesn't seem
280 // to properly indicate an error; check errno instead.
282 for (unsigned i=0; i < 32; i++) {
284 assert(sizeof(double)==8); // make sure it's big enough!
287 P_ptrace(PT_READ_FPR, pid, &value,
288 FPR0 + i, // see <sys/reg.h>
291 perror("ptrace PT_READ_FPR");
292 cerr << "regnum was " << FPR0 + i << "; FPR0=" << FPR0 << endl;
296 memcpy(bufferPtr, &value, sizeof(value));
298 unsigned *oldBufferPtr = bufferPtr;
299 bufferPtr += 2; // 2 unsigned's --> 8 bytes
300 assert((char*)bufferPtr - (char*)oldBufferPtr == 8); // just for fun
302 assert(2*sizeof(unsigned) == 8);
305 // Finally, the special registers.
306 // (See the notes on PT_READ_GPR above: pass reg # as 3d param, 4th & 5th ignored)
307 // (Only reg numbered 0-31 or 128-136 are valid)
308 const int special_register_codenums [] = {IAR, MSR, CR, LR, CTR, XER, MQ, TID, FPSCR};
309 // see <sys/reg.h>; FPINFO and FPSCRX are out of range, so we can't use them!
310 const int num_special_registers = 9;
312 for (unsigned i=0; i < num_special_registers; i++) {
314 unsigned value = P_ptrace(PT_READ_GPR, pid, (void *)special_register_codenums[i], 0, 0);
316 perror("ptrace PT_READ_GPR for a special register");
317 cerr << "regnum was " << special_register_codenums[i] << endl;
321 *bufferPtr++ = value;
324 assert((unsigned)bufferPtr - (unsigned)buffer == num_bytes);
326 // Whew, finally done.
330 static bool executeDummyTrap(process *theProc) {
331 assert(theProc->status_ == stopped);
333 unsigned tempTramp = inferiorMalloc(theProc, 8, textHeap);
336 unsigned theInsns[2];
337 theInsns[0] = BREAK_POINT_INSN;
338 theInsns[1] = 0; // illegal insn, just to make sure we never exec past the trap
339 if (!theProc->writeDataSpace((void *)tempTramp, sizeof(theInsns), &theInsns)) {
340 cerr << "executeDummyTrap failed because writeTextSpace failed" << endl;
344 // Okay, the temp tramp has been set up. Let's set the PC there
346 unsigned oldpc = P_ptrace(PT_READ_GPR, theProc->getPid(), (void *)IAR, 0, 0);
350 P_ptrace(PT_WRITE_GPR, theProc->getPid(), (void *)IAR, tempTramp, 0);
353 if ((unsigned)P_ptrace(PT_READ_GPR, theProc->getPid(), (void *)IAR, 0, 0) != tempTramp) {
354 cerr << "executeDummyTrap failed because PT_READ_GPR of IAR register failed" << endl;
358 // We bypass continueProc() because continueProc() changes theProc->status_, which
359 // we don't want to do here
361 P_ptrace(PT_CONTINUE, theProc->getPid(), (void *)1, 0, 0);
362 // what if there are any pending signals? Don't we lose the chance to forward
369 // cerr << "doing a wait" << endl; cerr.flush();
370 pid = waitpid(theProc->getPid(), &status, WUNTRACED);
372 cerr << "waitpid returned special case of 0 (?)" << endl;
373 else if (pid == -1) {
375 // the child has died
378 perror("executeDummyTrap waitpid()");
381 // cerr << "waitpid result was " << pid << endl;
382 // if (pid == theProc->getPid())
383 // cerr << "which was the pid, as expected" << endl;
386 // cerr << "did a wait" << endl; cerr.flush();
387 } while (pid != theProc->getPid());
389 if (WIFEXITED(status))
393 assert(WIFSTOPPED(status));
395 int sig = WSTOPSIG(status);
396 if (sig == SIGTRAP) {
397 #ifdef INFERIOR_RPC_DEBUG
398 cerr << "executeDummyTrap: got SIGTRAP, as expected!" << endl;
403 // handle an 'ordinary' signal, e.g. SIGALRM
404 #ifdef INFERIOR_RPC_DEBUG
405 cerr << "executeDummyTrap: got unexpected signal " << sig << "...ignoring" << endl;
408 // We bypass continueProc() because continueProc() changes theProc->status_, which
409 // we don't want to do here
411 P_ptrace(PT_CONTINUE, theProc->getPid(), (void *)1, 0, 0);
412 // what if there are any pending signals? Don't we lose the chance to forward
416 // extern int handleSigChild(int, int);
417 // (void)handleSigChild(pid, status);
421 // Restore the old PC register value
423 P_ptrace(PT_WRITE_GPR, theProc->getPid(), (void *)IAR, oldpc, 0);
426 // delete the temp tramp now (not yet implemented)
428 #ifdef INFERIOR_RPC_DEBUG
429 cerr << "leaving executeDummyTrap now" << endl;
436 bool process::executingSystemCall() {
437 // this is not implemented yet - naim 5/15/97
441 bool process::changePC(unsigned loc) {
442 return changePC(loc, NULL);
445 bool process::changePC(unsigned loc, const void *) {
446 // compare to write_pc() of gdb (findvar.c)
447 // 2d arg (saved regs) of this routine isn't needed for aix, since it
448 // has the option to write just 1 register with a ptrace call.
450 // Format of PT_WRITE_GPR call:
451 // 3d param ('address'): the register to modify
452 // 4th param ('data'): the value to store
454 // Returns -1 on failure; else, returns the 'data' parameter
456 // EIO: 3d param not a valid register; must be 0-31 or 128-136
458 #ifdef INFERIOR_RPC_DEBUG
459 cerr << "welcome to changePC with loc=" << (void *)loc << endl;
462 // gdb hack: execute 1 dummy insn
463 #ifdef INFERIOR_RPC_DEBUG
464 cerr << "changePC: about to exec dummy trap" << endl;
466 if (!executeDummyTrap(this)) {
467 cerr << "changePC failed because executeDummyTrap failed" << endl;
472 P_ptrace(PT_WRITE_GPR, pid, (void *)IAR, loc, 0);
474 perror("changePC (PT_WRITE_GPR) failed");
478 // Double-check that the change was made by reading the IAR register
480 if (P_ptrace(PT_READ_GPR, pid, (void *)IAR, 0, 0) != (int)loc) {
481 cerr << "changePC failed because couldn't re-read IAR register" << endl;
489 bool process::restoreRegisters(void *buffer) {
490 // assumes process is stopped (ptrace requires it)
491 assert(status_ == stopped);
493 // WARNING: gdb has indications that one should execute a dummy instr (breakpoint)
494 // in order to let the kernel do housekeeping necessary to avoid corruption of
495 // the user stack (rs6000-nat.c). Should we worry about that?
496 // gdb's method (exec_one_dummy_insn()) works as follows: put a breakpoint
497 // instruction somewhere in the inferior, save the PC, write the PC to
498 // this dummy instr location, do a ptrace PT_CONTINUE, wait() for the signal,
499 // restore the PC, free up the breakpoint. But again, why is this needed?
501 unsigned *bufferPtr = (unsigned *)buffer;
503 // First, the general-purpose registers:
504 // Format for PT_WRITE_GPR:
505 // 3d param ('address'): specifies the register (must be 0-31 or 128-136)
506 // 4th param ('data'): specifies value to store
507 // 5th param ignored.
508 // Returns 3d param on success else -1 on error.
510 // EIO: address must be 0-31 or 128-136
512 for (unsigned i=GPR0; i <= GPR31; i++) {
514 P_ptrace(PT_WRITE_GPR, pid, (void *)i, *bufferPtr++, 0);
516 perror("ptrace PT_WRITE_GPR");
517 cerr << "regnum was " << i << endl;
522 // Next, the floating-point registers:
523 // Format of PT_WRITE_FPR: (it differs from PT_WRITE_GPR, probably because
524 // FP registers are 8 bytes instead of 4)
525 // 3d param ('address'): address of the value to store
526 // 4th param ('data'): reg num (256-287)
528 // returns -1 on error
530 // EIO: reg num must be 256-287
532 for (unsigned i=FPR0; i <= FPR31; i++) {
534 P_ptrace(PT_WRITE_FPR, pid, (void *)bufferPtr, i, 0);
535 // don't ask me why args 3,4 are reversed from the PT_WRITE_GPR case.,
536 // or why param 4 is a ptr to data instead of just data.
538 perror("ptrace PT_WRITE_FPR");
539 cerr << "regnum was " << i << endl;
543 const unsigned *oldBufferPtr = bufferPtr;
544 bufferPtr += 2; // 2 unsigned's == 8 bytes
545 assert((unsigned)bufferPtr - (unsigned)oldBufferPtr == 8); // just for fun
548 // Finally, special registers:
549 // Remeber, PT_WRITE_GPR gives an EIO error if the reg num isn't in range 128-136
550 const int special_register_codenums [] = {IAR, MSR, CR, LR, CTR, XER, MQ, TID, FPSCR};
551 // I'd like to add on FPINFO and FPSCRX, but their code nums in <sys/reg.h> (138, 148)
552 // make PT_WRITE_GPR give an EIO error...
553 const int num_special_registers = 9;
555 for (unsigned i=0; i < num_special_registers; i++) {
557 P_ptrace(PT_WRITE_GPR, pid, (void *)(special_register_codenums[i]), *bufferPtr++, 0);
559 perror("ptrace PT_WRITE_GPR for a special register");
560 cerr << "regnum was " << special_register_codenums[i] << endl;
565 return true; // success
569 bool process::emitInferiorRPCheader(void *insnPtr, unsigned &baseBytes) {
571 instruction *insn = (instruction *)insnPtr;
572 unsigned baseInstruc = baseBytes / sizeof(instruction);
574 // extern void generateBreakPoint(instruction &);
575 // generateBreakPoint(insn[baseInstruc++]);
576 // extern void generateIllegalInsn(instruction &);
577 // generateIllegalInsn(insn[baseInstruc++]);
579 // MT_AIX: since we don't have a base-trampoline here, we need to save
580 // registers before we can continue - naim
581 instruction *tmp_insn = (instruction *) (&insn[baseInstruc]);
582 extern void saveAllRegistersThatNeedsSaving(instruction *, unsigned &);
583 saveAllRegistersThatNeedsSaving(tmp_insn,baseInstruc);
586 baseBytes = baseInstruc * sizeof(instruction);
591 // note: the following should be moved to inst-power.C, since it's
592 // specific to an instruction set and not an OS, right?
593 bool process::emitInferiorRPCtrailer(void *insnPtr, unsigned &baseBytes,
594 unsigned &breakOffset,
596 unsigned &stopForResultOffset,
597 unsigned &justAfter_stopForResultOffset) {
598 // The sequence we want is: (restore), trap, illegal,
599 // where (restore) undoes anything done in emitInferiorRPCheader(), above.
601 instruction *insn = (instruction *)insnPtr;
602 unsigned baseInstruc = baseBytes / sizeof(instruction);
604 extern void generateBreakPoint(instruction &);
607 generateBreakPoint(insn[baseInstruc]);
608 stopForResultOffset = baseInstruc * sizeof(instruction);
611 justAfter_stopForResultOffset = baseInstruc * sizeof(instruction);
614 // MT_AIX: restoring previosly saved registers - naim
615 instruction *tmp_insn = (instruction *) (&insn[baseInstruc]);
616 extern void restoreAllRegistersThatNeededSaving(instruction *, unsigned &);
617 restoreAllRegistersThatNeededSaving(tmp_insn,baseInstruc);
619 // Trap instruction (breakpoint):
620 generateBreakPoint(insn[baseInstruc]);
621 breakOffset = baseInstruc * sizeof(instruction);
624 // And just to make sure that we don't continue, we put an illegal
626 extern void generateIllegalInsn(instruction &);
627 generateIllegalInsn(insn[baseInstruc++]);
629 baseBytes = baseInstruc * sizeof(instruction); // convert back
634 bool ptraceKludge::deliverPtrace(process *p, int req, void *addr,
635 int data, void *addr2) {
639 if (req != PT_DETACH) halted = haltProcess(p);
640 if (ptrace(req, p->getPid(), (int *)addr, data, (int *)addr2) == -1) // aix 4.1 likes int *
644 if (req != PT_DETACH) continueProcess(p, halted);
648 void ptraceKludge::continueProcess(process *p, const bool wasStopped) {
649 if ((p->status() != neonatal) && (!wasStopped)) {
651 /* Choose either one of the following methods to continue a process.
652 * The choice must be consistent with that in process::continueProc_ and stop_
655 #ifndef PTRACE_ATTACH_DETACH
656 if (ptrace(PT_CONTINUE, p->pid, (int *) 1, SIGCONT, NULL) == -1) {
658 //if (ptrace(PT_DETACH, p->pid, (int *) 1, SIGCONT, NULL) == -1) {
659 if (ptrace(PT_DETACH, p->pid, (int *) 1, SIGCONT, NULL) == -1) {
660 // aix 4.1 likes int *
662 logLine("Error in continueProcess\n");
668 // already setup on this FD.
669 // disconnect from controlling terminal
670 void OS::osDisconnect(void) {
671 int ttyfd = open ("/dev/tty", O_RDONLY);
672 ioctl (ttyfd, TIOCNOTTY, NULL);
676 bool process::stop_() {
677 /* Choose either one of the following methods for stopping a process,
679 * The choice must be consistent with that in process::continueProc_
680 * and ptraceKludge::continueProcess
682 #ifndef PTRACE_ATTACH_DETACH
683 return (P_kill(pid, SIGSTOP) != -1);
685 // attach generates a SIG TRAP which we catch
687 if (kill(pid, SIGSTOP) == -1)
694 bool process::continueWithForwardSignal(int sig) {
695 #if defined(PTRACE_ATTACH_DETACH)
697 ptrace(PT_DETACH, pid, (int*)1, stat, 0);
700 return (ptrace(PT_CONTINUE, pid, (int*)1, 0, 0) != -1);
703 return (ptrace(PT_CONTINUE, pid, (int*)1, sig, NULL) != -1);
707 void OS::osTraceMe(void)
711 ret = ptrace(PT_TRACE_ME, 0, 0, 0, 0);
716 // wait for a process to terminate or stop
717 int process::waitProcs(int *status) {
718 return waitpid(0, status, WNOHANG);
722 // attach to an inferior process.
723 bool process::attach() {
724 // we only need to attach to a process that is not our direct children.
732 bool process::attach_() {
733 // formerly OS::osAttach()
734 int ret = ptrace(PT_ATTACH, getPid(), (int *)0, 0, 0);
736 ret = ptrace(PT_REATT, getPid(), (int *)0, 0, 0);
741 bool process::isRunning_() const {
742 // determine if a process is running by doing low-level system checks, as
743 // opposed to checking the 'status_' member vrble. May assume that attach()
744 // has run, but can't assume anything else.
746 assert(false); // not yet implemented!
749 // TODO is this safe here ?
750 bool process::continueProc_() {
755 ptraceOps++; ptraceOtherOps++;
757 /* Choose either one of the following methods to continue a process.
758 * The choice must be consistent with that in process::continueProc_ and stop_
761 #ifndef PTRACE_ATTACH_DETACH
762 if (!ptraceKludge::deliverPtrace(this, PT_CONTINUE, (char*)1, 0, NULL))
766 // switch these to not detach after every call.
767 //ret = ptrace(PT_CONTINUE, pid, (int *)1, 0, NULL);
769 ret = ptrace(PT_DETACH, pid, (int *)1, 0, NULL);
775 #ifdef BPATCH_LIBRARY
776 bool process::terminateProc_()
781 if (P_ptrace(PT_KILL, pid, NULL, NULL, NULL) != 0)
789 bool process::pause_() {
792 ptraceOps++; ptraceOtherOps++;
793 bool wasStopped = (status() == stopped);
794 if (status() != neonatal && !wasStopped)
795 return (loopUntilStopped());
800 bool process::detach_() {
802 ptraceOps++; ptraceOtherOps++;
803 if (!ptraceKludge::deliverPtrace(this,PT_DETACH,(char*)1,SIGSTOP, NULL))
805 sprintf(errorLine, "Unable to detach %d\n", getPid());
807 showErrorCallback(40, (const char *) errorLine);
810 // always return true since we report the error condition.
814 #ifdef BPATCH_LIBRARY
815 bool process::API_detach_(const bool cont) {
818 ptraceOps++; ptraceOtherOps++;
819 return (ptraceKludge::deliverPtrace(this,PT_DETACH,(char*)1, cont ? 0 : SIGSTOP,NULL));
823 // temporarily unimplemented, PT_DUMPCORE is specific to sunos4.1
824 bool process::dumpCore_(const string /*coreFile*/) {
827 ptraceOps++; ptraceOtherOps++;
830 // if (!OS::osDumpImage(symbols->file(), pid, symbols->codeOffset()))
835 (void) ptrace(PT_CONTINUE, pid, (int*)1, SIGBUS, NULL);
840 bool process::writeTextWord_(caddr_t inTraced, int data) {
843 ptraceBytes += sizeof(int); ptraceOps++;
844 return (ptraceKludge::deliverPtrace(this, PT_WRITE_I, inTraced, data, NULL));
847 bool process::writeTextSpace_(void *inTraced, int amount, const void *inSelf) {
850 ptraceBytes += amount; ptraceOps++;
851 return (ptraceKludge::deliverPtrace(this, PT_WRITE_BLOCK, inTraced,
855 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
856 bool process::readTextSpace_(void *inTraced, int amount, const void *inSelf) {
859 ptraceOps++; ptraceBytes += amount;
860 return (ptraceKludge::deliverPtrace(this, PT_READ_BLOCK, inTraced, amount,
865 bool process::writeDataSpace_(void *inTraced, int amount, const void *inSelf) {
869 ptraceOps++; ptraceBytes += amount;
871 return (ptraceKludge::deliverPtrace(this, PT_WRITE_BLOCK, inTraced, amount, inSelf));
874 bool process::readDataSpace_(const void *inTraced, int amount, void *inSelf) {
877 ptraceOps++; ptraceBytes += amount;
878 return (ptraceKludge::deliverPtrace(this, PT_READ_BLOCK, inTraced, amount, inSelf));
881 bool process::loopUntilStopped() {
882 /* make sure the process is stopped in the eyes of ptrace */
883 stop_(); //Send the process a SIGSTOP
885 bool isStopped = false;
888 int ret = waitpid(pid, &waitStatus, WUNTRACED);
889 if ((ret == -1) && (errno == EINTR)) continue;
890 // these two ifs (ret==-1&&errno==ECHILD)||(WIF..) used to be together
891 // but had to seperate them, we were receiving ECHILD in a different
892 // situation, for some reason..
893 // if ((ret == -1 && errno == ECHILD) || (WIFEXITED(waitStatus))) {
894 if ((ret == -1) && (errno == ECHILD)) return true;
895 if(WIFEXITED(waitStatus)) {
896 // the child is gone.
898 handleProcessExit(this, WEXITSTATUS(waitStatus));
901 if (!WIFSTOPPED(waitStatus) && !WIFSIGNALED(waitStatus)) {
902 printf("problem stopping process\n");
905 int sig = WSTOPSIG(waitStatus);
906 if ((sig == SIGTRAP) || (sig == SIGSTOP) || (sig == SIGINT)) {
907 if (sig != SIGSTOP) { //Process already stopped, but not by our SIGSTOP
908 extern int handleSigChild(int, int);
909 if (handleSigChild(pid, waitStatus) < 0)
910 cerr << "handleSigChild failed for pid " << pid << endl;
911 } else { //Process stopped by our SIGSTOP
915 if (ptrace(PT_CONTINUE, pid, (int*)1, sig, 0) == -1) {
916 logLine("Ptrace error in PT_CONTINUE, loopUntilStopped\n");
927 // Write out the current contents of the text segment to disk. This is useful
928 // for debugging dyninst.
930 bool process::dumpImage() {
931 // formerly OS::osDumpImage()
932 const string &imageFileName = symbols->file();
933 // const Address codeOff = symbols->codeOffset();
950 struct scnhdr *sectHdr;
951 bool needsCont = false;
952 struct ld_info info[64];
954 ifd = open(imageFileName.string_of(), O_RDONLY, 0);
956 sprintf(errorLine, "Unable to open %s\n", outFile);
958 showErrorCallback(41, (const char *) errorLine);
963 rd = fstat(ifd, &statBuf);
966 sprintf(errorLine, "Unable to stat %s\n", outFile);
968 showErrorCallback(72, (const char *) errorLine);
971 length = statBuf.st_size;
972 sprintf(outFile, "%s.real", imageFileName.string_of());
973 sprintf(errorLine, "Saving program to %s\n", outFile);
976 ofd = open(outFile, O_WRONLY|O_CREAT, 0777);
982 /* read header and section headers */
983 cnt = read(ifd, &hdr, sizeof(struct filehdr));
984 if (cnt != sizeof(struct filehdr)) {
985 sprintf(errorLine, "Error reading header\n");
987 showErrorCallback(44, "");
991 cnt = read(ifd, &aout, sizeof(struct aouthdr));
993 sectHdr = (struct scnhdr *) calloc(sizeof(struct scnhdr), hdr.f_nscns);
994 cnt = read(ifd, sectHdr, sizeof(struct scnhdr) * hdr.f_nscns);
995 if ((unsigned) cnt != sizeof(struct scnhdr)* hdr.f_nscns) {
996 sprintf(errorLine, "Section headers\n");
1001 /* now copy the entire file */
1002 lseek(ofd, 0, SEEK_SET);
1003 lseek(ifd, 0, SEEK_SET);
1004 for (i=0; i < length; i += 4096) {
1005 rd = read(ifd, buffer, 4096);
1006 write(ofd, buffer, rd);
1011 // make sure it is stopped.
1012 findProcess(pid)->stop_();
1014 waitpid(pid, NULL, WUNTRACED);
1018 ret = ptrace(PT_LDINFO, pid, (int *) &info, sizeof(info), (int *) &info);
1020 statusLine("Unable to get loader info about process");
1021 showErrorCallback(43, "Unable to get loader info about process");
1025 baseAddr = (unsigned)info[0].ldinfo_textorg + (unsigned)aout.text_start;
1026 sprintf(errorLine, "seeking to %ld as the offset of the text segment \n",
1029 sprintf(errorLine, "Code offset = %d\n", baseAddr);
1032 /* seek to the text segment */
1033 lseek(ofd, aout.text_start, SEEK_SET);
1034 for (i=0; i < aout.tsize; i+= 1024) {
1036 length = ((i + 1024) < aout.tsize) ? 1024 : aout.tsize -i;
1037 ptrace(PT_READ_BLOCK, pid, (int*) (baseAddr + i), length, (int *)buffer);
1042 write(ofd, buffer, length);
1046 ptrace(PT_CONTINUE, pid, (int*) 1, SIGCONT, 0);
1056 // Seek to the desired offset and read the passed length of the file
1057 // into dest. If any errors are detected, log a message and return false.
1059 bool seekAndRead(int fd, int offset, void **dest, int length, bool allocate)
1064 *dest = malloc(length);
1068 sprintf(errorLine, "Unable to parse executable file\n");
1070 showErrorCallback(42, (const char *) errorLine);
1074 cnt = lseek(fd, offset, SEEK_SET);
1075 if (cnt != offset) {
1076 sprintf(errorLine, "Unable to parse executable file\n");
1078 showErrorCallback(42, (const char *) errorLine);
1081 cnt = read(fd, *dest, length);
1082 if (cnt != length) {
1083 sprintf(errorLine, "Unable to parse executable file\n");
1085 showErrorCallback(42, (const char *) errorLine);
1091 void Object::load_object()
1104 struct aouthdr aout;
1105 union auxent *csect;
1106 char *stringPool=NULL;
1107 bool newModule = false;
1108 Symbol::SymbolType type;
1109 int *lengthPtr = &poolLength;
1110 struct syment *symbols = NULL;
1111 struct scnhdr *sectHdr = NULL;
1112 Symbol::SymbolLinkage linkage;
1113 unsigned toc_offset = 0;
1115 fd = open(file_.string_of(), O_RDONLY, 0);
1117 sprintf(errorLine, "Unable to open executable file %s\n",
1119 statusLine(errorLine);
1120 showErrorCallback(27,(const char *) errorLine);
1124 cnt = read(fd, &hdr, sizeof(struct filehdr));
1125 if (cnt != sizeof(struct filehdr)) {
1126 sprintf(errorLine, "Error reading executable file %s\n",
1128 statusLine(errorLine);
1129 showErrorCallback(49,(const char *) errorLine);
1133 cnt = read(fd, &aout, sizeof(struct aouthdr));
1134 if (cnt != sizeof(struct aouthdr)) {
1135 sprintf(errorLine, "Error reading executable file %s\n",
1137 statusLine(errorLine);
1138 showErrorCallback(49,(const char *) errorLine);
1142 sectHdr = (struct scnhdr *) malloc(sizeof(struct scnhdr) * hdr.f_nscns);
1144 cnt = read(fd, sectHdr, sizeof(struct scnhdr) * hdr.f_nscns);
1145 if ((unsigned) cnt != sizeof(struct scnhdr)* hdr.f_nscns) {
1146 sprintf(errorLine, "Error reading executable file %s\n",
1148 statusLine(errorLine);
1149 showErrorCallback(49,(const char *) errorLine);
1153 // fprintf(stderr, "symbol table has %d entries starting at %d\n",
1154 // (int) hdr.f_nsyms, (int) hdr.f_symptr);
1156 if (!seekAndRead(fd, hdr.f_symptr, (void**) &symbols,
1157 hdr.f_nsyms * SYMESZ, true)) {
1162 * Get the string pool
1164 poolOffset = hdr.f_symptr + hdr.f_nsyms * SYMESZ;
1165 /* length is stored in the first 4 bytes of the string pool */
1166 if (!seekAndRead(fd, poolOffset, (void**) &lengthPtr, sizeof(int), false)) {
1170 if (!seekAndRead(fd, poolOffset, (void**) &stringPool, poolLength, true)) {
1174 // identify the code region.
1175 if ((unsigned) aout.tsize != sectHdr[aout.o_sntext-1].s_size) {
1176 // consistantcy check failed!!!!
1178 "Executable header file internal error: text segment size %s\n",
1180 statusLine(errorLine);
1181 showErrorCallback(45,(const char *) errorLine);
1185 if (!seekAndRead(fd, sectHdr[aout.o_sntext-1].s_scnptr,
1186 (void **) &code_ptr_, aout.tsize, true)) {
1190 //code_off_ = aout.text_start + AIX_TEXT_OFFSET_HACK; (OLD, pre-4.1)
1191 code_off_ = aout.text_start;
1192 if (aout.text_start < TEXTORG) {
1193 code_off_ += AIX_TEXT_OFFSET_HACK;
1195 AIX_TEXT_OFFSET_HACK = 0;
1199 // fprintf(stderr, "reading code starting at %x\n", code_off_);
1201 code_len_ = aout.tsize;
1203 // now the init data segment.
1204 if ((unsigned) aout.dsize != sectHdr[aout.o_sndata-1].s_size) {
1205 // consistantcy check failed!!!!
1207 "Executable header file interal error: data segment size %s\n",
1209 statusLine(errorLine);
1210 showErrorCallback(45,(const char *) errorLine);
1213 if (!seekAndRead(fd, sectHdr[aout.o_sndata-1].s_scnptr,
1214 (void **) &data_ptr_, aout.dsize, true)) {
1218 // data_off_ = sectHdr[aout.o_sndata-1].s_vaddr + AIX_DATA_OFFSET_HACK;
1220 data_off_ = aout.data_start;
1221 if (aout.data_start < DATAORG) {
1222 data_off_ += AIX_DATA_OFFSET_HACK;
1224 AIX_DATA_OFFSET_HACK = 0;
1227 data_len_ = aout.dsize;
1229 for (i=0; i < hdr.f_nsyms; i++) {
1230 /* do the pointer addition by hand since sizeof(struct syment)
1231 * seems to be 20 not 18 as it should be */
1232 sym = (struct syment *) (((unsigned) symbols) + i * SYMESZ);
1233 if (!(sym->n_sclass & DBXMASK)) {
1234 if ((sym->n_sclass == C_HIDEXT) ||
1235 (sym->n_sclass == C_EXT) ||
1236 (sym->n_sclass == C_FILE)) {
1237 if (!sym->n_zeroes) {
1238 name = string(&stringPool[sym->n_offset]);
1241 memset(tempName, 0, 9);
1242 strncpy(tempName, sym->n_name, 8);
1243 name = string(tempName);
1247 if ((sym->n_sclass == C_HIDEXT) || (sym->n_sclass == C_EXT)) {
1248 if (sym->n_sclass == C_HIDEXT) {
1249 linkage = Symbol::SL_LOCAL;
1251 linkage = Symbol::SL_GLOBAL;
1254 if (sym->n_scnum == aout.o_sntext) {
1255 type = Symbol::PDST_FUNCTION;
1256 // XXX - Hack for AIX loader.
1257 value = sym->n_value + AIX_TEXT_OFFSET_HACK;
1260 csect = (union auxent *)
1261 ((char *) sym + sym->n_numaux * SYMESZ);
1263 if (csect->x_csect.x_smclas == XMC_TC0) {
1265 logLine("Found more than one XMC_TC0 entry.");
1266 toc_offset = sym->n_value;
1270 if ((csect->x_csect.x_smclas == XMC_TC) ||
1271 (csect->x_csect.x_smclas == XMC_DS)) {
1272 // table of contents related entry not a real symbol.
1275 type = Symbol::PDST_OBJECT;
1276 // XXX - Hack for AIX loader.
1277 value = sym->n_value + AIX_DATA_OFFSET_HACK;
1282 // modules are defined multiple times for xlf Fortran.
1283 if (symbols_.defines(module)) {
1284 Symbol &oldValue = symbols_[module];
1285 // symbols should be in assending order.
1286 if (oldValue.addr() > value) {
1287 logLine("Symbol table out of order, use -Xlinker -bnoobjreorder");
1288 showErrorCallback(48, "");
1292 symbols_[module] = Symbol(module, module,
1293 Symbol::PDST_MODULE, linkage, value, false);
1298 // skip .text entries
1299 if (name == ".text") continue;
1300 if (name.prefixed_by(".")) {
1301 // XXXX - Hack to make names match assumptions of symtab.C
1303 //sprintf(temp, "_%s", &name.string_of()[1]);
1305 sprintf(temp, "%s", &name.string_of()[1]);
1306 name = string(temp);
1307 } else if (type == Symbol::PDST_FUNCTION) {
1308 // text segment without a leady . is a toc item
1312 //fprintf(stderr, "Found symbol %s in (%s) at %x\n",
1313 // name.string_of(), module.string_of(), value);
1314 symbols_[name] = Symbol(name, module, type, linkage,
1316 } else if (sym->n_sclass == C_FILE) {
1317 if (!strcmp(name.string_of(), ".file")) {
1319 /* has aux record with additional information. */
1320 for (j=1; j <= sym->n_numaux; j++) {
1321 aux = (union auxent *) ((char *) sym + j * SYMESZ);
1322 if (aux->x_file._x.x_ftype == XFT_FN) {
1323 // this aux record contains the file name.
1324 if (!aux->x_file._x.x_zeroes) {
1326 string(&stringPool[aux->x_file._x.x_offset]);
1328 // x_fname is 14 bytes
1330 memset(tempName, 0, 15);
1331 strncpy(tempName, aux->x_file.x_fname, 14);
1332 name = string(tempName);
1337 // fprintf(stderr, "Found module %s\n", name.string_of());
1338 // mark it to be added, but don't add it until the next symbol
1339 // tells us the address.
1347 // cout << "The value of TOC is: " << toc_offset << endl;
1348 //extern void initTocOffset(int);
1349 //initTocOffset(toc_offset);
1350 // this value is now defined per object. toc_offset_ is a private member
1351 // of class Object in Object-aix.h - naim
1352 toc_offset_ = toc_offset;
1356 if (sectHdr) free(sectHdr);
1357 if (stringPool) free(stringPool);
1358 if (symbols) free(symbols);
1364 Object::Object(const string file, void (*err_func)(const char *))
1365 : AObject(file, err_func) {
1369 Object::Object(const Object& obj)
1374 // for shared object files: not currently implemented
1375 // this should call a load_shared_object routine to parse the shared obj. file
1376 Object::Object(const string file,u_int,void (*err_func)(const char *))
1377 : AObject(file, err_func) {
1381 Object::~Object() { }
1383 Object& Object::operator=(const Object& obj) {
1384 (void) AObject::operator=(obj);
1389 // Verify that that program is statically linked, and establish the text
1390 // and data segments starting addresses.
1392 bool establishBaseAddrs(int pid, int &status, bool waitForTrap)
1395 struct ld_info *ptr;
1396 struct ld_info info[64];
1398 // check that the program was loaded at the correct address.
1400 // wait for the TRAP point.
1402 waitpid(pid, &status, WUNTRACED);
1404 /* It seems that AIX has some timing problems and
1405 when the user stack grows, the kernel doesn't update the stack info in time
1406 and ptrace calls step on user stack. This is the reason why call sleep
1407 here, giving the kernel some time to update its internals. */
1410 ret = ptrace(PT_LDINFO, pid, (int *) &info, sizeof(info), (int *) &info);
1412 statusLine("Unable to get loader info about process, application aborted");
1413 showErrorCallback(43, "Unable to get loader info about process, application aborted");
1418 if (ptr->ldinfo_next) {
1419 statusLine("ERROR: program not statically linked");
1420 logLine("ERROR: program not statically linked");
1421 showErrorCallback(46, "Program not statically linked");
1426 AIX_TEXT_OFFSET_HACK = (unsigned) ptr->ldinfo_textorg + 0x200;
1427 AIX_DATA_OFFSET_HACK = (unsigned) ptr->ldinfo_dataorg;
1429 ptrace(PT_MULTI, pid, 0, 1, 0);
1435 // dummy versions of OS statistics.
1437 float OS::compute_rusage_cpu() { return(0.0); }
1438 float OS::compute_rusage_sys() { return(0.0); }
1439 float OS::compute_rusage_min() { return(0.0); }
1440 float OS::compute_rusage_maj() { return(0.0); }
1441 float OS::compute_rusage_swap() { return(0.0); }
1442 float OS::compute_rusage_io_in() { return(0.0); }
1443 float OS::compute_rusage_io_out() { return(0.0); }
1444 float OS::compute_rusage_msg_send() { return(0.0); }
1445 float OS::compute_rusage_sigs() { return(0.0); }
1446 float OS::compute_rusage_vol_cs() { return(0.0); }
1447 float OS::compute_rusage_inv_cs() { return(0.0); }
1448 float OS::compute_rusage_msg_recv() { return(0.0); }
1450 int getNumberOfCPUs()
1455 // #include "paradynd/src/metric.h"
1456 // #include "paradynd/src/costmetrics.h"
1460 // the following MUST become process member vrbles, since paradynd can have
1461 // more than one process active doing a fork!!!
1462 static bool seenForkTrapForParent = false;
1463 static bool seenForkTrapForChild = false;
1464 static pid_t pidForParent;
1465 static pid_t pidForChild;
1467 extern bool completeTheFork(process *, int);
1468 // in inst-power.C since class instPoint is too
1470 static void process_whenBothForkTrapsReceived() {
1471 assert(seenForkTrapForParent);
1472 assert(seenForkTrapForChild);
1474 forkexec_cerr << "welcome to: process_whenBothForkTrapsReceived" << endl;
1476 process *parent = findProcess(pidForParent);
1479 // complete the fork!
1481 forkexec_cerr << "calling completeTheFork" << endl;
1483 if (!completeTheFork(parent, pidForChild))
1486 // let's continue both processes
1488 if (!parent->continueProc())
1491 // Note that we use PT_CONTINUE on the child instead of kill(pid, SIGSTOP).
1492 // Is this right? (I think so)
1494 // int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, 0, 0);
1495 int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, SIGCONT, 0);
1499 seenForkTrapForParent = seenForkTrapForChild = false;
1501 forkexec_cerr << "leaving process_whenBothForkTrapsReceived (parent & "
1502 << "child running and should execute DYNINSTfork soon)"
1506 //////////////////////////////////////////////////////////////////////////
1507 //Restore the base trampolines after they have been cleared by an AIX load
1509 void resurrectBaseTramps(process *p)
1513 vector<const instPoint*> allInstPoints = p->baseMap.keys();
1515 extern void findAndReinstallBaseTramps(process *, vector<const instPoint*> &);
1516 findAndReinstallBaseTramps(p, allInstPoints);
1518 vector<instInstance*> allInstInstances; //Get all mini trampolines
1519 getAllInstInstancesForProcess(p, allInstInstances);
1521 extern void reattachMiniTramps(process *, vector<instInstance*> &);
1522 reattachMiniTramps(p, allInstInstances);
1526 bool handleAIXsigTraps(int pid, int status) {
1527 process *curr = findProcess(pid); // NULL for child of a fork
1529 // see man page for "waitpid" et al for descriptions of constants such
1530 // as W_SLWTED, W_SFWTED, etc.
1532 if (WIFSTOPPED(status) && (WSTOPSIG(status)==SIGTRAP)
1533 && ((status & 0x7f) == W_SLWTED)) {
1534 //Process is stopped on a load. AIX has reloaded the process image and
1535 // the text segment heap has been cleared.
1537 curr->status_ = stopped;
1538 //fprintf(stderr, "Got load SIGTRAP from pid %d, PC=%x\n", pid,
1539 // curr->currentPC());
1540 resurrectBaseTramps(curr); //Restore base trampolines
1541 curr->continueProc();
1544 } // W_SLWTED (stopped-on-load)
1546 // On AIX the processes will get a SIGTRAP when they execute a fork.
1547 // (Both the parent and the child will get this TRAP).
1548 // we must check for the SIGTRAP here, and handle the fork.
1549 // On aix the instrumentation on the parent will not be duplicated on
1550 // the child, so we need to insert instrumentation again.
1552 if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP
1553 && ((status & 0x7f) == W_SFWTED)) {
1555 // parent process. Stay stopped until the child process has completed
1556 // calling "completeTheFork()".
1557 forkexec_cerr << "AIX: got fork SIGTRAP from parent process " << pid << endl;
1559 curr->status_ = stopped;
1561 seenForkTrapForParent = true;
1562 pidForParent = curr->getPid();
1564 if (seenForkTrapForChild)
1565 process_whenBothForkTrapsReceived();
1570 forkexec_cerr << "AIX: got SIGTRAP from forked (child) process " << pid << endl;
1573 struct procsinfo psinfo;
1574 pid_t process_pid = pid;
1575 if (getprocs(&psinfo, sizeof(psinfo), NULL, 0, &process_pid, 1) == -1) {
1580 assert((pid_t)psinfo.pi_pid == pid);
1582 //string str = string("Parent of process ") + string(pid) + " is " +
1583 // string(psinfo.pi_ppid) + "\n";
1584 //logLine(str.string_of());
1586 seenForkTrapForChild = true;
1588 if (seenForkTrapForParent) {
1589 assert((pid_t) pidForParent == (pid_t) psinfo.pi_ppid);
1591 process_whenBothForkTrapsReceived();
1596 } // W_SFWTED (stopped-on-fork)
1601 string process::tryToFindExecutable(const string &progpath, int pid) {
1602 // returns empty string on failure
1604 if (progpath.length() == 0)
1607 if (exists_executable(progpath)) // util lib
1610 return ""; // failure
1613 unsigned process::read_inferiorRPC_result_register(reg returnValReg) {
1614 assert(false); // not yet implemented!!!
1618 bool process::set_breakpoint_for_syscall_completion() {
1619 // We don't know how to do this on AIX
1623 vector<int> process::getTOCoffsetInfo() const
1626 toc_offset = ((getImage())->getObject()).getTOCoffset();
1628 // st r2,20(r1) ; 0x90410014 save toc register
1629 dummy += 0x90410014;
1631 // liu r2, 0x0000 ;0x3c40abcd reset the toc value to 0xabcdefgh
1632 dummy += (0x3c400000 | (toc_offset >> 16));
1634 // oril r2, r2,0x0000 ;0x6042efgh
1635 dummy += (0x60420000 | (toc_offset & 0x0000ffff));