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