removed log within file, which wasn't being updated anyway.
[dyninst.git] / dyninstAPI / src / aix.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 #include "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"
52
53 #include <sys/ioctl.h>
54 #include <sys/types.h>
55 #include <fcntl.h>
56 #include <assert.h>
57 #include <stdlib.h>
58 #include <fcntl.h>
59 #include <unistd.h>
60 #include <stdio.h>
61 #include <string.h>
62 #include <xcoff.h>
63 #include <scnhdr.h>
64 #include <sys/time.h>
65 #include <sys/reg.h>
66 #include <sys/user.h>
67 #include <sys/wait.h>
68 #include <sys/ptrace.h>
69 #include <procinfo.h> // struct procsinfo
70 #include <sys/types.h>
71
72 #include "paradynd/src/showerror.h"
73 #include "util/h/debugOstream.h"
74
75 extern "C" {
76 extern int ioctl(int, int, ...);
77 };
78
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;
85
86 extern process* findProcess(int);
87
88 unsigned AIX_TEXT_OFFSET_HACK;
89 unsigned AIX_DATA_OFFSET_HACK;
90
91 class ptraceKludge {
92 public:
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);
97 };
98
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";
104       assert(0);
105     }
106   }
107   return wasStopped;
108 }
109
110 // what is the top most frame.
111 static int firstFrame;
112
113 //
114 // returns the current frame pointer (fp) and program counter (pc). 
115 // returns true if we are able to read the registers.
116 //
117 bool process::getActiveFrame(int *fp, int *pc)
118 {
119     int sp;
120     bool ret;
121     int dummy;
122
123     errno = 0;
124     sp = P_ptrace(PT_READ_GPR, pid, (int *) STKP, 0, 0); // aix 4.1 likes int *
125     if (errno != 0) return false;
126
127     errno = 0;
128     *pc = P_ptrace(PT_READ_GPR, pid, (int *) IAR, 0, 0); // aix 4.1 likes int *
129     if (errno != 0) return false;
130
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);
136     firstFrame = *fp;
137
138     return(ret);
139 }
140
141 bool process::needToAddALeafFrame(Frame,unsigned int &){
142     return false;
143 }
144
145
146 //
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.
152 //
153 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool /*uppermost*/)
154 {
155     //
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
159     //
160     struct {
161         unsigned oldFp;
162         unsigned savedCR;
163         unsigned savedLR;
164         unsigned compilerInfo;
165         unsigned binderInfo;
166         unsigned savedTOC;
167     } linkArea;
168
169     if (readDataSpace((caddr_t) currentFP, 
170                       sizeof(linkArea), 
171                       (caddr_t) &linkArea,
172                       false)) {
173         *fp = linkArea.oldFp;
174         *rtn = linkArea.savedLR;
175
176         if (currentFP == firstFrame) {
177             // use the value stored in the link register instead.
178             errno = 0;
179             *rtn = P_ptrace(PT_READ_GPR, pid, (int *)LR, 0, 0); // aix 4.1 likes int *
180             if (errno != 0) return false;
181         }
182         return true;
183     } else {
184         return false;
185     }
186 }
187
188 void *process::getRegisters() {
189    // assumes the process is stopped (ptrace requires it)
190    assert(status_ == stopped);
191
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)
203    // TID
204    // FPSCR (fp status)
205    // FPINFO (fp info) [no, out of range of what ptrace can access (why?)]
206    // FPSCRX (fp sreg ext.) [no, out of range, too]
207    
208    void *buffer = new char[num_bytes];
209    assert(buffer);
210
211    unsigned *bufferPtr = (unsigned *)buffer;
212
213    // First, the general-purpose integer registers:
214
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'
222    // Errors:
223    //    EIO --> 3d arg didn't specify a valid register (must be 0-31 or 128-136)
224
225    for (unsigned i=0; i < 32; i++) {
226       errno = 0;
227       unsigned value = P_ptrace(PT_READ_GPR, pid, (void *)i, 0, 0);
228       if (errno != 0) {
229          perror("ptrace PT_READ_GPR");
230          cerr << "regnum was " << i << endl;
231          return NULL;
232       }
233
234       *bufferPtr++ = value;
235    }
236
237    // Next, the general purpose floating point registers.
238
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.
248
249    for (unsigned i=0; i < 32; i++) {
250       double value;
251       assert(sizeof(double)==8); // make sure it's big enough!
252
253       errno = 0;
254       P_ptrace(PT_READ_FPR, pid, &value,
255                FPR0 + i, // see <sys/reg.h>
256                0);
257       if (errno != 0) {
258          perror("ptrace PT_READ_FPR");
259          cerr << "regnum was " << FPR0 + i << "; FPR0=" << FPR0 << endl;
260          return NULL;
261       }
262
263       memcpy(bufferPtr, &value, sizeof(value));
264
265       unsigned *oldBufferPtr = bufferPtr;
266       bufferPtr += 2; // 2 unsigned's --> 8 bytes
267       assert((char*)bufferPtr - (char*)oldBufferPtr == 8); // just for fun
268
269       assert(2*sizeof(unsigned) == 8);
270    }
271
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;
278
279    for (unsigned i=0; i < num_special_registers; i++) {
280       errno = 0;
281       unsigned value = P_ptrace(PT_READ_GPR, pid, (void *)special_register_codenums[i], 0, 0);
282       if (errno != 0) {
283          perror("ptrace PT_READ_GPR for a special register");
284          cerr << "regnum was " << special_register_codenums[i] << endl;
285          return NULL;
286       }
287
288       *bufferPtr++ = value;
289    }
290
291    assert((unsigned)bufferPtr - (unsigned)buffer == num_bytes);
292
293    // Whew, finally done.
294    return buffer;
295 }
296
297 static bool executeDummyTrap(process *theProc) {
298    assert(theProc->status_ == stopped);
299    
300    unsigned tempTramp = inferiorMalloc(theProc, 8, textHeap);
301    assert(tempTramp);
302
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;
308       return false;
309    }
310
311    // Okay, the temp tramp has been set up.  Let's set the PC there
312    errno = 0;
313    unsigned oldpc = P_ptrace(PT_READ_GPR, theProc->getPid(), (void *)IAR, 0, 0);
314    assert(errno == 0);
315
316    errno = 0;
317    P_ptrace(PT_WRITE_GPR, theProc->getPid(), (void *)IAR, tempTramp, 0);
318    assert(errno == 0);
319
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;
322       return false;
323    }
324
325    // We bypass continueProc() because continueProc() changes theProc->status_, which
326    // we don't want to do here
327    errno = 0;
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
330       // them now?
331    assert(errno == 0);
332
333 while (true) {
334    int status, pid;
335    do {
336 //      cerr << "doing a wait" << endl; cerr.flush();
337       pid = waitpid(theProc->getPid(), &status, WUNTRACED);
338       if (pid == 0)
339          cerr << "waitpid returned special case of 0 (?)" << endl;
340       else if (pid == -1) {
341          if (errno == ECHILD)
342             // the child has died
343             assert(false);
344          else
345             perror("executeDummyTrap waitpid()");
346       }
347       else {
348 //       cerr << "waitpid result was " << pid << endl;
349 //       if (pid == theProc->getPid())
350 //          cerr << "which was the pid, as expected" << endl;
351       }
352
353 //      cerr << "did a wait" << endl; cerr.flush();
354    } while (pid != theProc->getPid());
355
356    if (WIFEXITED(status))
357       // the child died
358       assert(false);
359
360    assert(WIFSTOPPED(status));
361
362    int sig = WSTOPSIG(status);
363    if (sig == SIGTRAP) {
364 #ifdef INFERIOR_RPC_DEBUG
365       cerr << "executeDummyTrap: got SIGTRAP, as expected!" << endl;
366 #endif
367       break;
368    }
369    else {
370       // handle an 'ordinary' signal, e.g. SIGALRM
371 #ifdef INFERIOR_RPC_DEBUG
372       cerr << "executeDummyTrap: got unexpected signal " << sig << "...ignoring" << endl;
373 #endif
374
375       // We bypass continueProc() because continueProc() changes theProc->status_, which
376       // we don't want to do here
377       errno = 0;
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
380          // them now?
381       assert(errno == 0);
382
383 //      extern int handleSigChild(int, int);
384 //      (void)handleSigChild(pid, status);
385    }
386 }
387
388    // Restore the old PC register value
389    errno = 0;
390    P_ptrace(PT_WRITE_GPR, theProc->getPid(), (void *)IAR, oldpc, 0);
391    assert(errno == 0);
392
393    // delete the temp tramp now (not yet implemented)
394
395 #ifdef INFERIOR_RPC_DEBUG
396    cerr << "leaving executeDummyTrap now" << endl;
397    cerr.flush();
398 #endif
399
400    return true;
401 }
402
403 bool process::executingSystemCall() {
404    // this is not implemented yet - naim 5/15/97
405    return false;
406 }
407
408 bool process::changePC(unsigned loc) {
409    return changePC(loc, NULL);
410 }
411
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.
416
417    // Format of PT_WRITE_GPR call:
418    // 3d param ('address'): the register to modify
419    // 4th param ('data'): the value to store
420    // 5th param ignored
421    // Returns -1 on failure; else, returns the 'data' parameter
422    // Errors:
423    //    EIO: 3d param not a valid register; must be 0-31 or 128-136
424
425 #ifdef INFERIOR_RPC_DEBUG
426    cerr << "welcome to changePC with loc=" << (void *)loc << endl;
427 #endif
428
429 // gdb hack: execute 1 dummy insn
430 #ifdef INFERIOR_RPC_DEBUG
431    cerr << "changePC: about to exec dummy trap" << endl;
432 #endif
433    if (!executeDummyTrap(this)) {
434       cerr << "changePC failed because executeDummyTrap failed" << endl;
435       return false;
436    }
437
438    errno = 0;
439    P_ptrace(PT_WRITE_GPR, pid, (void *)IAR, loc, 0);
440    if (errno) {
441       perror("changePC (PT_WRITE_GPR) failed");
442       return false;
443    }
444
445    // Double-check that the change was made by reading the IAR register
446    errno = 0;
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;
449       return false;
450    }
451    assert(errno == 0);
452
453    return true;
454 }
455
456 bool process::restoreRegisters(void *buffer) {
457    // assumes process is stopped (ptrace requires it)
458    assert(status_ == stopped);
459
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?
467
468    unsigned *bufferPtr = (unsigned *)buffer;
469
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.
476    // Errors:
477    //    EIO: address must be 0-31 or 128-136
478
479    for (unsigned i=GPR0; i <= GPR31; i++) {
480       errno = 0;
481       P_ptrace(PT_WRITE_GPR, pid, (void *)i, *bufferPtr++, 0);
482       if (errno) {
483          perror("ptrace PT_WRITE_GPR");
484          cerr << "regnum was " << i << endl;
485          return false;
486       }
487    } 
488
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)
494    // 5th param ignored
495    // returns -1 on error
496    // Errors:
497    //    EIO: reg num must be 256-287
498
499    for (unsigned i=FPR0; i <= FPR31; i++) {
500       errno = 0;
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.
504       if (errno != 0) {
505          perror("ptrace PT_WRITE_FPR");
506          cerr << "regnum was " << i << endl;
507          return false;
508       }
509
510       const unsigned *oldBufferPtr = bufferPtr;
511       bufferPtr += 2; // 2 unsigned's == 8 bytes
512       assert((unsigned)bufferPtr - (unsigned)oldBufferPtr == 8); // just for fun
513    } 
514
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;
521
522    for (unsigned i=0; i < num_special_registers; i++) {
523       errno = 0;
524       P_ptrace(PT_WRITE_GPR, pid, (void *)(special_register_codenums[i]), *bufferPtr++, 0);
525       if (errno != 0) {
526          perror("ptrace PT_WRITE_GPR for a special register");
527          cerr << "regnum was " << special_register_codenums[i] << endl;
528          return false;
529       }
530    }
531
532    return true; // success
533 }
534
535
536 bool process::emitInferiorRPCheader(void *insnPtr, unsigned &baseBytes) {
537    // TODO: write me!
538    instruction *insn = (instruction *)insnPtr;
539    unsigned baseInstruc = baseBytes / sizeof(instruction);
540
541 //   extern void generateBreakPoint(instruction &);
542 //   generateBreakPoint(insn[baseInstruc++]);
543 //   extern void generateIllegalInsn(instruction &);
544 //   generateIllegalInsn(insn[baseInstruc++]); 
545
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);
551
552    // Convert back:
553    baseBytes = baseInstruc * sizeof(instruction);
554
555    return true;
556 }
557
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,
562                                      bool stopForResult,
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.
567
568    instruction *insn = (instruction *)insnPtr;
569    unsigned baseInstruc = baseBytes / sizeof(instruction);
570
571    extern void generateBreakPoint(instruction &);
572
573    if (stopForResult) {
574       generateBreakPoint(insn[baseInstruc]);
575       stopForResultOffset = baseInstruc * sizeof(instruction);
576       baseInstruc++;
577
578       justAfter_stopForResultOffset = baseInstruc * sizeof(instruction);
579    }
580
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);
585
586    // Trap instruction (breakpoint):
587    generateBreakPoint(insn[baseInstruc]);
588    breakOffset = baseInstruc * sizeof(instruction);
589    baseInstruc++;
590
591    // And just to make sure that we don't continue, we put an illegal
592    // insn here:
593    extern void generateIllegalInsn(instruction &);
594    generateIllegalInsn(insn[baseInstruc++]);
595
596    baseBytes = baseInstruc * sizeof(instruction); // convert back
597
598    return true;
599 }
600
601 bool ptraceKludge::deliverPtrace(process *p, int req, void *addr,
602                                  int data, void *addr2) {
603   bool halted;
604   bool ret;
605   
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 *
608     ret = false;
609   else
610     ret = true;
611   if (req != PT_DETACH) continueProcess(p, halted);
612   return ret;
613 }
614
615 void ptraceKludge::continueProcess(process *p, const bool wasStopped) {
616   if ((p->status() != neonatal) && (!wasStopped)) {
617
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_
620  */
621
622 #ifndef PTRACE_ATTACH_DETACH
623     if (ptrace(PT_CONTINUE, p->pid, (int *) 1, SIGCONT, NULL) == -1) {
624 #else
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 *
628 #endif
629       logLine("Error in continueProcess\n");
630       assert(0);
631     }
632   }
633 }
634
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); 
640   close (ttyfd);
641 }
642
643 bool process::stop_() {
644 /* Choose either one of the following methods for stopping a process, 
645  * but not both. 
646  * The choice must be consistent with that in process::continueProc_ 
647  * and ptraceKludge::continueProcess
648  */
649 #ifndef PTRACE_ATTACH_DETACH
650         return (P_kill(pid, SIGSTOP) != -1); 
651 #else
652         // attach generates a SIG TRAP which we catch
653         if (!attach_()) {
654           if (kill(pid, SIGSTOP) == -1)
655              return false;
656         }
657         return(true);
658 #endif
659 }
660
661 bool process::continueWithForwardSignal(int sig) {
662 #if defined(PTRACE_ATTACH_DETACH)
663   if (sig != 0) {
664       ptrace(PT_DETACH, pid, (int*)1, stat, 0);
665       return (true);
666   } else {
667       return (ptrace(PT_CONTINUE, pid, (int*)1, 0, 0) != -1);
668   }
669 #else
670   return (ptrace(PT_CONTINUE, pid, (int*)1, sig, NULL) != -1);
671 #endif
672 }
673
674 void OS::osTraceMe(void)
675 {
676   int ret;
677
678   ret = ptrace(PT_TRACE_ME, 0, 0, 0, 0);
679   assert(ret != -1);
680 }
681
682
683 // wait for a process to terminate or stop
684 int process::waitProcs(int *status) {
685   return waitpid(0, status, WNOHANG);
686 }
687
688
689 // attach to an inferior process.
690 bool process::attach() {
691   // we only need to attach to a process that is not our direct children.
692   if (parent != 0) {
693     return attach_();
694   }
695   else
696     return true;
697 }
698
699 bool process::attach_() {
700    // formerly OS::osAttach()
701    int ret = ptrace(PT_ATTACH, getPid(), (int *)0, 0, 0);
702    if (ret == -1)
703       ret = ptrace(PT_REATT, getPid(), (int *)0, 0, 0);
704
705    return (ret != -1);
706 }
707
708 bool process::isRunning_() const {
709    // determine if a process is running by doing low-level system checks, as
710    // opposed to checking the 'status_' member vrble.  May assume that attach()
711    // has run, but can't assume anything else.
712
713    assert(false); // not yet implemented!   
714 }
715
716 // TODO is this safe here ?
717 bool process::continueProc_() {
718   int ret;
719
720   if (!checkStatus()) 
721     return false;
722   ptraceOps++; ptraceOtherOps++;
723
724 /* Choose either one of the following methods to continue a process.
725  * The choice must be consistent with that in process::continueProc_ and stop_
726  */
727
728 #ifndef PTRACE_ATTACH_DETACH
729   if (!ptraceKludge::deliverPtrace(this, PT_CONTINUE, (char*)1, 0, NULL))
730     ret = -1;
731   else
732     ret = 0;
733   // switch these to not detach after every call.
734   //ret = ptrace(PT_CONTINUE, pid, (int *)1, 0, NULL);
735 #else
736   ret = ptrace(PT_DETACH, pid, (int *)1, 0, NULL);
737 #endif
738
739   return (ret != -1);
740 }
741
742 #ifdef BPATCH_LIBRARY
743 bool process::terminateProc_()
744 {
745   if (!checkStatus())
746     return false;
747
748   if (P_ptrace(PT_KILL, pid, NULL, NULL, NULL) != 0)
749     return false;
750   else
751     return true;
752 }
753 #endif
754
755 // TODO ??
756 bool process::pause_() {
757   if (!checkStatus()) 
758     return false;
759   ptraceOps++; ptraceOtherOps++;
760   bool wasStopped = (status() == stopped);
761   if (status() != neonatal && !wasStopped)
762     return (loopUntilStopped());
763   else
764     return true;
765 }
766
767 bool process::detach_() {
768   if (checkStatus()) {
769       ptraceOps++; ptraceOtherOps++;
770       if (!ptraceKludge::deliverPtrace(this,PT_DETACH,(char*)1,SIGSTOP, NULL))
771       {
772           sprintf(errorLine, "Unable to detach %d\n", getPid());
773           logLine(errorLine);
774           showErrorCallback(40, (const char *) errorLine);
775       }
776   }
777   // always return true since we report the error condition.
778   return (true);
779 }
780
781 #ifdef BPATCH_LIBRARY
782 bool process::API_detach_(const bool cont) {
783   if (!checkStatus())
784       return false;
785   ptraceOps++; ptraceOtherOps++;
786   return (ptraceKludge::deliverPtrace(this,PT_DETACH,(char*)1, cont ? 0 : SIGSTOP,NULL));
787 }
788 #endif
789
790 // temporarily unimplemented, PT_DUMPCORE is specific to sunos4.1
791 bool process::dumpCore_(const string /*coreFile*/) {
792   if (!checkStatus()) 
793     return false;
794   ptraceOps++; ptraceOtherOps++;
795
796   if (!dumpImage()) {
797 //  if (!OS::osDumpImage(symbols->file(), pid, symbols->codeOffset()))
798      assert(false);
799   }
800
801   errno = 0;
802   (void) ptrace(PT_CONTINUE, pid, (int*)1, SIGBUS, NULL);
803   assert(errno == 0);
804   return true;
805 }
806
807 bool process::writeTextWord_(caddr_t inTraced, int data) {
808   if (!checkStatus()) 
809     return false;
810   ptraceBytes += sizeof(int); ptraceOps++;
811   return (ptraceKludge::deliverPtrace(this, PT_WRITE_I, inTraced, data, NULL));
812 }
813
814 bool process::writeTextSpace_(void *inTraced, int amount, const void *inSelf) {
815   if (!checkStatus()) 
816     return false;
817   ptraceBytes += amount; ptraceOps++;
818   return (ptraceKludge::deliverPtrace(this, PT_WRITE_BLOCK, inTraced, 
819                                       amount, inSelf));
820 }
821
822 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
823 bool process::readTextSpace_(void *inTraced, int amount, const void *inSelf) {
824   if (!checkStatus())
825     return false;
826   ptraceOps++; ptraceBytes += amount;
827   return (ptraceKludge::deliverPtrace(this, PT_READ_BLOCK, inTraced, amount,
828                                       inSelf));
829 }
830 #endif
831
832 bool process::writeDataSpace_(void *inTraced, int amount, const void *inSelf) {
833   if (!checkStatus())
834     return false;
835
836   ptraceOps++; ptraceBytes += amount;
837
838   return (ptraceKludge::deliverPtrace(this, PT_WRITE_BLOCK, inTraced, amount, inSelf));
839 }
840
841 bool process::readDataSpace_(const void *inTraced, int amount, void *inSelf) {
842   if (!checkStatus())
843     return false;
844   ptraceOps++; ptraceBytes += amount;
845   return (ptraceKludge::deliverPtrace(this, PT_READ_BLOCK, inTraced, amount, inSelf));
846 }
847
848 bool process::loopUntilStopped() {
849   /* make sure the process is stopped in the eyes of ptrace */
850   stop_();     //Send the process a SIGSTOP
851
852   bool isStopped = false;
853   int waitStatus;
854   while (!isStopped) {
855     int ret = waitpid(pid, &waitStatus, WUNTRACED);
856     if ((ret == -1) && (errno == EINTR)) continue;
857     // these two ifs (ret==-1&&errno==ECHILD)||(WIF..) used to be together
858     // but had to seperate them, we were receiving ECHILD in a different
859     // situation, for some reason..
860     // if ((ret == -1 && errno == ECHILD) || (WIFEXITED(waitStatus))) {
861     if ((ret == -1) && (errno == ECHILD)) return true;
862     if(WIFEXITED(waitStatus)) {
863       // the child is gone.
864       //status_ = exited;
865       handleProcessExit(this, WEXITSTATUS(waitStatus));
866       return(false);
867     }
868     if (!WIFSTOPPED(waitStatus) && !WIFSIGNALED(waitStatus)) {
869       printf("problem stopping process\n");
870       return false;
871     }
872     int sig = WSTOPSIG(waitStatus);
873     if ((sig == SIGTRAP) || (sig == SIGSTOP) || (sig == SIGINT)) {
874       if (sig != SIGSTOP) { //Process already stopped, but not by our SIGSTOP
875         extern int handleSigChild(int, int);
876         if (handleSigChild(pid, waitStatus) < 0) 
877           cerr << "handleSigChild failed for pid " << pid << endl; 
878       } else {              //Process stopped by our SIGSTOP
879         isStopped = true;
880       }
881     } else {
882       if (ptrace(PT_CONTINUE, pid, (int*)1, sig, 0) == -1) {
883         logLine("Ptrace error in PT_CONTINUE, loopUntilStopped\n");
884         return false;
885       }
886     }
887   }
888
889   return true;
890 }
891
892
893 //
894 // Write out the current contents of the text segment to disk.  This is useful
895 //    for debugging dyninst.
896 //
897 bool process::dumpImage() {
898     // formerly OS::osDumpImage()
899     const string &imageFileName = symbols->file();
900     // const Address codeOff = symbols->codeOffset();
901
902     int i;
903     int rd;
904     int ifd;
905     int ofd;
906     int cnt;
907     int ret;
908     int total;
909     int length;
910     Address baseAddr;
911     extern int errno;
912     char buffer[4096];
913     char outFile[256];
914     struct filehdr hdr;
915     struct stat statBuf;
916     struct aouthdr aout;
917     struct scnhdr *sectHdr;
918     bool needsCont = false;
919     struct ld_info info[64];
920
921     ifd = open(imageFileName.string_of(), O_RDONLY, 0);
922     if (ifd < 0) {
923       sprintf(errorLine, "Unable to open %s\n", outFile);
924       logLine(errorLine);
925       showErrorCallback(41, (const char *) errorLine);
926       perror("open");
927       return true;
928     }
929
930     rd = fstat(ifd, &statBuf);
931     if (rd != 0) {
932       perror("fstat");
933       sprintf(errorLine, "Unable to stat %s\n", outFile);
934       logLine(errorLine);
935       showErrorCallback(72, (const char *) errorLine);
936       return true;
937     }
938     length = statBuf.st_size;
939     sprintf(outFile, "%s.real", imageFileName.string_of());
940     sprintf(errorLine, "Saving program to %s\n", outFile);
941     logLine(errorLine);
942
943     ofd = open(outFile, O_WRONLY|O_CREAT, 0777);
944     if (ofd < 0) {
945       perror("open");
946       exit(-1);
947     }
948
949     /* read header and section headers */
950     cnt = read(ifd, &hdr, sizeof(struct filehdr));
951     if (cnt != sizeof(struct filehdr)) {
952         sprintf(errorLine, "Error reading header\n");
953         logLine(errorLine);
954         showErrorCallback(44, "");
955         return false;
956     }
957
958     cnt = read(ifd, &aout, sizeof(struct aouthdr));
959
960     sectHdr = (struct scnhdr *) calloc(sizeof(struct scnhdr), hdr.f_nscns);
961     cnt = read(ifd, sectHdr, sizeof(struct scnhdr) * hdr.f_nscns);
962     if ((unsigned) cnt != sizeof(struct scnhdr)* hdr.f_nscns) {
963         sprintf(errorLine, "Section headers\n");
964         logLine(errorLine);
965         return false;
966     }
967
968     /* now copy the entire file */
969     lseek(ofd, 0, SEEK_SET);
970     lseek(ifd, 0, SEEK_SET);
971     for (i=0; i < length; i += 4096) {
972         rd = read(ifd, buffer, 4096);
973         write(ofd, buffer, rd);
974         total += rd;
975     }
976
977     if (!stopped) {
978         // make sure it is stopped.
979         findProcess(pid)->stop_();
980
981         waitpid(pid, NULL, WUNTRACED);
982         needsCont = true;
983     }
984
985     ret = ptrace(PT_LDINFO, pid, (int *) &info, sizeof(info), (int *) &info);
986     if (ret != 0) {
987         statusLine("Unable to get loader info about process");
988         showErrorCallback(43, "Unable to get loader info about process");
989         return false;
990     }
991
992     baseAddr = (unsigned)info[0].ldinfo_textorg + (unsigned)aout.text_start;
993     sprintf(errorLine, "seeking to %ld as the offset of the text segment \n",
994         aout.text_start);
995     logLine(errorLine);
996     sprintf(errorLine, "Code offset = %d\n", baseAddr);
997     logLine(errorLine);
998
999     /* seek to the text segment */
1000     lseek(ofd, aout.text_start, SEEK_SET);
1001     for (i=0; i < aout.tsize; i+= 1024) {
1002         errno = 0;
1003         length = ((i + 1024) < aout.tsize) ? 1024 : aout.tsize -i;
1004         ptrace(PT_READ_BLOCK, pid, (int*) (baseAddr + i), length, (int *)buffer);
1005         if (errno) {
1006             perror("ptrace");
1007             assert(0);
1008         }
1009         write(ofd, buffer, length);
1010     }
1011
1012     if (needsCont) {
1013         ptrace(PT_CONTINUE, pid, (int*) 1, SIGCONT, 0);
1014     }
1015
1016     close(ofd);
1017     close(ifd);
1018
1019     return true;
1020 }
1021
1022 //
1023 // Seek to the desired offset and read the passed length of the file
1024 //   into dest.  If any errors are detected, log a message and return false.
1025 //
1026 bool seekAndRead(int fd, int offset, void **dest, int length, bool allocate)
1027 {
1028     int cnt;
1029
1030     if (allocate) {
1031         *dest = malloc(length);
1032     }
1033
1034     if (!*dest) {
1035         sprintf(errorLine, "Unable to parse executable file\n");
1036         logLine(errorLine);
1037         showErrorCallback(42, (const char *) errorLine);
1038         return false;
1039     }
1040
1041     cnt = lseek(fd, offset, SEEK_SET);
1042     if (cnt != offset) {
1043         sprintf(errorLine, "Unable to parse executable file\n");
1044         logLine(errorLine);
1045         showErrorCallback(42, (const char *) errorLine);
1046         return false;
1047     }
1048     cnt = read(fd, *dest, length);
1049     if (cnt != length) {
1050         sprintf(errorLine, "Unable to parse executable file\n");
1051         logLine(errorLine);
1052         showErrorCallback(42, (const char *) errorLine);
1053         return false;
1054     }
1055     return true;
1056 }
1057
1058 unsigned long roundup4(unsigned long val) {
1059    while (val % 4 != 0)
1060       val++;
1061    return val;
1062 }
1063
1064 void Object::load_object()
1065 {
1066    // all these vrble declarations need to be up here due to the gotos,
1067    // which mustn't cross vrble initializations.  Too bad.
1068    long i;
1069    int fd;
1070    int cnt;
1071    string name;
1072    unsigned value;
1073    int poolOffset;
1074    int poolLength;
1075    union auxent *aux;
1076    struct filehdr hdr;
1077    struct syment *sym;
1078    struct aouthdr aout;
1079    union auxent *csect;
1080    char *stringPool=NULL;
1081    Symbol::SymbolType type; 
1082    int *lengthPtr = &poolLength;
1083    struct syment *symbols = NULL;
1084    struct scnhdr *sectHdr = NULL;
1085    Symbol::SymbolLinkage linkage;
1086    unsigned toc_offset = 0;
1087    string modName;
1088
1089    fd = open(file_.string_of(), O_RDONLY, 0);
1090    if (fd <0) {
1091       sprintf(errorLine, "Unable to open executable file %s\n", 
1092               file_.string_of());
1093       statusLine(errorLine);
1094       showErrorCallback(27,(const char *) errorLine);
1095       goto cleanup;
1096    }
1097
1098    cnt = read(fd, &hdr, sizeof(struct filehdr));
1099    if (cnt != sizeof(struct filehdr)) {
1100       sprintf(errorLine, "Error reading executable file %s\n", 
1101               file_.string_of());
1102       statusLine(errorLine);
1103       showErrorCallback(49,(const char *) errorLine);
1104       goto cleanup;
1105    }
1106
1107    cnt = read(fd, &aout, sizeof(struct aouthdr));
1108    if (cnt != sizeof(struct aouthdr)) {
1109       sprintf(errorLine, "Error reading executable file %s\n", 
1110               file_.string_of());
1111       statusLine(errorLine);
1112       showErrorCallback(49,(const char *) errorLine);
1113       goto cleanup;
1114    }
1115
1116    sectHdr = (struct scnhdr *) malloc(sizeof(struct scnhdr) * hdr.f_nscns);
1117    assert(sectHdr);
1118    cnt = read(fd, sectHdr, sizeof(struct scnhdr) * hdr.f_nscns);
1119    if ((unsigned) cnt != sizeof(struct scnhdr)* hdr.f_nscns) {
1120       sprintf(errorLine, "Error reading executable file %s\n", 
1121               file_.string_of());
1122       statusLine(errorLine);
1123       showErrorCallback(49,(const char *) errorLine);
1124       goto cleanup;
1125    }
1126
1127    // fprintf(stderr, "symbol table has %d entries starting at %d\n",
1128    //    (int) hdr.f_nsyms, (int) hdr.f_symptr);
1129
1130    if (!seekAndRead(fd, hdr.f_symptr, (void**) &symbols, 
1131                     hdr.f_nsyms * SYMESZ, true)) {
1132       goto cleanup;
1133    }
1134
1135    /*
1136     * Get the string pool
1137     */
1138    poolOffset = hdr.f_symptr + hdr.f_nsyms * SYMESZ;
1139    /* length is stored in the first 4 bytes of the string pool */
1140    if (!seekAndRead(fd, poolOffset, (void**) &lengthPtr, sizeof(int), false)) {
1141       goto cleanup;
1142    }
1143
1144    if (!seekAndRead(fd, poolOffset, (void**) &stringPool, poolLength, true)) {
1145       goto cleanup;
1146    }
1147
1148    // identify the code region.
1149    if ((unsigned) aout.tsize != sectHdr[aout.o_sntext-1].s_size) {
1150       // consistantcy check failed!!!!
1151       sprintf(errorLine, 
1152               "Executable header file internal error: text segment size %s\n", 
1153               file_.string_of());
1154       statusLine(errorLine);
1155       showErrorCallback(45,(const char *) errorLine);
1156       goto cleanup;
1157    }
1158
1159    if (!seekAndRead(fd, roundup4(sectHdr[aout.o_sntext-1].s_scnptr), 
1160                     (void **) &code_ptr_, aout.tsize, true)) {
1161       goto cleanup;
1162    }
1163
1164    //code_off_ =  aout.text_start + AIX_TEXT_OFFSET_HACK; (OLD, pre-4.1)
1165    code_off_ =  aout.text_start;
1166    if (aout.text_start < TEXTORG) {
1167       code_off_ += AIX_TEXT_OFFSET_HACK;
1168    } else {
1169       AIX_TEXT_OFFSET_HACK = 0;
1170    }
1171
1172    code_len_ = aout.tsize;
1173
1174    // now the init data segment (as opposed to .bss, the uninitialized data segment)
1175    if ((unsigned long) aout.dsize != sectHdr[aout.o_sndata-1].s_size) {
1176       // consistantcy check failed!!!!
1177       sprintf(errorLine, 
1178               "Executable header file interal error: data segment size %s\n", 
1179               file_.string_of());
1180       statusLine(errorLine);
1181       showErrorCallback(45,(const char *) errorLine);
1182       goto cleanup;
1183    }
1184    if (!seekAndRead(fd, roundup4(sectHdr[aout.o_sndata-1].s_scnptr), 
1185                     (void **) &data_ptr_, aout.dsize, true)) {
1186       cerr << "seekAndRead for initialized data section failed!" << endl;
1187       goto cleanup;
1188    }
1189
1190    // data_off_ = sectHdr[aout.o_sndata-1].s_vaddr + AIX_DATA_OFFSET_HACK; 
1191    // (OLD, pre-4.1)
1192    data_off_ = aout.data_start;
1193    if (aout.data_start < DATAORG) {
1194       data_off_ += AIX_DATA_OFFSET_HACK;
1195    } else {
1196       AIX_DATA_OFFSET_HACK = 0;
1197    }
1198 //   cerr << "load_object for aix: data_off=" << (void*)data_off_ << endl;
1199 //   cerr << "after an original aout.data_start of " << (void*)aout.data_start << endl;
1200 //   cerr << "and a DATAORG of " << (void*)DATAORG << endl;
1201 //   cerr << "and an AIX_DATA_OFFSET_HACK of " << (void*)AIX_DATA_OFFSET_HACK << endl;
1202 //   cerr << "aout.dsize is " << (void*)aout.dsize << endl;
1203
1204    data_len_ = aout.dsize;
1205
1206    // Now the symbol table itself:
1207    for (i=0; i < hdr.f_nsyms; i++) {
1208       /* do the pointer addition by hand since sizeof(struct syment)
1209        *   seems to be 20 not 18 as it should be */
1210       sym = (struct syment *) (((unsigned) symbols) + i * SYMESZ);
1211       if (sym->n_sclass & DBXMASK)
1212          continue;
1213       
1214       if ((sym->n_sclass == C_HIDEXT) || 
1215           (sym->n_sclass == C_EXT) ||
1216           (sym->n_sclass == C_FILE)) {
1217          if (!sym->n_zeroes) {
1218             name = string(&stringPool[sym->n_offset]);
1219          } else {
1220             char tempName[9];
1221             memset(tempName, 0, 9);
1222             strncpy(tempName, sym->n_name, 8);
1223             name = string(tempName);
1224          }
1225       }
1226             
1227       if ((sym->n_sclass == C_HIDEXT) || (sym->n_sclass == C_EXT)) {
1228          if (sym->n_sclass == C_HIDEXT) {
1229             linkage = Symbol::SL_LOCAL;
1230          } else {
1231             linkage = Symbol::SL_GLOBAL;
1232          }
1233
1234          if (sym->n_scnum == aout.o_sntext) {
1235             type = Symbol::PDST_FUNCTION;
1236             // XXX - Hack for AIX loader.
1237             value = sym->n_value + AIX_TEXT_OFFSET_HACK;
1238          } else {
1239             // bss or data
1240             csect = (union auxent *)
1241                ((char *) sym + sym->n_numaux * SYMESZ);
1242                     
1243             if (csect->x_csect.x_smclas == XMC_TC0) { 
1244                if (toc_offset)
1245                   logLine("Found more than one XMC_TC0 entry.");
1246                toc_offset = sym->n_value;
1247                continue;
1248             }
1249
1250             if ((csect->x_csect.x_smclas == XMC_TC) ||
1251                 (csect->x_csect.x_smclas == XMC_DS)) {
1252                // table of contents related entry not a real symbol.
1253                //dump << " toc entry -- ignoring" << endl;
1254                continue;
1255             }
1256             type = Symbol::PDST_OBJECT;
1257             // XXX - Hack for AIX loader.
1258             value = sym->n_value + AIX_DATA_OFFSET_HACK;
1259          }
1260
1261
1262          // skip .text entries
1263          if (name == ".text") continue;
1264          if (name.prefixed_by(".")) {
1265             // XXXX - Hack to make names match assumptions of symtab.C
1266             name = string(name.string_of()+1);
1267          }
1268          else if (type == Symbol::PDST_FUNCTION) {
1269             // text segment without a leady . is a toc item
1270             //dump << " (no leading . so assuming toc item & ignoring)" << endl;
1271             continue;
1272          }
1273
1274          //dump << "name \"" << name << "\" in module \"" << modName << "\" value=" << (void*)value << endl;
1275             
1276          //fprintf(stderr, "Found symbol %s in (%s) at %x\n", 
1277          //   name.string_of(), modName.string_of(), value);
1278          Symbol sym(name, modName, type, linkage, value, false);
1279          symbols_[name] = sym;
1280
1281          if (symbols_.defines(modName)) {
1282             // Adjust module's address, if necessary, to ensure that it's <= the
1283             // address of this new symbol
1284             Symbol &mod_symbol = symbols_[modName];
1285             if (value < mod_symbol.addr()) {
1286                //cerr << "adjusting addr of module " << modName
1287                //     << " to " << value << endl;
1288                mod_symbol.setAddr(value);
1289             }
1290          }
1291       } else if (sym->n_sclass == C_FILE) {
1292          if (!strcmp(name.string_of(), ".file")) {
1293             int j;
1294             /* has aux record with additional information. */
1295             for (j=1; j <= sym->n_numaux; j++) {
1296                aux = (union auxent *) ((char *) sym + j * SYMESZ);
1297                if (aux->x_file._x.x_ftype == XFT_FN) {
1298                   // this aux record contains the file name.
1299                   if (!aux->x_file._x.x_zeroes) {
1300                      name = 
1301                         string(&stringPool[aux->x_file._x.x_offset]);
1302                   } else {
1303                      // x_fname is 14 bytes
1304                      char tempName[15];
1305                      memset(tempName, 0, 15);
1306                      strncpy(tempName, aux->x_file.x_fname, 14);
1307                      name = string(tempName);
1308                   }
1309                }
1310             }
1311          }
1312          //dump << "found module \"" << name << "\"" << endl;
1313
1314          modName = name;
1315          
1316          const Symbol modSym(modName, modName, 
1317                              Symbol::PDST_MODULE, linkage,
1318                              UINT_MAX, // dummy address for now!
1319                              false);
1320          symbols_[modName] = modSym;
1321          
1322          continue;
1323       }
1324    }
1325         
1326    // cout << "The value of TOC is: " << toc_offset << endl;
1327    //extern void initTocOffset(int);    
1328    //initTocOffset(toc_offset);
1329    // this value is now defined per object. toc_offset_ is a private member
1330    // of class Object in Object-aix.h - naim
1331    toc_offset_ = toc_offset;
1332
1333   cleanup:
1334    close(fd);
1335    if (sectHdr) free(sectHdr);
1336    if (stringPool) free(stringPool);
1337    if (symbols) free(symbols);
1338
1339    return;
1340 }
1341
1342
1343 Object::Object(const string file, void (*err_func)(const char *))
1344     : AObject(file, err_func) {
1345     load_object();
1346 }
1347
1348 Object::Object(const Object& obj)
1349     : AObject(obj) {
1350     load_object();
1351 }
1352
1353 // for shared object files: not currently implemented
1354 // this should call a load_shared_object routine to parse the shared obj. file
1355 Object::Object(const string file,u_int,void (*err_func)(const char *))
1356     : AObject(file, err_func) {
1357 }
1358
1359
1360 Object::~Object() { }
1361
1362 Object& Object::operator=(const Object& obj) {
1363     (void) AObject::operator=(obj);
1364     return *this;
1365 }
1366
1367 //
1368 // Verify that that program is statically linked, and establish the text 
1369 //   and data segments starting addresses.
1370 //
1371 bool establishBaseAddrs(int pid, int &status, bool waitForTrap)
1372 {
1373     int ret;
1374     struct ld_info *ptr;
1375     struct ld_info info[64];
1376
1377     // check that the program was loaded at the correct address.
1378     //logLine("welcome to establishBaseAddrs\n");
1379
1380     // wait for the TRAP point.
1381     if (waitForTrap)
1382       waitpid(pid, &status, WUNTRACED);
1383
1384     /* It seems that AIX has some timing problems and
1385      when the user stack grows, the kernel doesn't update the stack info in time
1386      and ptrace calls step on user stack. This is the reason why call sleep 
1387      here, giving the kernel some time to update its internals. */
1388     usleep (36000);
1389
1390     ret = ptrace(PT_LDINFO, pid, (int *) &info, sizeof(info), (int *) &info);
1391     if (ret != 0) {
1392         statusLine("Unable to get loader info about process, application aborted");
1393         showErrorCallback(43, "Unable to get loader info about process, application aborted");
1394         return false;
1395     }
1396
1397     ptr = info;
1398     if (ptr->ldinfo_next) {
1399         statusLine("ERROR: program not statically linked");
1400         logLine("ERROR: program not statically linked");
1401         showErrorCallback(46, "Program not statically linked");
1402         return false;
1403     }
1404
1405     // now check addr.
1406     AIX_TEXT_OFFSET_HACK = (unsigned) ptr->ldinfo_textorg + 0x200;
1407     AIX_DATA_OFFSET_HACK = (unsigned) ptr->ldinfo_dataorg;
1408
1409     // turn on 'multiprocess debugging', which allows ptracing of both the
1410     // parent and child after a fork.  In particular, both parent & child will
1411     // TRAP after a fork.  Also, a process will TRAP after an exec (after the
1412     // new image has loaded but before it has started to execute at all).
1413     // Note that turning on multiprocess debugging enables two new values to be
1414     // returned by wait(): W_SEWTED and W_SFWTED, which indicate stops during
1415     // execution of exec and fork, respectively.
1416     ptrace(PT_MULTI, pid, 0, 1, 0);
1417
1418 //    cerr << "done with establishBaseAddrs; DATA hack=" << (void*)AIX_DATA_OFFSET_HACK
1419 //         << endl;
1420
1421     return true;
1422 }
1423
1424 //
1425 // dummy versions of OS statistics.
1426 //
1427 float OS::compute_rusage_cpu() { return(0.0); }
1428 float OS::compute_rusage_sys() { return(0.0); }
1429 float OS::compute_rusage_min() { return(0.0); }
1430 float OS::compute_rusage_maj() { return(0.0); }
1431 float OS::compute_rusage_swap() { return(0.0); }
1432 float OS::compute_rusage_io_in() { return(0.0); }
1433 float OS::compute_rusage_io_out() { return(0.0); }
1434 float OS::compute_rusage_msg_send() { return(0.0); }
1435 float OS::compute_rusage_sigs() { return(0.0); }
1436 float OS::compute_rusage_vol_cs() { return(0.0); }
1437 float OS::compute_rusage_inv_cs() { return(0.0); }
1438 float OS::compute_rusage_msg_recv() { return(0.0); }
1439
1440 int getNumberOfCPUs()
1441 {
1442   return(1);
1443 }
1444
1445 // #include "paradynd/src/metric.h"
1446 // #include "paradynd/src/costmetrics.h"
1447
1448 class instInstance;
1449
1450 // the following MUST become process member vrbles, since paradynd can have
1451 // more than one process active doing a fork!!!
1452 static bool seenForkTrapForParent = false;
1453 static bool seenForkTrapForChild  = false;
1454 static pid_t pidForParent;
1455 static pid_t pidForChild;
1456
1457 extern bool completeTheFork(process *, int);
1458    // in inst-power.C since class instPoint is too
1459
1460 static void process_whenBothForkTrapsReceived() {
1461    assert(seenForkTrapForParent);
1462    assert(seenForkTrapForChild);
1463
1464    forkexec_cerr << "welcome to: process_whenBothForkTrapsReceived" << endl;
1465
1466    process *parent = findProcess(pidForParent);
1467    assert(parent);
1468
1469    // complete the fork!
1470
1471    forkexec_cerr << "calling completeTheFork" << endl;
1472
1473    if (!completeTheFork(parent, pidForChild))
1474       assert(false);
1475
1476    // let's continue both processes
1477
1478    if (!parent->continueProc())
1479       assert(false);
1480
1481    // Note that we use PT_CONTINUE on the child instead of kill(pid, SIGSTOP).
1482    // Is this right?  (I think so)
1483
1484 //   int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, 0, 0);
1485    int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, SIGCONT, 0);
1486    if (ret == -1)
1487       assert(false);
1488
1489    seenForkTrapForParent = seenForkTrapForChild = false;
1490
1491    forkexec_cerr << "leaving process_whenBothForkTrapsReceived (parent & "
1492                  << "child running and should execute DYNINSTfork soon)"
1493                  << endl;
1494 }
1495
1496      //////////////////////////////////////////////////////////////////////////
1497      //Restore the base trampolines after they have been cleared by an AIX load
1498      //
1499 void resurrectBaseTramps(process *p)
1500 {
1501   if (! p) return;
1502
1503   vector<const instPoint*> allInstPoints = p->baseMap.keys();
1504
1505   extern void findAndReinstallBaseTramps(process *, vector<const instPoint*> &);
1506   findAndReinstallBaseTramps(p, allInstPoints);
1507
1508   vector<instInstance*> allInstInstances;             //Get all mini trampolines
1509   getAllInstInstancesForProcess(p, allInstInstances);
1510
1511   extern void reattachMiniTramps(process *, vector<instInstance*> &);
1512   reattachMiniTramps(p, allInstInstances);
1513 }
1514
1515
1516 bool handleAIXsigTraps(int pid, int status) {
1517     process *curr = findProcess(pid); // NULL for child of a fork
1518
1519     // see man page for "waitpid" et al for descriptions of constants such
1520     // as W_SLWTED, W_SFWTED, etc.
1521  
1522     if (WIFSTOPPED(status) && (WSTOPSIG(status)==SIGTRAP)
1523         && ((status & 0x7f) == W_SLWTED)) {
1524       //Process is stopped on a load.  AIX has reloaded the process image and
1525       //   the text segment heap has been cleared.
1526       if (curr) {
1527         curr->status_ = stopped;
1528         //fprintf(stderr, "Got load SIGTRAP from pid %d, PC=%x\n", pid,
1529         //                curr->currentPC());
1530         resurrectBaseTramps(curr);            //Restore base trampolines
1531         curr->continueProc();
1532       }
1533       return true;
1534     } // W_SLWTED (stopped-on-load)
1535
1536     // On AIX the processes will get a SIGTRAP when they execute a fork.
1537     // (Both the parent and the child will get this TRAP).
1538     // we must check for the SIGTRAP here, and handle the fork.
1539     // On aix the instrumentation on the parent will not be duplicated on 
1540     // the child, so we need to insert instrumentation again.
1541
1542     if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP 
1543         && ((status & 0x7f) == W_SFWTED)) {
1544       if (curr) {
1545         // parent process.  Stay stopped until the child process has completed
1546         // calling "completeTheFork()".
1547         forkexec_cerr << "AIX: got fork SIGTRAP from parent process " << pid << endl;
1548
1549         curr->status_ = stopped;
1550
1551         seenForkTrapForParent = true;
1552         pidForParent = curr->getPid();
1553
1554         if (seenForkTrapForChild)
1555            process_whenBothForkTrapsReceived();
1556
1557         return true;
1558       } else {
1559         // child process
1560         forkexec_cerr << "AIX: got SIGTRAP from forked (child) process " << pid << endl;
1561
1562         // get process info
1563         struct procsinfo psinfo;
1564         pid_t process_pid = pid;
1565         if (getprocs(&psinfo, sizeof(psinfo), NULL, 0, &process_pid, 1) == -1) {
1566           assert(false);
1567           return false;
1568         }
1569
1570         assert((pid_t)psinfo.pi_pid == pid);
1571
1572         //string str = string("Parent of process ") + string(pid) + " is " +
1573         //               string(psinfo.pi_ppid) + "\n";
1574         //logLine(str.string_of());
1575
1576         seenForkTrapForChild = true;
1577         pidForChild = pid;
1578         if (seenForkTrapForParent) {
1579            assert((pid_t) pidForParent == (pid_t) psinfo.pi_ppid);
1580
1581            process_whenBothForkTrapsReceived();
1582         }
1583
1584         return true;
1585       } // child process
1586     } //  W_SFWTED (stopped-on-fork)
1587
1588     return false;
1589 }
1590
1591 string process::tryToFindExecutable(const string &progpath, int pid) {
1592    // returns empty string on failure
1593
1594    if (progpath.length() == 0)
1595       return "";
1596
1597    if (exists_executable(progpath)) // util lib
1598       return progpath;
1599
1600    return ""; // failure
1601 }
1602
1603 unsigned process::read_inferiorRPC_result_register(reg returnValReg) {
1604    assert(false); // not yet implemented!!!
1605    return 0;
1606 }
1607
1608 bool process::set_breakpoint_for_syscall_completion() {
1609    // We don't know how to do this on AIX
1610    return false;
1611 }
1612
1613 vector<int> process::getTOCoffsetInfo() const
1614 {
1615     int toc_offset;
1616     toc_offset = ((getImage())->getObject()).getTOCoffset();
1617     vector<int> dummy;
1618     //  st r2,20(r1)  ; 0x90410014 save toc register  
1619     dummy += 0x90410014; 
1620
1621     //  liu r2, 0x0000     ;0x3c40abcd reset the toc value to 0xabcdefgh
1622     dummy += (0x3c400000 | (toc_offset >> 16));
1623
1624     //  oril    r2, r2,0x0000   ;0x6042efgh
1625     dummy += (0x60420000 | (toc_offset & 0x0000ffff));
1626     return dummy;
1627 }