load_object() changed: roundup4() used for sntext and sndata file offsets;
[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 unsigned long roundup4(unsigned long val) {
1092    while (val % 4 != 0)
1093       val++;
1094    return val;
1095 }
1096
1097 void Object::load_object()
1098 {
1099    // all these vrble declarations need to be up here due to the gotos,
1100    // which mustn't cross vrble initializations.  Too bad.
1101    long i;
1102    int fd;
1103    int cnt;
1104    string name;
1105    unsigned value;
1106    int poolOffset;
1107    int poolLength;
1108    union auxent *aux;
1109    struct filehdr hdr;
1110    struct syment *sym;
1111    struct aouthdr aout;
1112    union auxent *csect;
1113    char *stringPool=NULL;
1114    Symbol::SymbolType type; 
1115    int *lengthPtr = &poolLength;
1116    struct syment *symbols = NULL;
1117    struct scnhdr *sectHdr = NULL;
1118    Symbol::SymbolLinkage linkage;
1119    unsigned toc_offset = 0;
1120    string modName;
1121
1122    fd = open(file_.string_of(), O_RDONLY, 0);
1123    if (fd <0) {
1124       sprintf(errorLine, "Unable to open executable file %s\n", 
1125               file_.string_of());
1126       statusLine(errorLine);
1127       showErrorCallback(27,(const char *) errorLine);
1128       goto cleanup;
1129    }
1130
1131    cnt = read(fd, &hdr, sizeof(struct filehdr));
1132    if (cnt != sizeof(struct filehdr)) {
1133       sprintf(errorLine, "Error reading executable file %s\n", 
1134               file_.string_of());
1135       statusLine(errorLine);
1136       showErrorCallback(49,(const char *) errorLine);
1137       goto cleanup;
1138    }
1139
1140    cnt = read(fd, &aout, sizeof(struct aouthdr));
1141    if (cnt != sizeof(struct aouthdr)) {
1142       sprintf(errorLine, "Error reading executable file %s\n", 
1143               file_.string_of());
1144       statusLine(errorLine);
1145       showErrorCallback(49,(const char *) errorLine);
1146       goto cleanup;
1147    }
1148
1149    sectHdr = (struct scnhdr *) malloc(sizeof(struct scnhdr) * hdr.f_nscns);
1150    assert(sectHdr);
1151    cnt = read(fd, sectHdr, sizeof(struct scnhdr) * hdr.f_nscns);
1152    if ((unsigned) cnt != sizeof(struct scnhdr)* hdr.f_nscns) {
1153       sprintf(errorLine, "Error reading executable file %s\n", 
1154               file_.string_of());
1155       statusLine(errorLine);
1156       showErrorCallback(49,(const char *) errorLine);
1157       goto cleanup;
1158    }
1159
1160    // fprintf(stderr, "symbol table has %d entries starting at %d\n",
1161    //    (int) hdr.f_nsyms, (int) hdr.f_symptr);
1162
1163    if (!seekAndRead(fd, hdr.f_symptr, (void**) &symbols, 
1164                     hdr.f_nsyms * SYMESZ, true)) {
1165       goto cleanup;
1166    }
1167
1168    /*
1169     * Get the string pool
1170     */
1171    poolOffset = hdr.f_symptr + hdr.f_nsyms * SYMESZ;
1172    /* length is stored in the first 4 bytes of the string pool */
1173    if (!seekAndRead(fd, poolOffset, (void**) &lengthPtr, sizeof(int), false)) {
1174       goto cleanup;
1175    }
1176
1177    if (!seekAndRead(fd, poolOffset, (void**) &stringPool, poolLength, true)) {
1178       goto cleanup;
1179    }
1180
1181    // identify the code region.
1182    if ((unsigned) aout.tsize != sectHdr[aout.o_sntext-1].s_size) {
1183       // consistantcy check failed!!!!
1184       sprintf(errorLine, 
1185               "Executable header file internal error: text segment size %s\n", 
1186               file_.string_of());
1187       statusLine(errorLine);
1188       showErrorCallback(45,(const char *) errorLine);
1189       goto cleanup;
1190    }
1191
1192    if (!seekAndRead(fd, roundup4(sectHdr[aout.o_sntext-1].s_scnptr), 
1193                     (void **) &code_ptr_, aout.tsize, true)) {
1194       goto cleanup;
1195    }
1196
1197    //code_off_ =  aout.text_start + AIX_TEXT_OFFSET_HACK; (OLD, pre-4.1)
1198    code_off_ =  aout.text_start;
1199    if (aout.text_start < TEXTORG) {
1200       code_off_ += AIX_TEXT_OFFSET_HACK;
1201    } else {
1202       AIX_TEXT_OFFSET_HACK = 0;
1203    }
1204
1205    code_len_ = aout.tsize;
1206
1207    // now the init data segment (as opposed to .bss, the uninitialized data segment)
1208    if ((unsigned long) aout.dsize != sectHdr[aout.o_sndata-1].s_size) {
1209       // consistantcy check failed!!!!
1210       sprintf(errorLine, 
1211               "Executable header file interal error: data segment size %s\n", 
1212               file_.string_of());
1213       statusLine(errorLine);
1214       showErrorCallback(45,(const char *) errorLine);
1215       goto cleanup;
1216    }
1217    if (!seekAndRead(fd, roundup4(sectHdr[aout.o_sndata-1].s_scnptr), 
1218                     (void **) &data_ptr_, aout.dsize, true)) {
1219       cerr << "seekAndRead for initialized data section failed!" << endl;
1220       goto cleanup;
1221    }
1222
1223    // data_off_ = sectHdr[aout.o_sndata-1].s_vaddr + AIX_DATA_OFFSET_HACK; 
1224    // (OLD, pre-4.1)
1225    data_off_ = aout.data_start;
1226    if (aout.data_start < DATAORG) {
1227       data_off_ += AIX_DATA_OFFSET_HACK;
1228    } else {
1229       AIX_DATA_OFFSET_HACK = 0;
1230    }
1231 //   cerr << "load_object for aix: data_off=" << (void*)data_off_ << endl;
1232 //   cerr << "after an original aout.data_start of " << (void*)aout.data_start << endl;
1233 //   cerr << "and a DATAORG of " << (void*)DATAORG << endl;
1234 //   cerr << "and an AIX_DATA_OFFSET_HACK of " << (void*)AIX_DATA_OFFSET_HACK << endl;
1235 //   cerr << "aout.dsize is " << (void*)aout.dsize << endl;
1236
1237    data_len_ = aout.dsize;
1238
1239    // Now the symbol table itself:
1240    for (i=0; i < hdr.f_nsyms; i++) {
1241       /* do the pointer addition by hand since sizeof(struct syment)
1242        *   seems to be 20 not 18 as it should be */
1243       sym = (struct syment *) (((unsigned) symbols) + i * SYMESZ);
1244       if (sym->n_sclass & DBXMASK)
1245          continue;
1246       
1247       if ((sym->n_sclass == C_HIDEXT) || 
1248           (sym->n_sclass == C_EXT) ||
1249           (sym->n_sclass == C_FILE)) {
1250          if (!sym->n_zeroes) {
1251             name = string(&stringPool[sym->n_offset]);
1252          } else {
1253             char tempName[9];
1254             memset(tempName, 0, 9);
1255             strncpy(tempName, sym->n_name, 8);
1256             name = string(tempName);
1257          }
1258       }
1259             
1260       if ((sym->n_sclass == C_HIDEXT) || (sym->n_sclass == C_EXT)) {
1261          if (sym->n_sclass == C_HIDEXT) {
1262             linkage = Symbol::SL_LOCAL;
1263          } else {
1264             linkage = Symbol::SL_GLOBAL;
1265          }
1266
1267          if (sym->n_scnum == aout.o_sntext) {
1268             type = Symbol::PDST_FUNCTION;
1269             // XXX - Hack for AIX loader.
1270             value = sym->n_value + AIX_TEXT_OFFSET_HACK;
1271          } else {
1272             // bss or data
1273             csect = (union auxent *)
1274                ((char *) sym + sym->n_numaux * SYMESZ);
1275                     
1276             if (csect->x_csect.x_smclas == XMC_TC0) { 
1277                if (toc_offset)
1278                   logLine("Found more than one XMC_TC0 entry.");
1279                toc_offset = sym->n_value;
1280                continue;
1281             }
1282
1283             if ((csect->x_csect.x_smclas == XMC_TC) ||
1284                 (csect->x_csect.x_smclas == XMC_DS)) {
1285                // table of contents related entry not a real symbol.
1286                //dump << " toc entry -- ignoring" << endl;
1287                continue;
1288             }
1289             type = Symbol::PDST_OBJECT;
1290             // XXX - Hack for AIX loader.
1291             value = sym->n_value + AIX_DATA_OFFSET_HACK;
1292          }
1293
1294
1295          // skip .text entries
1296          if (name == ".text") continue;
1297          if (name.prefixed_by(".")) {
1298             // XXXX - Hack to make names match assumptions of symtab.C
1299             name = string(name.string_of()+1);
1300          }
1301          else if (type == Symbol::PDST_FUNCTION) {
1302             // text segment without a leady . is a toc item
1303             //dump << " (no leading . so assuming toc item & ignoring)" << endl;
1304             continue;
1305          }
1306
1307          //dump << "name \"" << name << "\" in module \"" << modName << "\" value=" << (void*)value << endl;
1308             
1309          //fprintf(stderr, "Found symbol %s in (%s) at %x\n", 
1310          //   name.string_of(), modName.string_of(), value);
1311          Symbol sym(name, modName, type, linkage, value, false);
1312          symbols_[name] = sym;
1313
1314          if (symbols_.defines(modName)) {
1315             // Adjust module's address, if necessary, to ensure that it's <= the
1316             // address of this new symbol
1317             Symbol &mod_symbol = symbols_[modName];
1318             if (value < mod_symbol.addr()) {
1319                //cerr << "adjusting addr of module " << modName
1320                //     << " to " << value << endl;
1321                mod_symbol.setAddr(value);
1322             }
1323          }
1324       } else if (sym->n_sclass == C_FILE) {
1325          if (!strcmp(name.string_of(), ".file")) {
1326             int j;
1327             /* has aux record with additional information. */
1328             for (j=1; j <= sym->n_numaux; j++) {
1329                aux = (union auxent *) ((char *) sym + j * SYMESZ);
1330                if (aux->x_file._x.x_ftype == XFT_FN) {
1331                   // this aux record contains the file name.
1332                   if (!aux->x_file._x.x_zeroes) {
1333                      name = 
1334                         string(&stringPool[aux->x_file._x.x_offset]);
1335                   } else {
1336                      // x_fname is 14 bytes
1337                      char tempName[15];
1338                      memset(tempName, 0, 15);
1339                      strncpy(tempName, aux->x_file.x_fname, 14);
1340                      name = string(tempName);
1341                   }
1342                }
1343             }
1344          }
1345          //dump << "found module \"" << name << "\"" << endl;
1346
1347          modName = name;
1348          
1349          const Symbol modSym(modName, modName, 
1350                              Symbol::PDST_MODULE, linkage,
1351                              UINT_MAX, // dummy address for now!
1352                              false);
1353          symbols_[modName] = modSym;
1354          
1355          continue;
1356       }
1357    }
1358         
1359    // cout << "The value of TOC is: " << toc_offset << endl;
1360    //extern void initTocOffset(int);    
1361    //initTocOffset(toc_offset);
1362    // this value is now defined per object. toc_offset_ is a private member
1363    // of class Object in Object-aix.h - naim
1364    toc_offset_ = toc_offset;
1365
1366   cleanup:
1367    close(fd);
1368    if (sectHdr) free(sectHdr);
1369    if (stringPool) free(stringPool);
1370    if (symbols) free(symbols);
1371
1372    return;
1373 }
1374
1375
1376 Object::Object(const string file, void (*err_func)(const char *))
1377     : AObject(file, err_func) {
1378     load_object();
1379 }
1380
1381 Object::Object(const Object& obj)
1382     : AObject(obj) {
1383     load_object();
1384 }
1385
1386 // for shared object files: not currently implemented
1387 // this should call a load_shared_object routine to parse the shared obj. file
1388 Object::Object(const string file,u_int,void (*err_func)(const char *))
1389     : AObject(file, err_func) {
1390 }
1391
1392
1393 Object::~Object() { }
1394
1395 Object& Object::operator=(const Object& obj) {
1396     (void) AObject::operator=(obj);
1397     return *this;
1398 }
1399
1400 //
1401 // Verify that that program is statically linked, and establish the text 
1402 //   and data segments starting addresses.
1403 //
1404 bool establishBaseAddrs(int pid, int &status, bool waitForTrap)
1405 {
1406     int ret;
1407     struct ld_info *ptr;
1408     struct ld_info info[64];
1409
1410     // check that the program was loaded at the correct address.
1411     //logLine("welcome to establishBaseAddrs\n");
1412
1413     // wait for the TRAP point.
1414     if (waitForTrap)
1415       waitpid(pid, &status, WUNTRACED);
1416
1417     /* It seems that AIX has some timing problems and
1418      when the user stack grows, the kernel doesn't update the stack info in time
1419      and ptrace calls step on user stack. This is the reason why call sleep 
1420      here, giving the kernel some time to update its internals. */
1421     usleep (36000);
1422
1423     ret = ptrace(PT_LDINFO, pid, (int *) &info, sizeof(info), (int *) &info);
1424     if (ret != 0) {
1425         statusLine("Unable to get loader info about process, application aborted");
1426         showErrorCallback(43, "Unable to get loader info about process, application aborted");
1427         return false;
1428     }
1429
1430     ptr = info;
1431     if (ptr->ldinfo_next) {
1432         statusLine("ERROR: program not statically linked");
1433         logLine("ERROR: program not statically linked");
1434         showErrorCallback(46, "Program not statically linked");
1435         return false;
1436     }
1437
1438     // now check addr.
1439     AIX_TEXT_OFFSET_HACK = (unsigned) ptr->ldinfo_textorg + 0x200;
1440     AIX_DATA_OFFSET_HACK = (unsigned) ptr->ldinfo_dataorg;
1441
1442     // turn on 'multiprocess debugging', which allows ptracing of both the
1443     // parent and child after a fork.  In particular, both parent & child will
1444     // TRAP after a fork.  Also, a process will TRAP after an exec (after the
1445     // new image has loaded but before it has started to execute at all).
1446     // Note that turning on multiprocess debugging enables two new values to be
1447     // returned by wait(): W_SEWTED and W_SFWTED, which indicate stops during
1448     // execution of exec and fork, respectively.
1449     ptrace(PT_MULTI, pid, 0, 1, 0);
1450
1451 //    cerr << "done with establishBaseAddrs; DATA hack=" << (void*)AIX_DATA_OFFSET_HACK
1452 //         << endl;
1453
1454     return true;
1455 }
1456
1457 //
1458 // dummy versions of OS statistics.
1459 //
1460 float OS::compute_rusage_cpu() { return(0.0); }
1461 float OS::compute_rusage_sys() { return(0.0); }
1462 float OS::compute_rusage_min() { return(0.0); }
1463 float OS::compute_rusage_maj() { return(0.0); }
1464 float OS::compute_rusage_swap() { return(0.0); }
1465 float OS::compute_rusage_io_in() { return(0.0); }
1466 float OS::compute_rusage_io_out() { return(0.0); }
1467 float OS::compute_rusage_msg_send() { return(0.0); }
1468 float OS::compute_rusage_sigs() { return(0.0); }
1469 float OS::compute_rusage_vol_cs() { return(0.0); }
1470 float OS::compute_rusage_inv_cs() { return(0.0); }
1471 float OS::compute_rusage_msg_recv() { return(0.0); }
1472
1473 int getNumberOfCPUs()
1474 {
1475   return(1);
1476 }
1477
1478 // #include "paradynd/src/metric.h"
1479 // #include "paradynd/src/costmetrics.h"
1480
1481 class instInstance;
1482
1483 // the following MUST become process member vrbles, since paradynd can have
1484 // more than one process active doing a fork!!!
1485 static bool seenForkTrapForParent = false;
1486 static bool seenForkTrapForChild  = false;
1487 static pid_t pidForParent;
1488 static pid_t pidForChild;
1489
1490 extern bool completeTheFork(process *, int);
1491    // in inst-power.C since class instPoint is too
1492
1493 static void process_whenBothForkTrapsReceived() {
1494    assert(seenForkTrapForParent);
1495    assert(seenForkTrapForChild);
1496
1497    forkexec_cerr << "welcome to: process_whenBothForkTrapsReceived" << endl;
1498
1499    process *parent = findProcess(pidForParent);
1500    assert(parent);
1501
1502    // complete the fork!
1503
1504    forkexec_cerr << "calling completeTheFork" << endl;
1505
1506    if (!completeTheFork(parent, pidForChild))
1507       assert(false);
1508
1509    // let's continue both processes
1510
1511    if (!parent->continueProc())
1512       assert(false);
1513
1514    // Note that we use PT_CONTINUE on the child instead of kill(pid, SIGSTOP).
1515    // Is this right?  (I think so)
1516
1517 //   int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, 0, 0);
1518    int ret = ptrace(PT_CONTINUE, pidForChild, (int*)1, SIGCONT, 0);
1519    if (ret == -1)
1520       assert(false);
1521
1522    seenForkTrapForParent = seenForkTrapForChild = false;
1523
1524    forkexec_cerr << "leaving process_whenBothForkTrapsReceived (parent & "
1525                  << "child running and should execute DYNINSTfork soon)"
1526                  << endl;
1527 }
1528
1529      //////////////////////////////////////////////////////////////////////////
1530      //Restore the base trampolines after they have been cleared by an AIX load
1531      //
1532 void resurrectBaseTramps(process *p)
1533 {
1534   if (! p) return;
1535
1536   vector<const instPoint*> allInstPoints = p->baseMap.keys();
1537
1538   extern void findAndReinstallBaseTramps(process *, vector<const instPoint*> &);
1539   findAndReinstallBaseTramps(p, allInstPoints);
1540
1541   vector<instInstance*> allInstInstances;             //Get all mini trampolines
1542   getAllInstInstancesForProcess(p, allInstInstances);
1543
1544   extern void reattachMiniTramps(process *, vector<instInstance*> &);
1545   reattachMiniTramps(p, allInstInstances);
1546 }
1547
1548
1549 bool handleAIXsigTraps(int pid, int status) {
1550     process *curr = findProcess(pid); // NULL for child of a fork
1551
1552     // see man page for "waitpid" et al for descriptions of constants such
1553     // as W_SLWTED, W_SFWTED, etc.
1554  
1555     if (WIFSTOPPED(status) && (WSTOPSIG(status)==SIGTRAP)
1556         && ((status & 0x7f) == W_SLWTED)) {
1557       //Process is stopped on a load.  AIX has reloaded the process image and
1558       //   the text segment heap has been cleared.
1559       if (curr) {
1560         curr->status_ = stopped;
1561         //fprintf(stderr, "Got load SIGTRAP from pid %d, PC=%x\n", pid,
1562         //                curr->currentPC());
1563         resurrectBaseTramps(curr);            //Restore base trampolines
1564         curr->continueProc();
1565       }
1566       return true;
1567     } // W_SLWTED (stopped-on-load)
1568
1569     // On AIX the processes will get a SIGTRAP when they execute a fork.
1570     // (Both the parent and the child will get this TRAP).
1571     // we must check for the SIGTRAP here, and handle the fork.
1572     // On aix the instrumentation on the parent will not be duplicated on 
1573     // the child, so we need to insert instrumentation again.
1574
1575     if (WIFSTOPPED(status) && WSTOPSIG(status)==SIGTRAP 
1576         && ((status & 0x7f) == W_SFWTED)) {
1577       if (curr) {
1578         // parent process.  Stay stopped until the child process has completed
1579         // calling "completeTheFork()".
1580         forkexec_cerr << "AIX: got fork SIGTRAP from parent process " << pid << endl;
1581
1582         curr->status_ = stopped;
1583
1584         seenForkTrapForParent = true;
1585         pidForParent = curr->getPid();
1586
1587         if (seenForkTrapForChild)
1588            process_whenBothForkTrapsReceived();
1589
1590         return true;
1591       } else {
1592         // child process
1593         forkexec_cerr << "AIX: got SIGTRAP from forked (child) process " << pid << endl;
1594
1595         // get process info
1596         struct procsinfo psinfo;
1597         pid_t process_pid = pid;
1598         if (getprocs(&psinfo, sizeof(psinfo), NULL, 0, &process_pid, 1) == -1) {
1599           assert(false);
1600           return false;
1601         }
1602
1603         assert((pid_t)psinfo.pi_pid == pid);
1604
1605         //string str = string("Parent of process ") + string(pid) + " is " +
1606         //               string(psinfo.pi_ppid) + "\n";
1607         //logLine(str.string_of());
1608
1609         seenForkTrapForChild = true;
1610         pidForChild = pid;
1611         if (seenForkTrapForParent) {
1612            assert((pid_t) pidForParent == (pid_t) psinfo.pi_ppid);
1613
1614            process_whenBothForkTrapsReceived();
1615         }
1616
1617         return true;
1618       } // child process
1619     } //  W_SFWTED (stopped-on-fork)
1620
1621     return false;
1622 }
1623
1624 string process::tryToFindExecutable(const string &progpath, int pid) {
1625    // returns empty string on failure
1626
1627    if (progpath.length() == 0)
1628       return "";
1629
1630    if (exists_executable(progpath)) // util lib
1631       return progpath;
1632
1633    return ""; // failure
1634 }
1635
1636 unsigned process::read_inferiorRPC_result_register(reg returnValReg) {
1637    assert(false); // not yet implemented!!!
1638    return 0;
1639 }
1640
1641 bool process::set_breakpoint_for_syscall_completion() {
1642    // We don't know how to do this on AIX
1643    return false;
1644 }
1645
1646 vector<int> process::getTOCoffsetInfo() const
1647 {
1648     int toc_offset;
1649     toc_offset = ((getImage())->getObject()).getTOCoffset();
1650     vector<int> dummy;
1651     //  st r2,20(r1)  ; 0x90410014 save toc register  
1652     dummy += 0x90410014; 
1653
1654     //  liu r2, 0x0000     ;0x3c40abcd reset the toc value to 0xabcdefgh
1655     dummy += (0x3c400000 | (toc_offset >> 16));
1656
1657     //  oril    r2, r2,0x0000   ;0x6042efgh
1658     dummy += (0x60420000 | (toc_offset & 0x0000ffff));
1659     return dummy;
1660 }