Commented out two debugging messages
[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 /* 
43  * aix.C,v
44  * Revision 1.10  1996/05/12  05:12:57  tamches
45  * (really Jeff)
46  * Added ability to process aix 4.1-linked files.
47  *
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
51  * removed warnings
52  *
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.
57  *
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
61  * dynamically
62  * Added error messages
63  *
64  * Revision 1.6  1996/02/13 16:23:22  hollings
65  * Move Object class constructors to this file.
66  *
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
71  *
72  */
73
74
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"
85
86 #include <sys/ioctl.h>
87 #include <sys/types.h>
88 #include <fcntl.h>
89 #include <assert.h>
90 #include <stdlib.h>
91 #include <fcntl.h>
92 #include <unistd.h>
93 #include <stdio.h>
94 #include <string.h>
95 #include <xcoff.h>
96 #include <scnhdr.h>
97 #include <sys/time.h>
98 #include <sys/reg.h>
99 #include <sys/user.h>
100 #include <sys/wait.h>
101 #include <sys/ptrace.h>
102 #include <procinfo.h> // struct procsinfo
103 #include <sys/types.h>
104
105 #include "paradynd/src/showerror.h"
106 #include "util/h/debugOstream.h"
107
108 extern "C" {
109 extern int ioctl(int, int, ...);
110 };
111
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;
118
119 extern process* findProcess(int);
120
121 unsigned AIX_TEXT_OFFSET_HACK;
122 unsigned AIX_DATA_OFFSET_HACK;
123
124 class ptraceKludge {
125 public:
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);
130 };
131
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";
137       assert(0);
138     }
139   }
140   return wasStopped;
141 }
142
143 // what is the top most frame.
144 static int firstFrame;
145
146 //
147 // returns the current frame pointer (fp) and program counter (pc). 
148 // returns true if we are able to read the registers.
149 //
150 bool process::getActiveFrame(int *fp, int *pc)
151 {
152     int sp;
153     bool ret;
154     int dummy;
155
156     errno = 0;
157     sp = P_ptrace(PT_READ_GPR, pid, (int *) STKP, 0, 0); // aix 4.1 likes int *
158     if (errno != 0) return false;
159
160     errno = 0;
161     *pc = P_ptrace(PT_READ_GPR, pid, (int *) IAR, 0, 0); // aix 4.1 likes int *
162     if (errno != 0) return false;
163
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);
169     firstFrame = *fp;
170
171     return(ret);
172 }
173
174 bool process::needToAddALeafFrame(Frame,unsigned int &){
175     return false;
176 }
177
178
179 //
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.
185 //
186 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool /*uppermost*/)
187 {
188     //
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
192     //
193     struct {
194         unsigned oldFp;
195         unsigned savedCR;
196         unsigned savedLR;
197         unsigned compilerInfo;
198         unsigned binderInfo;
199         unsigned savedTOC;
200     } linkArea;
201
202     if (readDataSpace((caddr_t) currentFP, 
203                       sizeof(linkArea), 
204                       (caddr_t) &linkArea,
205                       false)) {
206         *fp = linkArea.oldFp;
207         *rtn = linkArea.savedLR;
208
209         if (currentFP == firstFrame) {
210             // use the value stored in the link register instead.
211             errno = 0;
212             *rtn = P_ptrace(PT_READ_GPR, pid, (int *)LR, 0, 0); // aix 4.1 likes int *
213             if (errno != 0) return false;
214         }
215         return true;
216     } else {
217         return false;
218     }
219 }
220
221 void *process::getRegisters() {
222    // assumes the process is stopped (ptrace requires it)
223    assert(status_ == stopped);
224
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)
236    // TID
237    // FPSCR (fp status)
238    // FPINFO (fp info) [no, out of range of what ptrace can access (why?)]
239    // FPSCRX (fp sreg ext.) [no, out of range, too]
240    
241    void *buffer = new char[num_bytes];
242    assert(buffer);
243
244    unsigned *bufferPtr = (unsigned *)buffer;
245
246    // First, the general-purpose integer registers:
247
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'
255    // Errors:
256    //    EIO --> 3d arg didn't specify a valid register (must be 0-31 or 128-136)
257
258    for (unsigned i=0; i < 32; i++) {
259       errno = 0;
260       unsigned value = P_ptrace(PT_READ_GPR, pid, (void *)i, 0, 0);
261       if (errno != 0) {
262          perror("ptrace PT_READ_GPR");
263          cerr << "regnum was " << i << endl;
264          return NULL;
265       }
266
267       *bufferPtr++ = value;
268    }
269
270    // Next, the general purpose floating point registers.
271
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.
281
282    for (unsigned i=0; i < 32; i++) {
283       double value;
284       assert(sizeof(double)==8); // make sure it's big enough!
285
286       errno = 0;
287       P_ptrace(PT_READ_FPR, pid, &value,
288                FPR0 + i, // see <sys/reg.h>
289                0);
290       if (errno != 0) {
291          perror("ptrace PT_READ_FPR");
292          cerr << "regnum was " << FPR0 + i << "; FPR0=" << FPR0 << endl;
293          return NULL;
294       }
295
296       memcpy(bufferPtr, &value, sizeof(value));
297
298       unsigned *oldBufferPtr = bufferPtr;
299       bufferPtr += 2; // 2 unsigned's --> 8 bytes
300       assert((char*)bufferPtr - (char*)oldBufferPtr == 8); // just for fun
301
302       assert(2*sizeof(unsigned) == 8);
303    }
304
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;
311
312    for (unsigned i=0; i < num_special_registers; i++) {
313       errno = 0;
314       unsigned value = P_ptrace(PT_READ_GPR, pid, (void *)special_register_codenums[i], 0, 0);
315       if (errno != 0) {
316          perror("ptrace PT_READ_GPR for a special register");
317          cerr << "regnum was " << special_register_codenums[i] << endl;
318          return NULL;
319       }
320
321       *bufferPtr++ = value;
322    }
323
324    assert((unsigned)bufferPtr - (unsigned)buffer == num_bytes);
325
326    // Whew, finally done.
327    return buffer;
328 }
329
330 static bool executeDummyTrap(process *theProc) {
331    assert(theProc->status_ == stopped);
332    
333    unsigned tempTramp = inferiorMalloc(theProc, 8, textHeap);
334    assert(tempTramp);
335
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;
341       return false;
342    }
343
344    // Okay, the temp tramp has been set up.  Let's set the PC there
345    errno = 0;
346    unsigned oldpc = P_ptrace(PT_READ_GPR, theProc->getPid(), (void *)IAR, 0, 0);
347    assert(errno == 0);
348
349    errno = 0;
350    P_ptrace(PT_WRITE_GPR, theProc->getPid(), (void *)IAR, tempTramp, 0);
351    assert(errno == 0);
352
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;
355       return false;
356    }
357
358    // We bypass continueProc() because continueProc() changes theProc->status_, which
359    // we don't want to do here
360    errno = 0;
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
363       // them now?
364    assert(errno == 0);
365
366 while (true) {
367    int status, pid;
368    do {
369 //      cerr << "doing a wait" << endl; cerr.flush();
370       pid = waitpid(theProc->getPid(), &status, WUNTRACED);
371       if (pid == 0)
372          cerr << "waitpid returned special case of 0 (?)" << endl;
373       else if (pid == -1) {
374          if (errno == ECHILD)
375             // the child has died
376             assert(false);
377          else
378             perror("executeDummyTrap waitpid()");
379       }
380       else {
381 //       cerr << "waitpid result was " << pid << endl;
382 //       if (pid == theProc->getPid())
383 //          cerr << "which was the pid, as expected" << endl;
384       }
385
386 //      cerr << "did a wait" << endl; cerr.flush();
387    } while (pid != theProc->getPid());
388
389    if (WIFEXITED(status))
390       // the child died
391       assert(false);
392
393    assert(WIFSTOPPED(status));
394
395    int sig = WSTOPSIG(status);
396    if (sig == SIGTRAP) {
397 #ifdef INFERIOR_RPC_DEBUG
398       cerr << "executeDummyTrap: got SIGTRAP, as expected!" << endl;
399 #endif
400       break;
401    }
402    else {
403       // handle an 'ordinary' signal, e.g. SIGALRM
404 #ifdef INFERIOR_RPC_DEBUG
405       cerr << "executeDummyTrap: got unexpected signal " << sig << "...ignoring" << endl;
406 #endif
407
408       // We bypass continueProc() because continueProc() changes theProc->status_, which
409       // we don't want to do here
410       errno = 0;
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
413          // them now?
414       assert(errno == 0);
415
416 //      extern int handleSigChild(int, int);
417 //      (void)handleSigChild(pid, status);
418    }
419 }
420
421    // Restore the old PC register value
422    errno = 0;
423    P_ptrace(PT_WRITE_GPR, theProc->getPid(), (void *)IAR, oldpc, 0);
424    assert(errno == 0);
425
426    // delete the temp tramp now (not yet implemented)
427
428 #ifdef INFERIOR_RPC_DEBUG
429    cerr << "leaving executeDummyTrap now" << endl;
430    cerr.flush();
431 #endif
432
433    return true;
434 }
435
436 bool process::executingSystemCall() {
437    // this is not implemented yet - naim 5/15/97
438    return false;
439 }
440
441 bool process::changePC(unsigned loc) {
442    return changePC(loc, NULL);
443 }
444
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.
449
450    // Format of PT_WRITE_GPR call:
451    // 3d param ('address'): the register to modify
452    // 4th param ('data'): the value to store
453    // 5th param ignored
454    // Returns -1 on failure; else, returns the 'data' parameter
455    // Errors:
456    //    EIO: 3d param not a valid register; must be 0-31 or 128-136
457
458 #ifdef INFERIOR_RPC_DEBUG
459    cerr << "welcome to changePC with loc=" << (void *)loc << endl;
460 #endif
461
462 // gdb hack: execute 1 dummy insn
463 #ifdef INFERIOR_RPC_DEBUG
464    cerr << "changePC: about to exec dummy trap" << endl;
465 #endif
466    if (!executeDummyTrap(this)) {
467       cerr << "changePC failed because executeDummyTrap failed" << endl;
468       return false;
469    }
470
471    errno = 0;
472    P_ptrace(PT_WRITE_GPR, pid, (void *)IAR, loc, 0);
473    if (errno) {
474       perror("changePC (PT_WRITE_GPR) failed");
475       return false;
476    }
477
478    // Double-check that the change was made by reading the IAR register
479    errno = 0;
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;
482       return false;
483    }
484    assert(errno == 0);
485
486    return true;
487 }
488
489 bool process::restoreRegisters(void *buffer) {
490    // assumes process is stopped (ptrace requires it)
491    assert(status_ == stopped);
492
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?
500
501    unsigned *bufferPtr = (unsigned *)buffer;
502
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.
509    // Errors:
510    //    EIO: address must be 0-31 or 128-136
511
512    for (unsigned i=GPR0; i <= GPR31; i++) {
513       errno = 0;
514       P_ptrace(PT_WRITE_GPR, pid, (void *)i, *bufferPtr++, 0);
515       if (errno) {
516          perror("ptrace PT_WRITE_GPR");
517          cerr << "regnum was " << i << endl;
518          return false;
519       }
520    } 
521
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)
527    // 5th param ignored
528    // returns -1 on error
529    // Errors:
530    //    EIO: reg num must be 256-287
531
532    for (unsigned i=FPR0; i <= FPR31; i++) {
533       errno = 0;
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.
537       if (errno != 0) {
538          perror("ptrace PT_WRITE_FPR");
539          cerr << "regnum was " << i << endl;
540          return false;
541       }
542
543       const unsigned *oldBufferPtr = bufferPtr;
544       bufferPtr += 2; // 2 unsigned's == 8 bytes
545       assert((unsigned)bufferPtr - (unsigned)oldBufferPtr == 8); // just for fun
546    } 
547
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;
554
555    for (unsigned i=0; i < num_special_registers; i++) {
556       errno = 0;
557       P_ptrace(PT_WRITE_GPR, pid, (void *)(special_register_codenums[i]), *bufferPtr++, 0);
558       if (errno != 0) {
559          perror("ptrace PT_WRITE_GPR for a special register");
560          cerr << "regnum was " << special_register_codenums[i] << endl;
561          return false;
562       }
563    }
564
565    return true; // success
566 }
567
568
569 bool process::emitInferiorRPCheader(void *insnPtr, unsigned &baseBytes) {
570    // TODO: write me!
571    instruction *insn = (instruction *)insnPtr;
572    unsigned baseInstruc = baseBytes / sizeof(instruction);
573
574 //   extern void generateBreakPoint(instruction &);
575 //   generateBreakPoint(insn[baseInstruc++]);
576 //   extern void generateIllegalInsn(instruction &);
577 //   generateIllegalInsn(insn[baseInstruc++]); 
578
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);
584
585    // Convert back:
586    baseBytes = baseInstruc * sizeof(instruction);
587
588    return true;
589 }
590
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,
595                                      bool stopForResult,
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.
600
601    instruction *insn = (instruction *)insnPtr;
602    unsigned baseInstruc = baseBytes / sizeof(instruction);
603
604    extern void generateBreakPoint(instruction &);
605
606    if (stopForResult) {
607       generateBreakPoint(insn[baseInstruc]);
608       stopForResultOffset = baseInstruc * sizeof(instruction);
609       baseInstruc++;
610
611       justAfter_stopForResultOffset = baseInstruc * sizeof(instruction);
612    }
613
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);
618
619    // Trap instruction (breakpoint):
620    generateBreakPoint(insn[baseInstruc]);
621    breakOffset = baseInstruc * sizeof(instruction);
622    baseInstruc++;
623
624    // And just to make sure that we don't continue, we put an illegal
625    // insn here:
626    extern void generateIllegalInsn(instruction &);
627    generateIllegalInsn(insn[baseInstruc++]);
628
629    baseBytes = baseInstruc * sizeof(instruction); // convert back
630
631    return true;
632 }
633
634 bool ptraceKludge::deliverPtrace(process *p, int req, void *addr,
635                                  int data, void *addr2) {
636   bool halted;
637   bool ret;
638   
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 *
641     ret = false;
642   else
643     ret = true;
644   if (req != PT_DETACH) continueProcess(p, halted);
645   return ret;
646 }
647
648 void ptraceKludge::continueProcess(process *p, const bool wasStopped) {
649   if ((p->status() != neonatal) && (!wasStopped)) {
650
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_
653  */
654
655 #ifndef PTRACE_ATTACH_DETACH
656     if (ptrace(PT_CONTINUE, p->pid, (int *) 1, SIGCONT, NULL) == -1) {
657 #else
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 *
661 #endif
662       logLine("Error in continueProcess\n");
663       assert(0);
664     }
665   }
666 }
667
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); 
673   close (ttyfd);
674 }
675
676 bool process::stop_() {
677 /* Choose either one of the following methods for stopping a process, 
678  * but not both. 
679  * The choice must be consistent with that in process::continueProc_ 
680  * and ptraceKludge::continueProcess
681  */
682 #ifndef PTRACE_ATTACH_DETACH
683         return (P_kill(pid, SIGSTOP) != -1); 
684 #else
685         // attach generates a SIG TRAP which we catch
686         if (!attach_()) {
687           if (kill(pid, SIGSTOP) == -1)
688              return false;
689         }
690         return(true);
691 #endif
692 }
693
694 bool process::continueWithForwardSignal(int sig) {
695 #if defined(PTRACE_ATTACH_DETACH)
696   if (sig != 0) {
697       ptrace(PT_DETACH, pid, (int*)1, stat, 0);
698       return (true);
699   } else {
700       return (ptrace(PT_CONTINUE, pid, (int*)1, 0, 0) != -1);
701   }
702 #else
703   return (ptrace(PT_CONTINUE, pid, (int*)1, sig, NULL) != -1);
704 #endif
705 }
706
707 void OS::osTraceMe(void)
708 {
709   int ret;
710
711   ret = ptrace(PT_TRACE_ME, 0, 0, 0, 0);
712   assert(ret != -1);
713 }
714
715
716 // wait for a process to terminate or stop
717 int process::waitProcs(int *status) {
718   return waitpid(0, status, WNOHANG);
719 }
720
721
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.
725   if (parent != 0) {
726     return attach_();
727   }
728   else
729     return true;
730 }
731
732 bool process::attach_() {
733    // formerly OS::osAttach()
734    int ret = ptrace(PT_ATTACH, getPid(), (int *)0, 0, 0);
735    if (ret == -1)
736       ret = ptrace(PT_REATT, getPid(), (int *)0, 0, 0);
737
738    return (ret != -1);
739 }
740
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.
745
746    assert(false); // not yet implemented!   
747 }
748
749 // TODO is this safe here ?
750 bool process::continueProc_() {
751   int ret;
752
753   if (!checkStatus()) 
754     return false;
755   ptraceOps++; ptraceOtherOps++;
756
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_
759  */
760
761 #ifndef PTRACE_ATTACH_DETACH
762   if (!ptraceKludge::deliverPtrace(this, PT_CONTINUE, (char*)1, 0, NULL))
763     ret = -1;
764   else
765     ret = 0;
766   // switch these to not detach after every call.
767   //ret = ptrace(PT_CONTINUE, pid, (int *)1, 0, NULL);
768 #else
769   ret = ptrace(PT_DETACH, pid, (int *)1, 0, NULL);
770 #endif
771
772   return (ret != -1);
773 }
774
775 #ifdef BPATCH_LIBRARY
776 bool process::terminateProc_()
777 {
778   if (!checkStatus())
779     return false;
780
781   if (P_ptrace(PT_KILL, pid, NULL, NULL, NULL) != 0)
782     return false;
783   else
784     return true;
785 }
786 #endif
787
788 // TODO ??
789 bool process::pause_() {
790   if (!checkStatus()) 
791     return false;
792   ptraceOps++; ptraceOtherOps++;
793   bool wasStopped = (status() == stopped);
794   if (status() != neonatal && !wasStopped)
795     return (loopUntilStopped());
796   else
797     return true;
798 }
799
800 bool process::detach_() {
801   if (checkStatus()) {
802       ptraceOps++; ptraceOtherOps++;
803       if (!ptraceKludge::deliverPtrace(this,PT_DETACH,(char*)1,SIGSTOP, NULL))
804       {
805           sprintf(errorLine, "Unable to detach %d\n", getPid());
806           logLine(errorLine);
807           showErrorCallback(40, (const char *) errorLine);
808       }
809   }
810   // always return true since we report the error condition.
811   return (true);
812 }
813
814 #ifdef BPATCH_LIBRARY
815 bool process::API_detach_(const bool cont) {
816   if (!checkStatus())
817       return false;
818   ptraceOps++; ptraceOtherOps++;
819   return (ptraceKludge::deliverPtrace(this,PT_DETACH,(char*)1, cont ? 0 : SIGSTOP,NULL));
820 }
821 #endif
822
823 // temporarily unimplemented, PT_DUMPCORE is specific to sunos4.1
824 bool process::dumpCore_(const string /*coreFile*/) {
825   if (!checkStatus()) 
826     return false;
827   ptraceOps++; ptraceOtherOps++;
828
829   if (!dumpImage()) {
830 //  if (!OS::osDumpImage(symbols->file(), pid, symbols->codeOffset()))
831      assert(false);
832   }
833
834   errno = 0;
835   (void) ptrace(PT_CONTINUE, pid, (int*)1, SIGBUS, NULL);
836   assert(errno == 0);
837   return true;
838 }
839
840 bool process::writeTextWord_(caddr_t inTraced, int data) {
841   if (!checkStatus()) 
842     return false;
843   ptraceBytes += sizeof(int); ptraceOps++;
844   return (ptraceKludge::deliverPtrace(this, PT_WRITE_I, inTraced, data, NULL));
845 }
846
847 bool process::writeTextSpace_(void *inTraced, int amount, const void *inSelf) {
848   if (!checkStatus()) 
849     return false;
850   ptraceBytes += amount; ptraceOps++;
851   return (ptraceKludge::deliverPtrace(this, PT_WRITE_BLOCK, inTraced, 
852                                       amount, inSelf));
853 }
854
855 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
856 bool process::readTextSpace_(void *inTraced, int amount, const void *inSelf) {
857   if (!checkStatus())
858     return false;
859   ptraceOps++; ptraceBytes += amount;
860   return (ptraceKludge::deliverPtrace(this, PT_READ_BLOCK, inTraced, amount,
861                                       inSelf));
862 }
863 #endif
864
865 bool process::writeDataSpace_(void *inTraced, int amount, const void *inSelf) {
866   if (!checkStatus())
867     return false;
868
869   ptraceOps++; ptraceBytes += amount;
870
871   return (ptraceKludge::deliverPtrace(this, PT_WRITE_BLOCK, inTraced, amount, inSelf));
872 }
873
874 bool process::readDataSpace_(const void *inTraced, int amount, void *inSelf) {
875   if (!checkStatus())
876     return false;
877   ptraceOps++; ptraceBytes += amount;
878   return (ptraceKludge::deliverPtrace(this, PT_READ_BLOCK, inTraced, amount, inSelf));
879 }
880
881 bool process::loopUntilStopped() {
882   /* make sure the process is stopped in the eyes of ptrace */
883   stop_();     //Send the process a SIGSTOP
884
885   bool isStopped = false;
886   int waitStatus;
887   while (!isStopped) {
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.
897       //status_ = exited;
898       handleProcessExit(this, WEXITSTATUS(waitStatus));
899       return(false);
900     }
901     if (!WIFSTOPPED(waitStatus) && !WIFSIGNALED(waitStatus)) {
902       printf("problem stopping process\n");
903       return false;
904     }
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
912         isStopped = true;
913       }
914     } else {
915       if (ptrace(PT_CONTINUE, pid, (int*)1, sig, 0) == -1) {
916         logLine("Ptrace error in PT_CONTINUE, loopUntilStopped\n");
917         return false;
918       }
919     }
920   }
921
922   return true;
923 }
924
925
926 //
927 // Write out the current contents of the text segment to disk.  This is useful
928 //    for debugging dyninst.
929 //
930 bool process::dumpImage() {
931     // formerly OS::osDumpImage()
932     const string &imageFileName = symbols->file();
933     // const Address codeOff = symbols->codeOffset();
934
935     int i;
936     int rd;
937     int ifd;
938     int ofd;
939     int cnt;
940     int ret;
941     int total;
942     int length;
943     Address baseAddr;
944     extern int errno;
945     char buffer[4096];
946     char outFile[256];
947     struct filehdr hdr;
948     struct stat statBuf;
949     struct aouthdr aout;
950     struct scnhdr *sectHdr;
951     bool needsCont = false;
952     struct ld_info info[64];
953
954     ifd = open(imageFileName.string_of(), O_RDONLY, 0);
955     if (ifd < 0) {
956       sprintf(errorLine, "Unable to open %s\n", outFile);
957       logLine(errorLine);
958       showErrorCallback(41, (const char *) errorLine);
959       perror("open");
960       return true;
961     }
962
963     rd = fstat(ifd, &statBuf);
964     if (rd != 0) {
965       perror("fstat");
966       sprintf(errorLine, "Unable to stat %s\n", outFile);
967       logLine(errorLine);
968       showErrorCallback(72, (const char *) errorLine);
969       return true;
970     }
971     length = statBuf.st_size;
972     sprintf(outFile, "%s.real", imageFileName.string_of());
973     sprintf(errorLine, "Saving program to %s\n", outFile);
974     logLine(errorLine);
975
976     ofd = open(outFile, O_WRONLY|O_CREAT, 0777);
977     if (ofd < 0) {
978       perror("open");
979       exit(-1);
980     }
981
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");
986         logLine(errorLine);
987         showErrorCallback(44, "");
988         return false;
989     }
990
991     cnt = read(ifd, &aout, sizeof(struct aouthdr));
992
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");
997         logLine(errorLine);
998         return false;
999     }
1000
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);
1007         total += rd;
1008     }
1009
1010     if (!stopped) {
1011         // make sure it is stopped.
1012         findProcess(pid)->stop_();
1013
1014         waitpid(pid, NULL, WUNTRACED);
1015         needsCont = true;
1016     }
1017
1018     ret = ptrace(PT_LDINFO, pid, (int *) &info, sizeof(info), (int *) &info);
1019     if (ret != 0) {
1020         statusLine("Unable to get loader info about process");
1021         showErrorCallback(43, "Unable to get loader info about process");
1022         return false;
1023     }
1024
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",
1027         aout.text_start);
1028     logLine(errorLine);
1029     sprintf(errorLine, "Code offset = %d\n", baseAddr);
1030     logLine(errorLine);
1031
1032     /* seek to the text segment */
1033     lseek(ofd, aout.text_start, SEEK_SET);
1034     for (i=0; i < aout.tsize; i+= 1024) {
1035         errno = 0;
1036         length = ((i + 1024) < aout.tsize) ? 1024 : aout.tsize -i;
1037         ptrace(PT_READ_BLOCK, pid, (int*) (baseAddr + i), length, (int *)buffer);
1038         if (errno) {
1039             perror("ptrace");
1040             assert(0);
1041         }
1042         write(ofd, buffer, length);
1043     }
1044
1045     if (needsCont) {
1046         ptrace(PT_CONTINUE, pid, (int*) 1, SIGCONT, 0);
1047     }
1048
1049     close(ofd);
1050     close(ifd);
1051
1052     return true;
1053 }
1054
1055 //
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.
1058 //
1059 bool seekAndRead(int fd, int offset, void **dest, int length, bool allocate)
1060 {
1061     int cnt;
1062
1063     if (allocate) {
1064         *dest = malloc(length);
1065     }
1066
1067     if (!*dest) {
1068         sprintf(errorLine, "Unable to parse executable file\n");
1069         logLine(errorLine);
1070         showErrorCallback(42, (const char *) errorLine);
1071         return false;
1072     }
1073
1074     cnt = lseek(fd, offset, SEEK_SET);
1075     if (cnt != offset) {
1076         sprintf(errorLine, "Unable to parse executable file\n");
1077         logLine(errorLine);
1078         showErrorCallback(42, (const char *) errorLine);
1079         return false;
1080     }
1081     cnt = read(fd, *dest, length);
1082     if (cnt != length) {
1083         sprintf(errorLine, "Unable to parse executable file\n");
1084         logLine(errorLine);
1085         showErrorCallback(42, (const char *) errorLine);
1086         return false;
1087     }
1088     return true;
1089 }
1090
1091 void Object::load_object()
1092 {
1093     long i;
1094     int fd;
1095     int cnt;
1096     string name;
1097     string module;
1098     unsigned value;
1099     int poolOffset;
1100     int poolLength;
1101     union auxent *aux;
1102     struct filehdr hdr;
1103     struct syment *sym;
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;
1114
1115     fd = open(file_.string_of(), O_RDONLY, 0);
1116     if (fd <0) {
1117         sprintf(errorLine, "Unable to open executable file %s\n", 
1118             file_.string_of());
1119         statusLine(errorLine);
1120         showErrorCallback(27,(const char *) errorLine);
1121         goto cleanup;
1122     }
1123
1124     cnt = read(fd, &hdr, sizeof(struct filehdr));
1125     if (cnt != sizeof(struct filehdr)) {
1126         sprintf(errorLine, "Error reading executable file %s\n", 
1127             file_.string_of());
1128         statusLine(errorLine);
1129         showErrorCallback(49,(const char *) errorLine);
1130         goto cleanup;
1131     }
1132
1133     cnt = read(fd, &aout, sizeof(struct aouthdr));
1134     if (cnt != sizeof(struct aouthdr)) {
1135         sprintf(errorLine, "Error reading executable file %s\n", 
1136             file_.string_of());
1137         statusLine(errorLine);
1138         showErrorCallback(49,(const char *) errorLine);
1139         goto cleanup;
1140     }
1141
1142     sectHdr = (struct scnhdr *) malloc(sizeof(struct scnhdr) * hdr.f_nscns);
1143     assert(sectHdr);
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", 
1147             file_.string_of());
1148         statusLine(errorLine);
1149         showErrorCallback(49,(const char *) errorLine);
1150         goto cleanup;
1151     }
1152
1153     // fprintf(stderr, "symbol table has %d entries starting at %d\n",
1154     //    (int) hdr.f_nsyms, (int) hdr.f_symptr);
1155
1156     if (!seekAndRead(fd, hdr.f_symptr, (void**) &symbols, 
1157         hdr.f_nsyms * SYMESZ, true)) {
1158         goto cleanup;
1159     }
1160
1161     /*
1162      * Get the string pool
1163      */
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)) {
1167         goto cleanup;
1168     }
1169
1170     if (!seekAndRead(fd, poolOffset, (void**) &stringPool, poolLength, true)) {
1171         goto cleanup;
1172     }
1173
1174     // identify the code region.
1175     if ((unsigned) aout.tsize != sectHdr[aout.o_sntext-1].s_size) {
1176         // consistantcy check failed!!!!
1177         sprintf(errorLine, 
1178             "Executable header file internal error: text segment size %s\n", 
1179             file_.string_of());
1180         statusLine(errorLine);
1181         showErrorCallback(45,(const char *) errorLine);
1182         goto cleanup;
1183     }
1184
1185     if (!seekAndRead(fd, sectHdr[aout.o_sntext-1].s_scnptr, 
1186         (void **) &code_ptr_, aout.tsize, true)) {
1187         goto cleanup;
1188     }
1189
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;
1194      } else {
1195        AIX_TEXT_OFFSET_HACK = 0;
1196      }
1197
1198
1199     // fprintf(stderr, "reading code starting at %x\n", code_off_);
1200
1201     code_len_ = aout.tsize;
1202
1203     // now the init data segment.
1204     if ((unsigned) aout.dsize != sectHdr[aout.o_sndata-1].s_size) {
1205         // consistantcy check failed!!!!
1206         sprintf(errorLine, 
1207             "Executable header file interal error: data segment size %s\n", 
1208             file_.string_of());
1209         statusLine(errorLine);
1210         showErrorCallback(45,(const char *) errorLine);
1211         goto cleanup;
1212     }
1213     if (!seekAndRead(fd, sectHdr[aout.o_sndata-1].s_scnptr, 
1214         (void **) &data_ptr_, aout.dsize, true)) {
1215         goto cleanup;
1216     }
1217
1218     // data_off_ = sectHdr[aout.o_sndata-1].s_vaddr + AIX_DATA_OFFSET_HACK; 
1219     // (OLD, pre-4.1)
1220     data_off_ = aout.data_start;
1221     if (aout.data_start < DATAORG) {
1222        data_off_ += AIX_DATA_OFFSET_HACK;
1223     } else {
1224        AIX_DATA_OFFSET_HACK = 0;
1225     }
1226
1227     data_len_ = aout.dsize;
1228
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]);
1239                 } else {
1240                     char tempName[9];
1241                     memset(tempName, 0, 9);
1242                     strncpy(tempName, sym->n_name, 8);
1243                     name = string(tempName);
1244                 }
1245             }
1246             
1247             if ((sym->n_sclass == C_HIDEXT) || (sym->n_sclass == C_EXT)) {
1248                 if (sym->n_sclass == C_HIDEXT) {
1249                     linkage = Symbol::SL_LOCAL;
1250                 } else {
1251                     linkage = Symbol::SL_GLOBAL;
1252                 }
1253
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;
1258                 } else {
1259                     // bss or data
1260                     csect = (union auxent *)
1261                         ((char *) sym + sym->n_numaux * SYMESZ);
1262                     
1263                     if (csect->x_csect.x_smclas == XMC_TC0) { 
1264                         if (toc_offset)
1265                             logLine("Found more than one XMC_TC0 entry.");
1266                         toc_offset = sym->n_value;
1267                         continue;
1268                     }
1269
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.
1273                         continue;
1274                     }
1275                     type = Symbol::PDST_OBJECT;
1276                     // XXX - Hack for AIX loader.
1277                     value = sym->n_value + AIX_DATA_OFFSET_HACK;
1278                 }
1279
1280
1281                 if (newModule) {
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, "");
1289                             goto cleanup;
1290                         }
1291                     } else {
1292                         symbols_[module] = Symbol(module, module, 
1293                             Symbol::PDST_MODULE, linkage, value, false);
1294                     }
1295                     newModule = false;
1296                 }
1297
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
1302                     char temp[512];
1303                     //sprintf(temp, "_%s", &name.string_of()[1]);
1304                     //Just skip the "."
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
1309                     continue;
1310                 }
1311
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, 
1315                             value, false);
1316             } else if (sym->n_sclass == C_FILE) {
1317                 if (!strcmp(name.string_of(), ".file")) {
1318                     int j;
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) {
1325                                 name = 
1326                                   string(&stringPool[aux->x_file._x.x_offset]);
1327                             } else {
1328                                 // x_fname is 14 bytes
1329                                 char tempName[14];
1330                                 memset(tempName, 0, 15);
1331                                 strncpy(tempName, aux->x_file.x_fname, 14);
1332                                 name = string(tempName);
1333                             }
1334                         }
1335                     }
1336                 }
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.
1340                 newModule = true;
1341                 module = name;
1342                 continue;
1343             }
1344         }
1345     }
1346         
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;
1353
1354 cleanup:
1355     close(fd);
1356     if (sectHdr) free(sectHdr);
1357     if (stringPool) free(stringPool);
1358     if (symbols) free(symbols);
1359
1360     return;
1361 }
1362
1363
1364 Object::Object(const string file, void (*err_func)(const char *))
1365     : AObject(file, err_func) {
1366     load_object();
1367 }
1368
1369 Object::Object(const Object& obj)
1370     : AObject(obj) {
1371     load_object();
1372 }
1373
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) {
1378 }
1379
1380
1381 Object::~Object() { }
1382
1383 Object& Object::operator=(const Object& obj) {
1384     (void) AObject::operator=(obj);
1385     return *this;
1386 }
1387
1388 //
1389 // Verify that that program is statically linked, and establish the text 
1390 //   and data segments starting addresses.
1391 //
1392 bool establishBaseAddrs(int pid, int &status, bool waitForTrap)
1393 {
1394     int ret;
1395     struct ld_info *ptr;
1396     struct ld_info info[64];
1397
1398     // check that the program was loaded at the correct address.
1399
1400     // wait for the TRAP point.
1401     if (waitForTrap)
1402       waitpid(pid, &status, WUNTRACED);
1403
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. */
1408     usleep (36000);
1409
1410     ret = ptrace(PT_LDINFO, pid, (int *) &info, sizeof(info), (int *) &info);
1411     if (ret != 0) {
1412         statusLine("Unable to get loader info about process, application aborted");
1413         showErrorCallback(43, "Unable to get loader info about process, application aborted");
1414         return false;
1415     }
1416
1417     ptr = info;
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");
1422         return false;
1423     }
1424
1425     // now check addr.
1426     AIX_TEXT_OFFSET_HACK = (unsigned) ptr->ldinfo_textorg + 0x200;
1427     AIX_DATA_OFFSET_HACK = (unsigned) ptr->ldinfo_dataorg;
1428
1429     ptrace(PT_MULTI, pid, 0, 1, 0);
1430
1431     return true;
1432 }
1433
1434 //
1435 // dummy versions of OS statistics.
1436 //
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); }
1449
1450 int getNumberOfCPUs()
1451 {
1452   return(1);
1453 }
1454
1455 // #include "paradynd/src/metric.h"
1456 // #include "paradynd/src/costmetrics.h"
1457
1458 class instInstance;
1459
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;
1466
1467 extern bool completeTheFork(process *, int);
1468    // in inst-power.C since class instPoint is too
1469
1470 static void process_whenBothForkTrapsReceived() {
1471    assert(seenForkTrapForParent);
1472    assert(seenForkTrapForChild);
1473
1474    forkexec_cerr << "welcome to: process_whenBothForkTrapsReceived" << endl;
1475
1476    process *parent = findProcess(pidForParent);
1477    assert(parent);
1478
1479    // complete the fork!
1480
1481    forkexec_cerr << "calling completeTheFork" << endl;
1482
1483    if (!completeTheFork(parent, pidForChild))
1484       assert(false);
1485
1486    // let's continue both processes
1487
1488    if (!parent->continueProc())
1489       assert(false);
1490
1491    // Note that we use PT_CONTINUE on the child instead of kill(pid, SIGSTOP).
1492    // Is this right?  (I think so)
1493
1494 //   int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, 0, 0);
1495    int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, SIGCONT, 0);
1496    if (ret == -1)
1497       assert(false);
1498
1499    seenForkTrapForParent = seenForkTrapForChild = false;
1500
1501    forkexec_cerr << "leaving process_whenBothForkTrapsReceived (parent & "
1502                  << "child running and should execute DYNINSTfork soon)"
1503                  << endl;
1504 }
1505
1506      //////////////////////////////////////////////////////////////////////////
1507      //Restore the base trampolines after they have been cleared by an AIX load
1508      //
1509 void resurrectBaseTramps(process *p)
1510 {
1511   if (! p) return;
1512
1513   vector<const instPoint*> allInstPoints = p->baseMap.keys();
1514
1515   extern void findAndReinstallBaseTramps(process *, vector<const instPoint*> &);
1516   findAndReinstallBaseTramps(p, allInstPoints);
1517
1518   vector<instInstance*> allInstInstances;             //Get all mini trampolines
1519   getAllInstInstancesForProcess(p, allInstInstances);
1520
1521   extern void reattachMiniTramps(process *, vector<instInstance*> &);
1522   reattachMiniTramps(p, allInstInstances);
1523 }
1524
1525
1526 bool handleAIXsigTraps(int pid, int status) {
1527     process *curr = findProcess(pid); // NULL for child of a fork
1528
1529     // see man page for "waitpid" et al for descriptions of constants such
1530     // as W_SLWTED, W_SFWTED, etc.
1531  
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.
1536       if (curr) {
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();
1542       }
1543       return true;
1544     } // W_SLWTED (stopped-on-load)
1545
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.
1551
1552     if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP 
1553         && ((status & 0x7f) == W_SFWTED)) {
1554       if (curr) {
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;
1558
1559         curr->status_ = stopped;
1560
1561         seenForkTrapForParent = true;
1562         pidForParent = curr->getPid();
1563
1564         if (seenForkTrapForChild)
1565            process_whenBothForkTrapsReceived();
1566
1567         return true;
1568       } else {
1569         // child process
1570         forkexec_cerr << "AIX: got SIGTRAP from forked (child) process " << pid << endl;
1571
1572         // get process info
1573         struct procsinfo psinfo;
1574         pid_t process_pid = pid;
1575         if (getprocs(&psinfo, sizeof(psinfo), NULL, 0, &process_pid, 1) == -1) {
1576           assert(false);
1577           return false;
1578         }
1579
1580         assert((pid_t)psinfo.pi_pid == pid);
1581
1582         //string str = string("Parent of process ") + string(pid) + " is " +
1583         //               string(psinfo.pi_ppid) + "\n";
1584         //logLine(str.string_of());
1585
1586         seenForkTrapForChild = true;
1587         pidForChild = pid;
1588         if (seenForkTrapForParent) {
1589            assert((pid_t) pidForParent == (pid_t) psinfo.pi_ppid);
1590
1591            process_whenBothForkTrapsReceived();
1592         }
1593
1594         return true;
1595       } // child process
1596     } //  W_SFWTED (stopped-on-fork)
1597
1598     return false;
1599 }
1600
1601 string process::tryToFindExecutable(const string &progpath, int pid) {
1602    // returns empty string on failure
1603
1604    if (progpath.length() == 0)
1605       return "";
1606
1607    if (exists_executable(progpath)) // util lib
1608       return progpath;
1609
1610    return ""; // failure
1611 }
1612
1613 unsigned process::read_inferiorRPC_result_register(reg returnValReg) {
1614    assert(false); // not yet implemented!!!
1615    return 0;
1616 }
1617
1618 bool process::set_breakpoint_for_syscall_completion() {
1619    // We don't know how to do this on AIX
1620    return false;
1621 }
1622
1623 vector<int> process::getTOCoffsetInfo() const
1624 {
1625     int toc_offset;
1626     toc_offset = ((getImage())->getObject()).getTOCoffset();
1627     vector<int> dummy;
1628     //  st r2,20(r1)  ; 0x90410014 save toc register  
1629     dummy += 0x90410014; 
1630
1631     //  liu r2, 0x0000     ;0x3c40abcd reset the toc value to 0xabcdefgh
1632     dummy += (0x3c400000 | (toc_offset >> 16));
1633
1634     //  oril    r2, r2,0x0000   ;0x6042efgh
1635     dummy += (0x60420000 | (toc_offset & 0x0000ffff));
1636     return dummy;
1637 }