BPatch functions that block are now locked (on a finer grain than the rest of the...
[dyninst.git] / dyninstAPI / src / irix.C
1 /*
2  * Copyright (c) 1996-2004 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 // $Id: irix.C,v 1.86 2005/02/25 07:04:46 jaw Exp $
43
44 #include <sys/types.h>    // procfs
45 #include <sys/signal.h>   // procfs
46 #include <sys/fault.h>    // procfs
47 #include <sys/syscall.h>  // procfs
48 #include <sys/procfs.h>   // procfs
49 #include <unistd.h>       // getpid()
50 #include <sys/ucontext.h> // gregset_t
51
52 // #include "common/h/Types.h"
53
54 #include "dyninstAPI/src/arch-mips.h"
55 #include "dyninstAPI/src/inst-mips.h"
56 #include "dyninstAPI/src/symtab.h" // int_function
57 #include "dyninstAPI/src/instPoint.h"
58 #include "dyninstAPI/src/process.h"
59 #include "dyninstAPI/src/dyn_lwp.h"
60 #include "dyninstAPI/src/frame.h"
61 #include "dyninstAPI/src/instP.h"
62 #include "dyninstAPI/src/stats.h" // ptrace{Ops,Bytes}
63 #include "dyninstAPI/src/dyn_thread.h"
64 #include "common/h/pathName.h" // expand_tilde_pathname, exists_executable
65 #include "common/h/irixKludges.h" // PDYN_XXX
66 #include "common/h/Time.h"
67 #include "common/h/timing.h"
68 #include "dyninstAPI/src/signalhandler.h"
69 #include <limits.h>       // poll()
70 #include <stropts.h>      // poll()
71 #include <poll.h>         // poll()
72 #include <errno.h>        // errno
73 #include <stdio.h>        // perror()
74 #include <sys/sysmp.h>    // sysmp()
75 #include <sys/sysinfo.h>  // sysmp()
76 #include <string.h>       // strncmp()
77 #include <stdlib.h>       // getenv()
78 #include <termio.h>       // TIOCNOTTY
79 #include <sys/timers.h>   // PTIMER macros
80 #include <sys/hwperfmacros.h> // r10k_counter macros 
81 #include <sys/hwperftypes.h>  // r10k_counter types
82 #include <dlfcn.h>
83
84
85 extern unsigned enable_pd_inferior_rpc_debug;
86
87 #if ENABLE_DEBUG_CERR == 1
88 #define inferiorrpc_cerr if (enable_pd_inferior_rpc_debug) cerr
89 #else
90 #define inferiorrpc_cerr if (0) cerr
91 #endif /* ENABLE_DEBUG_CERR == 1 */
92
93 extern char *Bool[];
94 #ifndef BPATCH_LIBRARY
95 extern pdstring osName;
96 #endif
97
98 char* irixMPIappName;
99 bool attachToIrixMPIprocess(const pdstring &progpath, int pid, int afterAttach);
100 int masterMPIfd;
101 int masterMPIpid;
102
103 // constants derived from "tramp-mips.s" (must remain consistent)
104 // size of basetramp stack frame
105 // offset of save insns from basetramp "daddiu sp,sp,-512"
106 static const int bt_ra_save_off = (64 * INSN_SIZE); 
107 static const int bt_fp_save_off = (63 * INSN_SIZE); 
108 // basetramp stack frame slots
109 static const int bt_ra_slot = -512;
110 static const int bt_fp_slot = -504;
111 static const int bt_frame_size = 512;
112
113 void print_proc_flags(int fd)
114 {
115   prstatus stat;
116   ioctl(fd, PIOCSTATUS, &stat);
117   bperr( "flags: ");
118
119   if (stat.pr_flags & PR_STOPPED) bperr( "PR_STOPPED ");
120   if (stat.pr_flags & PR_ISTOP) bperr( "PR_ISTOP ");
121   if (stat.pr_flags & PR_DSTOP) bperr( "PR_DSTOP ");
122   if (stat.pr_flags & PR_STEP) bperr( "PR_STEP ");
123   if (stat.pr_flags & PR_ASLEEP) bperr( "PR_ASLEEP ");
124   if (stat.pr_flags & PR_PCINVAL) bperr( "PR_PCINVAL ");
125   //if (stat.pr_flags & PR_ISSYS) bperr( "PR_ISSYS ");
126   if (stat.pr_flags & PR_FORK) bperr( "PR_FORK ");
127   if (stat.pr_flags & PR_RLC) bperr( "PR_RLC ");
128   if (stat.pr_flags & PR_KLC) bperr( "PR_KLC ");
129   if (stat.pr_flags & PR_PTRACE) bperr( "PR_PTRACE ");
130
131   if (stat.pr_flags & PR_ISKTHREAD) bperr( "PR_ISKTHREAD ");
132   if (stat.pr_flags & PR_JOINTSTOP) bperr( "PR_JOINTSTOP ");
133   if (stat.pr_flags & PR_JOINTPOLL) bperr( "PR_JOINTPOLL ");
134   if (stat.pr_flags & PR_RETURN) bperr( "PR_RETURN ");
135   if (stat.pr_flags & PR_CKF) bperr( "PR_CKF ");
136
137   bperr( "\n");
138 }
139
140 void print_proc_regs(int fd)
141 {
142   gregset_t regs;
143   if (ioctl (fd, PIOCGREG, &regs) == -1) {
144     perror("ioctl(PIOCGREG)");
145     return;
146   }
147   char buf[32];
148   for (int i = 0; i < 32; i++) {
149     sprintf(buf, "$%s", reg_names[i]);
150     bperr( "%5s: %#10x %s", buf, (unsigned)regs[i],
151             (i % 4 == 3) ? ("\n") : (","));
152   }
153   bperr( "%5s: %#10x\n", "$pc", (unsigned)regs[CTX_EPC]);
154 }
155
156 void print_proc_pc(int fd)
157 {
158   gregset_t regs;
159   if (ioctl (fd, PIOCGREG, &regs) == -1) {
160     perror("ioctl(PIOCGREG)");
161     return;
162   }
163   bperr( "%5s: %#10x\n", "$pc", (unsigned)regs[CTX_EPC]);
164 }
165
166 bool dyn_lwp::readDataSpace(const void *inTraced, u_int nbytes, void *inSelf)
167 {
168    //bperr( ">>> process::readDataSpace_(%d@0x%016lx)\n", 
169    //        nbytes, inTraced);
170    ptraceOps++; 
171    ptraceBytes += nbytes;
172
173    if(lseek(get_fd(), (off_t)inTraced, SEEK_SET) == -1)
174    {
175       perror("process::readDataSpace_(lseek)");
176       return false;
177    }
178    
179    // TODO: check for infinite loop if read returns 0?
180    char *dst = (char *)inSelf;
181    for (int last, left = nbytes; left > 0; left -= last) {
182       if ((last = read(get_fd(), dst + nbytes - left, left)) == -1)
183       {
184          perror("process::readDataSpace_(read)");
185          return false;
186       } else if (last == 0) {
187          bperr( "process::readDataSpace_(read=%d@0x%016lx,"
188                  "left=%d/%d\n", last, inTraced, left, nbytes);
189          return false;
190       }
191    }
192    return true;
193 }
194
195 bool dyn_lwp::writeDataSpace(void *inTraced, u_int nbytes, const void *inSelf)
196 {
197    //bperr( ">>> process::writeDataSpace_(%d@0x%016lx)\n", 
198    //        nbytes, inTraced);
199    ptraceOps++; 
200    ptraceBytes += nbytes;
201
202    if(lseek(get_fd(), (off_t)inTraced, SEEK_SET) == -1)
203    {
204       perror("process::writeDataSpace_(lseek)");
205       return false;
206    }
207    
208    // TODO: check for infinite loop if write returns 0?
209    char *src = (char *)const_cast<void*>(inSelf);
210    for (int last, left = nbytes; left > 0; left -= last) {
211       if ((last = write(get_fd(), src + nbytes - left, left)) == -1)
212       {
213          perror("process::writeDataSpace_(write)");
214          return false;
215       }
216    }
217    return true;
218 }
219
220 bool dyn_lwp::writeTextWord(caddr_t inTraced, int data)
221 {
222    //bperr( ">>> process::writeTextWord_()\n");
223    return writeDataSpace(inTraced, INSN_SIZE, &data);
224 }
225
226 bool dyn_lwp::writeTextSpace(void *inTraced, u_int amount, const void *inSelf)
227 {
228    //bperr( ">>> process::writeTextSpace_()\n");
229    return writeDataSpace(inTraced, amount, inSelf);
230 }
231
232 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
233 bool dyn_lwp::readTextSpace(void *inTraced, u_int amount, const void *inSelf)
234 {
235    //bperr( ">>> process::readTextSpace_()\n");
236    return readDataSpace(inTraced, amount, (void *)inSelf);
237 }
238 #endif
239
240 bool dyn_lwp::getRegisters_(struct dyn_saved_regs *regs) 
241 {
242    if (ioctl(fd_, PIOCGREG, &(regs->intRegs)) == -1) {
243       perror("dyn_lwp::getRegisters(PIOCGREG)");
244       assert(errno != EBUSY); // procfs thinks the process is active
245       return false;
246    }
247    
248    if (ioctl(fd_, PIOCGFPREG, &(regs->fpRegs)) == -1) {
249       perror("dyn_lwp::getRegisters(PIOCGFPREG)");
250       assert(errno != EBUSY);  // procfs thinks the process is active
251       assert(errno != EINVAL); // no floating-point hardware
252       return false;
253    }
254    
255    return true;
256 }
257
258 bool dyn_lwp::restoreRegisters_(const struct dyn_saved_regs &regs)
259 {
260   if (ioctl(fd_, PIOCSREG, &(regs.intRegs)) == -1) {
261     perror("dyn_lwp::restoreRegisters(PIOCSREG)");
262     assert(errno != EBUSY); // procfs thinks the process is active
263     return false;
264   }  
265   if (ioctl(fd_, PIOCSFPREG, &(regs.fpRegs)) == -1) {
266     perror("dyn_lwp::restoreRegisters(PIOCSFPREG)");
267     assert(errno != EBUSY);  // procfs thinks the process is active
268     assert(errno != EINVAL); // no floating-point hardware
269     return false;
270   }
271
272   return true;
273 }
274
275 bool dyn_lwp::changePC(Address addr, struct dyn_saved_regs *regs)
276 {
277
278   /* copy integer registers from register buffer */
279   gregset_t intRegs;
280
281   if (regs) {
282     // FUGGLY someone please fix this (as in Solaris)
283     memcpy(&intRegs, &(regs->intRegs), sizeof(gregset_t));
284   }
285   else {
286     if (ioctl(fd_, PIOCGREG, &intRegs) == -1) {
287       perror("dyn_lwp::changePC(PIOCGREG)");
288       assert(errno != EBUSY); // procfs thinks the process is active
289       return false;
290     }
291   }
292   intRegs[PROC_REG_PC] = addr; // set PC
293   
294   if (ioctl(fd_, PIOCSREG, &intRegs) == -1) {
295     perror("dyn_lwp::changePC(PIOCSREG)");
296     assert(errno != EBUSY); // procfs thinks the process is active
297     return false;
298   }
299   
300   return true;
301 }
302
303 bool process::isRunning_() const
304 {
305   //bperr( ">>> process::isRunning_()\n");
306   prstatus status;
307   if (ioctl(getRepresentativeLWP()->get_fd(), PIOCSTATUS, &status) == -1) {
308     perror("process::isRunning_()");
309     assert(0);
310   }
311
312   // TODO - check for discrepancy with "status_" member?
313   if (status.pr_flags & PR_STOPPED) return false;
314
315   return true;
316 }
317
318 void OS::osTraceMe(void)
319 {
320   char procName[128];
321   sprintf(procName,"/proc/%05d", (int)getpid());
322   //bperr( ">>> OS::osTraceMe(%s)\n", procName);
323   int fd = P_open(procName, O_RDWR, 0);
324   if (fd < 0) {
325     bperr( "osTraceMe: open failed: %s\n", sys_errlist[errno]); 
326     fflush(stderr);
327     P__exit(-1); // must use _exit here.
328   }
329
330   // Procfs on Irix sets the "run-on-last-close" flag (PR_RLC) by default.
331   // This flag needs to be unset to avoid the PIOCSEXIT trace (below) from
332   // being lost when the child closes the proc file descriptor to itself.
333   /* reset "run-on-last-close" flag */
334   long flags = PR_RLC;
335   if (ioctl(fd, PIOCRESET, &flags) < 0) {
336     bperr( "osTraceMe: PIOCRESET failed: %s\n", sys_errlist[errno]); 
337     fflush(stderr);
338     P__exit(-1); // must use _exit here.
339   };
340
341   /* set a breakpoint at the exit of execv/execve */
342   sysset_t exitSet;
343   premptyset(&exitSet);
344   (void)praddset(&exitSet, SYS_execve);
345   if (ioctl(fd, PIOCSEXIT, &exitSet) < 0) {
346     bperr( "osTraceMe: PIOCSEXIT failed: %s\n", sys_errlist[errno]); 
347     fflush(stderr);
348     P__exit(-1); // must use _exit here.
349   }
350
351   errno = 0;
352   close(fd);
353 }
354
355 procSyscall_t decodeSyscall(process *p, procSignalWhat_t syscall)
356 {
357     if (syscall == SYS_fork)
358         return procSysFork;
359     if (syscall == SYS_execve)
360         return procSysExec;
361     if (syscall == SYS_exit)
362         return procSysExit;
363     return procSysOther;
364 }
365
366 int decodeProcStatus(process *proc,
367                      procProcStatus_t status,
368                      procSignalWhy_t &why,
369                      procSignalWhat_t &what,
370                      procSignalInfo_t &info) {
371     
372     switch (status.pr_why) {
373   case PR_SIGNALLED:
374       why = procSignalled;
375       what = status.pr_what;
376       break;
377   case PR_SYSENTRY:
378       why = procSyscallEntry;
379       what = status.pr_what;
380       // HACK: We need to know the exec'ed file name
381       // (on IRIX) so that we can find the binary to parse.
382       // We get this by checking the first argument of the exec
383       // call and storing it until the post-exec handling.
384       // Problem is, we can't just check the first argument:
385       // the function call part of the exec appears to be doing
386       // some modifications and so the argument to exec() is not the
387       // same as the argument to the exec syscall. By experimentation
388       // I've discovered register 18 holds the original argument.
389       // This is considered a hack and should be fixed by someone more
390       // clueful about IRIX than I am.
391       if (decodeSyscall(proc, what) == procSysExec)
392           info = (procSignalInfo_t) status.pr_reg[18];
393       else
394           info = (procSignalInfo_t) status.pr_reg[REG_A0];
395       break;
396   case PR_SYSEXIT:
397       why = procSyscallExit;
398       what = status.pr_what;
399       info = (procSignalInfo_t) status.pr_reg[PROC_REG_RV];
400       break;
401   case PR_REQUESTED:
402       // We don't expect PR_REQUESTED in the signal handler
403       assert(0 && "PR_REQUESTED not handled");
404       break;
405   case PR_JOBCONTROL:
406   case PR_FAULTED:
407   default:
408       assert(0);
409       break;
410     }
411     return 1;
412 }
413
414
415 // Get and decode a signal for a process
416 // We poll /proc for process events, and so it's possible that
417 // we'll get multiple hits. In this case we return one and queue
418 // the rest. Further calls of decodeProcessEvent will burn through
419 // the queue until there are none left, then re-poll.
420 // Return value: 0 if nothing happened, or process pointer
421
422 bool signalHandler::checkForProcessEvents(pdvector<procevent *> *events,
423                                           int wait_arg, int &timeout)
424 {
425     extern pdvector<process*> processVec;
426     static struct pollfd fds[OPEN_MAX];  // argument for poll
427     // Number of file descriptors with events pending
428     static int selected_fds = 0; 
429     // The current FD we're processing.
430     static int curr = 0;
431     prstatus_t stat;
432     bool any_active_procs = false;
433     procSignalWhy_t  why  = procUndefined;
434     procSignalWhat_t what = 0;
435     procSignalInfo_t info = 0;
436
437     if (selected_fds == 0) {
438         for (unsigned u = 0; u < processVec.size(); u++) {
439             //bperr("checking %d\n", processVec[u]->getPid());
440             if (processVec[u] && 
441                 (processVec[u]->status() == running || 
442                  processVec[u]->status() == neonatal)) {
443                 if (wait_arg == -1 ||
444                     processVec[u]->getPid() == wait_arg) {
445                     any_active_procs = true;
446                     fds[u].fd = processVec[u]->getRepresentativeLWP()->get_fd();
447                 }
448             } else {
449                 fds[u].fd = -1;
450             }   
451             // IRIX note:  Dave Anderson at SGI seems to think that it is
452             // "ill-defined" what band signals show up in.  He suggests
453             // that we do something like
454             //    fds[i].events = POLLPRI | POLLRDBAND;
455             // This seems to turn up a bunch of "false positives" in
456             // polling, though, which is why we're not doing it.
457             //  -- willb, 10/25/2000
458             fds[u].events = POLLPRI;
459             fds[u].revents = 0;
460         }
461         //  Add file descriptor for MPI master process
462         if ( masterMPIfd != -1 )
463         {
464             any_active_procs = true;
465             fds[processVec.size()].fd = masterMPIfd;
466             fds[processVec.size()].events = POLLPRI;
467             fds[processVec.size()].revents = 0;
468         }
469
470         if (!any_active_procs) {
471             // Avoid blocking on nothing
472             return false;
473         }
474         
475         selected_fds = poll(fds, processVec.size(), timeout);
476         
477         if (selected_fds <= 0) {
478             if (selected_fds < 0) {
479                 bperr( "decodeProcessEvent: poll failed: %s\n", sys_errlist[errno]);
480                 selected_fds = 0;
481             }
482             else {
483               //  we have timed out, indicate this
484               timeout = 0;
485             }
486             return false;
487         }
488         
489         // Reset the current pointer to the beginning of the poll list
490         curr = 0;
491     } // if selected_fds == 0
492     // We have one or more events to work with.
493     while (fds[curr].revents == 0) {
494         // skip
495         ++curr;
496     }
497     // fds[curr] has an event of interest
498     prstatus_t procstatus;
499     process *currProcess = processVec[curr];
500     
501     if (fds[curr].revents & POLLHUP) {
502         // True if the process exited out from under us
503         int status;
504         int ret;
505         if (fds[curr].fd == masterMPIfd) {
506             close(fds[curr].fd);
507             masterMPIfd = -1;
508         }
509         else {
510             // Process exited, get its return status
511             do {
512                 ret = waitpid(currProcess->getPid(), &status, 0);
513             } while ((ret < 0) && (errno == EINTR));
514             if (ret < 0) {
515                 // This means that the application exited, but was not our child
516                 // so it didn't wait around for us to get it's return code.  In
517                 // this case, we can't know why it exited or what it's return
518                 // code was.
519                 ret = currProcess->getPid();
520                 status = 0;
521                 // is this the bug??
522                 // processVec[curr]->continueProc_();
523             }
524             if (!decodeWaitPidStatus(currProcess, status, &why, &what)) {
525                 cerr << "decodeProcessEvent: failed to decode waitpid return" << endl;
526                 return false;
527             }
528         }
529     } else {
530         // Real return from poll
531         if (ioctl(currProcess->getRepresentativeLWP()->get_fd(), 
532                   PIOCSTATUS, 
533                   &procstatus) != -1) {
534             // Check if the process is stopped waiting for us
535             if (procstatus.pr_flags & PR_STOPPED ||
536                 procstatus.pr_flags & PR_ISTOP) {
537                 if (!decodeProcStatus(currProcess, procstatus, why, what,info))
538                 {
539                    return false;
540                 }
541             }
542         }
543         else {
544             // get_status failed, probably because the process doesn't exist
545         }
546     }
547
548     if (currProcess) {
549         procevent *new_event = new procevent;
550         new_event->proc = currProcess;
551         new_event->lwp  = currProcess->getRepresentativeLWP();
552         new_event->why  = why;
553         new_event->what = what;
554         new_event->info = info;
555         (*events).push_back(new_event);
556
557         // Got a signal, process is stopped.
558         currProcess->set_status(stopped);
559     }
560
561     // Skip this FD the next time through
562     --selected_fds;
563     ++curr;    
564     return true;
565     
566
567
568 // TODO: this ignores the "sig" argument
569 bool dyn_lwp::continueLWP_(int signalToContinueWith)
570 {
571    ptraceOps++; 
572    ptraceOtherOps++;
573
574    prstatus_t stat;
575    if (ioctl(get_fd(), PIOCSTATUS, &stat) == -1) {
576       perror("dyn_lwp::continueProc_(PIOCSTATUS)");
577       return false;
578    }
579    
580    if (!(stat.pr_flags & (PR_STOPPED | PR_ISTOP))) {
581       // not stopped
582       bperr( "continueProc_(): process not stopped\n");
583       print_proc_flags(get_fd());
584       return false;
585    }
586   
587    void *arg3;
588    prrun_t run;
589    if(signalToContinueWith == dyn_lwp::NoSignal) {
590       run.pr_flags = PRCSIG; // clear current signal
591       arg3 = &run;
592    }
593    else arg3 = NULL;
594
595    if (ioctl(get_fd(), PIOCRUN, arg3) == -1) {
596       perror("dyn_lwp::continueProc_(PIOCRUN)");
597       return false;
598    }
599    
600    return true;
601 }
602
603 bool process::heapIsOk(const pdvector<sym_data>&findUs)
604 {
605   if (!(mainFunction = findOnlyOneFunction("main")) &&
606       !(mainFunction = findOnlyOneFunction("_main"))) {
607     bperr( "process::heapIsOk(): failed to find \"main\"\n");
608     return false;
609   }
610
611   for (unsigned i = 0; i < findUs.size(); i++) {
612     const pdstring &name = findUs[i].name;
613     /*
614     Address addr = lookup_fn(this, name);
615     if (!addr && findUs[i].must_find) {
616       bperr( "process::heapIsOk(): failed to find \"%s\"\n", name.c_str());
617       return false;
618     }
619     */
620   }
621
622
623   return true;
624 }
625
626 bool dyn_lwp::executingSystemCall()
627 {
628    bool ret = false;
629    prstatus stat;
630    if (ioctl(fd_, PIOCSTATUS, &stat) == -1) {
631        perror("process::executingSystemCall(PIOCSTATUS)");
632        assert(0);
633    }
634    if (stat.pr_syscall > 0 && 
635        stat.pr_why != PR_SYSEXIT) {
636        inferiorrpc_cerr << "pr_syscall=" << stat.pr_syscall << endl;
637        ret = true;
638    }
639
640    return ret;
641 }
642
643 Address dyn_lwp::readRegister(Register retval_reg)
644 {
645   gregset_t regs;
646
647   assert(retval_reg < NGREG);
648
649   if (ioctl (fd_, PIOCGREG, &regs) == -1) {
650     perror("process::_inferiorRPC_result_registerread(PIOCGREG)");
651     return 0;
652   }
653   return regs[retval_reg];
654 }
655
656 static const Address lowest_addr = 0x00400000;
657 void process::inferiorMallocConstraints(Address near, Address &lo, Address &hi,
658                                         inferiorHeapType type)
659 {
660   if (near)
661     {
662       lo = region_lo(near);
663       hi = region_hi(near);  
664       // avoid mapping the zero page
665       if (lo < lowest_addr) lo = lowest_addr;
666     }
667 }
668
669 void process::inferiorMallocAlign(unsigned &size)
670 {
671   // quadword-aligned (stack alignment)
672   unsigned align = 16;
673   if (size % align) size = ((size/align)+1)*align;
674 }
675
676 bool dyn_lwp::stop_()
677 {
678   //bperr( ">>> process::pause_()\n");
679   ptraceOps++; 
680   ptraceOtherOps++;
681
682   int ret;
683   if ((ret = ioctl(get_fd(), PIOCSTOP, 0)) == -1) {
684     perror("process::pause_(PIOCSTOP)");
685     sprintf(errorLine, "warning: PIOCSTOP failed in \"pause_\", errno=%i\n", errno);
686     logLine(errorLine);
687   }
688
689   return (ret != -1);
690 }
691
692
693 bool dyn_lwp::waitUntilStopped() {
694    return true;
695 }
696
697 bool process::waitUntilStopped() {
698    return true;
699 }
700
701 int getNumberOfCPUs() 
702 {
703   // see sysmp(2) man page
704   int ret = sysmp(MP_NPROCS);
705   //bperr( ">>> getNumberOfCPUs(%i)\n", ret);
706   return ret;
707 }
708
709
710 syscallTrap *process::trapSyscallExitInternal(Address syscall) {
711     syscallTrap *trappedSyscall = NULL;
712     
713     // First, the cross-platform bit. If we're already trapping
714     // on this syscall, then increment the reference counter
715     // and return
716     
717     for (unsigned iter = 0; iter < syscallTraps_.size(); iter++) {
718         if (syscallTraps_[iter]->syscall_id == (int) syscall) {
719             trappedSyscall = syscallTraps_[iter];
720             break;
721         }
722     }
723     if (trappedSyscall) {
724         // That was easy...
725         trappedSyscall->refcount++;
726         return trappedSyscall;
727     }
728     else {
729         trappedSyscall = new syscallTrap;
730         trappedSyscall->refcount = 1;
731         trappedSyscall->syscall_id = (int) syscall;
732         sysset_t save_exitset;
733         dyn_lwp *replwp = getRepresentativeLWP();
734         if (-1 == ioctl(replwp->get_fd(), PIOCGEXIT, &save_exitset))
735             return NULL;
736
737         if (prismember(&save_exitset, trappedSyscall->syscall_id))
738             trappedSyscall->orig_setting = 1;
739         else
740             trappedSyscall->orig_setting = 0;
741     
742         praddset(&save_exitset, trappedSyscall->syscall_id);
743         
744         if (-1 == ioctl(replwp->get_fd(), PIOCSEXIT, &save_exitset))
745             return NULL;
746         
747         syscallTraps_ += trappedSyscall;
748         return trappedSyscall;
749     }
750     return NULL;
751 }
752
753 bool process::clearSyscallTrapInternal(syscallTrap *trappedSyscall) {
754     // Decrement the reference count, and if it's 0 remove the trapped
755     // system call
756     assert(trappedSyscall->refcount > 0);
757     
758     trappedSyscall->refcount--;
759     if (trappedSyscall->refcount > 0) {
760         return true;
761     }
762     // Erk... it hit 0. Remove the trap at the system call
763     dyn_lwp *replwp = getRepresentativeLWP();
764     sysset_t save_exitset;
765     if (-1 == ioctl(replwp->get_fd(), PIOCGEXIT, &save_exitset))
766         return false;
767     
768     if (trappedSyscall->orig_setting == 0)
769         prdelset(&save_exitset, trappedSyscall->syscall_id);
770     
771     if (-1 == ioctl(replwp->get_fd(), PIOCSEXIT, &save_exitset))
772         return false;
773  
774     // Now that we've reset the original behavior, remove this
775     // entry from the vector
776
777     pdvector<syscallTrap *> newSyscallTraps;
778     for (unsigned iter = 0; iter < syscallTraps_.size(); iter++) {
779         if (trappedSyscall != syscallTraps_[iter])
780             newSyscallTraps.push_back(syscallTraps_[iter]);
781     }
782     syscallTraps_ = newSyscallTraps;
783     /*
784     // Now that we've reset the original behavior, remove this
785     // entry from the vector
786     for (unsigned iter = 0; iter < syscallTraps_.size(); iter++) {
787         if (trappedSyscall == syscallTraps_[iter]) {
788 //            syscallTraps_.removeByIndex(iter);
789             syscallTraps_.erase( iter, iter );
790             break;
791         }
792     }
793     */
794     delete trappedSyscall;
795     
796     return true;
797 }
798
799 Address dyn_lwp::getCurrentSyscall() {
800     
801     prstatus theStatus;
802     if (ioctl(fd_, PIOCSTATUS, &theStatus) == -1) {
803         return 0;
804     }
805     return theStatus.pr_syscall;
806     
807 }
808
809 bool dyn_lwp::stepPastSyscallTrap() {
810     // Don't believe we have to do this
811     return true;
812 }
813
814 // 0: not reached syscall trap
815 // 1: lwp that isn't blocking reached syscall trap
816 // 2: lwp that is blocking reached syscall trap
817 int dyn_lwp::hasReachedSyscallTrap() {
818     prstatus theStatus;
819     if (ioctl(fd_, PIOCSTATUS, &theStatus) == -1) {
820         return 0;
821     }
822     if (theStatus.pr_why != PR_SYSEXIT) {
823         return 0;
824     }
825     Address syscall = theStatus.pr_what;
826     
827     if (trappedSyscall_ && syscall == trappedSyscall_->syscall_id) {
828         return 2;
829     }
830     
831     // Unfortunately we can't check a recorded system call trap,
832     // since we don't have one saved. So do a scan through all traps the
833     // process placed
834     if (proc()->checkTrappedSyscallsInternal(syscall))
835         return 1;
836     
837     return 0;
838 }
839
840 bool process::dumpCore_(const pdstring coreFile)
841 {
842   //bperr( ">>> process::dumpCore_()\n");
843   bool ret;
844 #ifdef BPATCH_LIBRARY
845   ret = dumpImage(coreFile);
846 #else
847   ret = dumpImage();
848 #endif
849   return ret;
850 }
851
852 dyn_lwp *process::createRepresentativeLWP() {
853    // don't register the representativeLWP in real_lwps since it's not a true
854    // lwp
855    representativeLWP = createFictionalLWP(0);
856    return representativeLWP;
857 }
858
859 terminateProcStatus_t process::terminateProc_()
860 {
861    // these next two lines are a hack used to get the poll call initiated
862    // by checkForAndHandleProcessEvents() in process::terminateProc to
863    // still check process for events if it was previously stopped
864    if(status() == stopped)
865       status_ = running;
866
867    if (kill(getPid(), 9)) {
868      if (errno == ESRCH)
869        return alreadyTerminated;
870      else
871        return terminateFailed;
872    }
873    return terminateSucceeded;
874 }
875
876 pdstring process::tryToFindExecutable(const pdstring &progpath, int /*pid*/)
877 {
878   //bperr( ">>> process::tryToFindExecutable(%s)\n", progpath.c_str());
879   pdstring ret = "";
880   
881   // attempt #1: expand_tilde_pathname()
882   ret = expand_tilde_pathname(progpath);
883   //bperr( "  expand_tilde => \"%s\"\n", ret.c_str());
884   if (exists_executable(ret)) return ret;
885   
886   // TODO: any other way to find executable?
887   // no procfs info available (argv, cwd, env) so we're stuck
888   return "";
889 }
890
891
892
893 // HERE BE DRAGONS
894
895
896
897 // TODO: this is a lousy implementation
898 #ifdef BPATCH_LIBRARY
899 bool process::dumpImage(pdstring outFile) {
900 #else
901 bool process::dumpImage() {
902   char buf[512];
903   sprintf(buf, "image.%d", pid);
904   pdstring outFile = buf;
905 #endif
906   //bperr( "!!! process::dumpImage(%s)\n", outFile.c_str());
907   
908   // copy and open file
909   image *img = getImage();
910   pdstring imgFile = img->file();
911   char buf1[1024];
912   sprintf(buf1, "cp %s %s", imgFile.c_str(), outFile.c_str());
913   system(buf1);
914   int fd = open(outFile.c_str(), O_RDWR, 0);
915   if (fd < 0) return false;
916
917   // overwrite ".text" section with runtime contents
918
919   bool is_elf64 = img->getObject().is_elf64();
920   Elf *elfp = elf_begin(fd, ELF_C_READ, 0);
921   assert(elfp);
922   int e_shstrndx;
923   if (is_elf64) {
924
925     Elf64_Ehdr *ehdrp = elf64_getehdr(elfp);
926     assert(ehdrp);
927     e_shstrndx = ehdrp->e_shstrndx;
928
929   } else { // 32-bit
930
931     Elf32_Ehdr *ehdrp = elf32_getehdr(elfp);
932     assert(ehdrp);
933     e_shstrndx = ehdrp->e_shstrndx;
934
935   }
936   Elf_Scn *shstrscnp = elf_getscn(elfp, e_shstrndx);
937   assert(shstrscnp);
938   Elf_Data *shstrdatap = elf_getdata(shstrscnp, 0);
939   assert(shstrdatap);
940   char *shnames = (char *)shstrdatap->d_buf;
941
942   Address txtAddr = 0;
943   int txtLen = 0;
944   int txtOff = 0;
945   Elf_Scn *scn = 0;
946   while ((scn = elf_nextscn(elfp, scn)) != 0) {
947     pdElfShdr pd_shdr(scn, is_elf64);
948     char *name = (char *)&shnames[pd_shdr.pd_name];
949     if (strcmp(name, ".text") == 0) {
950       txtOff = pd_shdr.pd_offset;
951       txtLen = pd_shdr.pd_size;
952       txtAddr = pd_shdr.pd_addr;
953       break;
954     }
955   }
956    
957   if (txtLen > 0) {
958     char *buf2 = new char[txtLen];
959     // TODO: readTextSpace_() only defined for BPATCH_MUTATIONS_ACTIVE
960     if (!(readDataSpace((void *)txtAddr, txtLen, buf2, false))) {
961       delete [] buf2;
962       return false;
963     }
964     lseek(fd, txtOff, SEEK_SET);
965     write(fd, buf2, txtLen);
966     close(fd);
967     delete [] buf2;
968   }
969   
970   return true;
971 }
972
973 #if 0 
974 // Make emacs happy...
975 }
976 #endif
977
978 /* 
979  * Syscall tracing wrappers
980  */
981 bool process::get_entry_syscalls(sysset_t *entries) {
982     dyn_lwp *replwp = getRepresentativeLWP();    
983     if (ioctl(replwp->get_fd(), PIOCGENTRY, entries) < 0) {
984         perror("get_entry_syscalls");
985         return false;
986     }
987     return true;
988 }
989
990 bool process::set_entry_syscalls(sysset_t *entries) {
991     dyn_lwp *replwp = getRepresentativeLWP();    
992     if (ioctl(replwp->get_fd(), PIOCSENTRY, entries) < 0) {
993         perror("set_entry_syscalls");
994         return false;
995     }
996     return true;
997 }
998
999 bool process::get_exit_syscalls(sysset_t *exits) {
1000     dyn_lwp *replwp = getRepresentativeLWP();    
1001     if (ioctl(replwp->get_fd(), PIOCGEXIT, exits) < 0) {
1002         perror("get_exit_syscalls");
1003         return false;
1004     }
1005     return true;
1006 }
1007
1008 bool process::set_exit_syscalls(sysset_t *exits) {
1009     dyn_lwp *replwp = getRepresentativeLWP();
1010     if (ioctl(replwp->get_fd(), PIOCSEXIT, exits) < 0) {
1011         perror("set_exit_syscalls");
1012         return false;
1013     }
1014     return true;
1015 }
1016
1017 /*
1018  * Use by dyninst to set events we care about from procfs
1019  *
1020  */
1021
1022 bool process::setProcessFlags()
1023 {
1024     
1025     long flags = PR_FORK;
1026
1027     dyn_lwp *replwp = getRepresentativeLWP();    
1028     if (ioctl(replwp->get_fd(), PIOCSET, &flags) < 0) {
1029         bperr( "attach: PIOCSET failed: %s\n", sys_errlist[errno]);
1030         return false;
1031     }
1032     
1033     sigset_t sigs;
1034     premptyset(&sigs);
1035     (void)praddset(&sigs, SIGSTOP);
1036     (void)praddset(&sigs, SIGTRAP);
1037     (void)praddset(&sigs, SIGILL);
1038 #if defined(bug_irix_broken_sigstop)
1039     // we need to use SIGEMT for breakpoints in IRIX due to a bug with
1040     // tracing SIGSTOP in a process and then waitpid()ing for it
1041     // --wcb 10/4/2000
1042     (void)praddset(&sigs, SIGEMT);
1043 #endif
1044     if (ioctl(replwp->get_fd(), PIOCSTRACE, &sigs) < 0) {
1045         perror("process::attach(PIOCSTRACE)");
1046         return false;
1047     }
1048     
1049     return true;
1050 }
1051
1052 bool process::unsetProcessFlags() 
1053 {
1054     bool ret = true;
1055 // signal handling
1056     sigset_t sigs;
1057     premptyset(&sigs);
1058     dyn_lwp *replwp = getRepresentativeLWP();
1059     if (ioctl(replwp->get_fd(), PIOCSTRACE, &sigs) == -1) {
1060         perror("process::unsetProcessFlags(PIOCSTRACE)");
1061         ret = false;
1062     }
1063     long flags = PR_FORK;
1064     if (ioctl(replwp->get_fd(), PIOCRESET, &flags) == -1) {
1065         perror("process::unsetProcessFlags(PIOCRESET)");
1066         ret = false;
1067     }
1068     return ret;
1069 }
1070
1071
1072 // getActiveFrame(): populate Frame object using toplevel frame
1073 Frame dyn_lwp::getActiveFrame()
1074 {
1075   Address pc = 0, fp = 0, sp = 0;
1076   // Get current register values
1077   gregset_t regs;
1078   if (ioctl(fd_, PIOCGREG, &regs) == -1) {
1079     perror("Frame::Frame(PIOCGREG)");
1080     return Frame();
1081   }
1082   
1083   pc = regs[PROC_REG_PC];
1084   sp = regs[PROC_REG_SP];
1085   fp = regs[PROC_REG_FP];
1086
1087   // sometimes the actual $fp is zero
1088   // (kludge for stack walk code)
1089   if (fp == 0) fp = sp;
1090
1091   return Frame(pc, fp, sp, proc_->getPid(), NULL, NULL, this, true);
1092
1093 }
1094  
1095 static bool basetrampRegSaved(Address pc, Register reg,
1096                               const instPoint *ip,
1097                               trampTemplate *bt,
1098                               miniTrampHandle *mt)
1099 {
1100   if (!ip) return false;
1101   if (mt) return true;
1102   assert(bt);
1103
1104   Address save_off;
1105   switch(reg) {
1106   case REG_RA:
1107     save_off = bt_ra_save_off;
1108     break;
1109   case REG_S8:
1110     save_off = bt_fp_save_off;
1111     break;
1112   default:
1113     assert(0);
1114   }
1115
1116   if (pc >  bt->baseAddr + bt->savePreInsOffset + save_off && 
1117       pc <= bt->baseAddr + bt->restorePreInsOffset) {
1118     return true;
1119   }
1120   if (pc >  bt->baseAddr + bt->savePostInsOffset + save_off && 
1121       pc <= bt->baseAddr + bt->restorePostInsOffset) {
1122     return true;
1123   }
1124
1125   return false;
1126 }
1127
1128 // TODO: need dataflow, ($pc < saveInsn) insufficient
1129 Frame Frame::getCallerFrame()
1130 {
1131   // check for active instrumentation
1132   // (i.e. $pc in native/basetramp/minitramp code)
1133   
1134   codeRange *range = getRange();
1135   if (!range) {
1136     // We have no idea where we are....
1137     return Frame();
1138   }
1139     
1140     trampTemplate *bt = range->is_basetramp();
1141     miniTrampHandle  *mt = range->is_minitramp();
1142     const instPoint     *ip = NULL;
1143     if (mt) bt = mt->baseTramp;
1144     if (bt) ip = bt->location;
1145     int_function *callee = range->is_function();
1146     Address pc_off;
1147     if (!callee && ip)
1148         callee = (int_function *) ip->pointFunc();
1149
1150     // calculate runtime address of callee fn
1151     if (!callee) {
1152         bperr( "!!! <0x%016lx:???> unknown callee\n", pc_);
1153         return Frame(); // zero frame
1154     }
1155
1156     if (ip) {
1157         pc_off = ip->pointAddr() - callee->getEffectiveAddress(getProc());
1158     }
1159     else {
1160         pc_off = pc_ - callee->getEffectiveAddress(getProc());
1161     }
1162     
1163     // frame pointers for native and basetramp frames
1164     Address fp_bt = sp_;
1165     if (bt) {
1166         fp_bt += bt_frame_size;
1167     }
1168     Address fp_native = fp_bt;
1169
1170     if (!bt) {
1171         fp_native += callee->frame_size;
1172     }
1173     // override calculated $fp if frame pointer conventions used
1174     if (callee->uses_fp) fp_native = saved_fp;
1175     
1176     // which frames is $ra saved in?
1177     int_function::regSave_t &ra_save = callee->reg_saves[REG_RA];
1178     bool ra_saved_native = (ra_save.slot != -1 && pc_off > ra_save.insn);
1179     bool ra_saved_bt = basetrampRegSaved(pc_, REG_RA, ip, bt, mt);
1180     
1181     // which frames is $fp saved in?
1182     int_function::regSave_t &fp_save = callee->reg_saves[REG_S8];
1183     bool fp_saved_native = (fp_save.slot != -1 && pc_off > fp_save.insn);
1184     bool fp_saved_bt = basetrampRegSaved(pc_, REG_S8, ip, bt, mt);
1185     
1186     
1187     // find caller $pc (callee $ra)
1188     Address ra;
1189     Address ra_addr = 0;
1190     char ra_debug[256];
1191     sprintf(ra_debug, "<unknown>");
1192     
1193     if (!bt && ra_saved_native) {
1194         // $ra saved in native frame
1195         ra_addr = fp_native + ra_save.slot;
1196         ra = readAddressInMemory(getProc(), ra_addr, ra_save.dword);
1197         sprintf(ra_debug, "[$fp - %i]", -ra_save.slot);
1198     } else if (bt && ra_saved_bt) {
1199         // $ra saved in basetramp frame
1200         ra_addr = fp_bt + bt_ra_slot;
1201         ra = readAddressInMemory(getProc(), ra_addr, true);
1202         sprintf(ra_debug, "[$fp - %i]", -bt_ra_slot);
1203
1204         // The basetramp's caller might have set up a stack frame.
1205         // Attempt to detect, and remove it if necessary.
1206         //
1207         // NOTE: This will not work for tracing through instrumented
1208         // leaf functions.  More complex code analysis would be needed.
1209         if (ra_saved_native) {
1210             Address fp_tmp = fp_bt + callee->frame_size;
1211             Address ra_addr_tmp = fp_tmp + ra_save.slot;
1212             Address ra_tmp = readAddressInMemory(getProc(), ra_addr_tmp, true);
1213
1214             if (ra_tmp == ra) {
1215                 // Stack frame for caller was active.
1216                 // Remove it from consideration.
1217                 fp_native += callee->frame_size;
1218             }
1219         }
1220
1221     } else {
1222         // $ra not saved in any frame
1223         // try to read $ra from registers (toplevel only)
1224         if (uppermost_) {
1225             // $ra in live register
1226             gregset_t regs;
1227             unsigned fd;
1228             if (lwp_)
1229                 fd = lwp_->get_fd();
1230             else
1231                 fd = getProc()->getRepresentativeLWP()->get_fd();
1232             if (ioctl(fd, PIOCGREG, &regs) == -1) {
1233                 perror("process::readDataFromFrame(PIOCGREG)");
1234                 return Frame(); // zero frame
1235             }
1236             ra = regs[PROC_REG_RA];
1237             sprintf(ra_debug, "regs[ra]");
1238         } else {
1239             /*
1240               // debug
1241               if (callee->prettyName() != "main" &&
1242               callee->prettyName() != "__start")
1243               bperr( "!!! <0x%016lx:\"%s\"> $ra not saved\n",
1244               pc_adj, callee->prettyName().c_str());
1245             */
1246             // $ra cannot be found (error)
1247             return Frame(); // zero frame
1248         }
1249     }
1250     
1251     // determine location of caller $pc (native code, basetramp, minitramp)
1252     instPoint *ip2 = NULL;
1253     trampTemplate *bt2 = NULL;
1254     miniTrampHandle *mt2 = NULL;
1255     int_function *caller = NULL;
1256     range = getProc()->findCodeRangeByAddress(ra);
1257     if (range) {
1258         mt2 = range->is_minitramp();
1259         bt2 = range->is_basetramp();
1260         caller = range->is_function();
1261     }
1262     if (mt2) bt2 = mt2->baseTramp;
1263     if (bt2) ip2 = (instPoint *) bt2->location;
1264     if (!caller && ip2)
1265         caller = (int_function *)ip2->pointFunc();
1266     
1267     // Check for saved $fp value
1268     Address fp2;
1269     Address fp_addr = 0;
1270     char fp_debug[256];
1271     sprintf(fp_debug, "<unknown>");
1272     if (!bt && fp_saved_native) {
1273         // $fp saved in native frame
1274         fp_addr = fp_native + fp_save.slot;
1275         fp2 = readAddressInMemory(getProc(), fp_addr, fp_save.dword);
1276         sprintf(fp_debug, "[$fp - %i]", -fp_save.slot);
1277         //bperr( "  read fp_saved_native at %x from fp_native %x and slot %d\n", fp_addr, fp_native, fp_save.slot);
1278     } else if (bt && fp_saved_bt) {
1279         // $ra saved in basetramp frame
1280         fp_addr = fp_bt + bt_fp_slot;
1281         fp2 = readAddressInMemory(getProc(), fp_addr, true);
1282         sprintf(fp_debug, "[$fp - %i]", -bt_fp_slot);
1283         //bperr( "  read fp_saved_bt at %x from fp_native %x and slot %d\n", fp_addr, fp_bt, bt_fp_slot);
1284     } else {
1285         // $fp not saved in any frame
1286         // pass up callee $fp
1287         fp2 = saved_fp;
1288         sprintf(fp_debug, "(callee $fp)");
1289     }
1290   // sometimes the retrieved $fp is zero
1291   // (kludge for stack walk code)
1292   if (fp2 == 0) fp2 = saved_fp;
1293   
1294   // Sometimes we have identified functions with a stack frame
1295   // ra slot that do not store the ra in the slot.  The following
1296   // code accounts for this situation.
1297   if (caller == NULL && uppermost_) {
1298       // $ra in live register
1299       gregset_t regs;
1300       unsigned fd;
1301       if (lwp_) fd = lwp_->get_fd();
1302       else fd = getProc()->getRepresentativeLWP()->get_fd();
1303       if (ioctl(fd, PIOCGREG, &regs) == -1) {
1304           perror("process::readDataFromFrame(PIOCGREG)");
1305           return Frame(); // zero frame
1306       }
1307       ra = regs[PROC_REG_RA];
1308       caller = getProc()->findFuncByAddr(ra);
1309   }
1310   
1311   // caller frame is invalid if $pc does not resolve to a function
1312   if (!caller) return Frame(); // zero frame
1313
1314   // return value
1315   Frame ret(0, 0, 0, pid_, proc_, thread_, lwp_, false);
1316
1317   // I've gotten the strangest segfaults doing direct assignment
1318   memcpy(&ret.pc_, &ra, sizeof(Address));
1319   memcpy(&ret.sp_, &fp_native, sizeof(Address));
1320
1321   if ( caller )
1322   {
1323       if ( caller->uses_fp )
1324         memcpy(&ret.fp_, &fp2, sizeof(Address));
1325       else {
1326         fp_native += caller->frame_size;
1327         memcpy(&ret.fp_, &fp_native, sizeof(Address));
1328       }
1329   }
1330   else 
1331     memcpy(&ret.fp_, &fp2, sizeof(Address));
1332   
1333   ret.saved_fp = fp2;
1334   
1335   return ret;
1336 }
1337
1338 bool Frame::setPC(Address newpc) {
1339   fprintf(stderr, "Implement me! Changing frame PC from %x to %x\n",
1340           pc_, newpc);
1341   return true;
1342 }
1343
1344
1345 //
1346 // paradynd-only methods
1347 //
1348
1349
1350 void OS::osDisconnect(void) {
1351   //bperr( ">>> osDisconnect()\n");
1352   int fd = open("/dev/tty", O_RDONLY);
1353   ioctl(fd, TIOCNOTTY, NULL); 
1354   P_close(fd);
1355 }
1356
1357 #if !defined(BPATCH_LIBRARY)
1358
1359 rawTime64 dyn_lwp::getRawCpuTime_hw()
1360 {
1361   rawTime64 ret = 0;
1362   hwperf_cntr_t cnts;
1363   
1364   if(ioctl(fd_, PIOCGETEVCTRS, (void *)&cnts) < 0) {
1365     return hw_previous_;
1366   }
1367   
1368   ret = cnts.hwp_evctr[0];
1369   if(ret < hw_previous_) {
1370     logLine("*** time going backwards in paradynd ***\n");
1371     ret = hw_previous_;
1372   }
1373   hw_previous_ = ret;
1374
1375   return ret;
1376 }
1377
1378 /* return unit: nsecs */
1379 rawTime64 dyn_lwp::getRawCpuTime_sw()
1380 {
1381   //bperr( ">>> getInferiorProcessCPUtime()\n");
1382   rawTime64 ret;
1383   
1384   /*
1385   pracinfo_t t;
1386   ioctl(proc_fd, PIOCACINFO, &t);
1387   ret = PDYN_div1000(t.pr_timers.ac_utime + t.pr_timers.ac_stime);
1388   */
1389
1390   timespec_t t[MAX_PROCTIMER];
1391   if (ioctl(fd_, PIOCGETPTIMER, t) == -1) {
1392     perror("getInferiorProcessCPUtime - PIOCGETPTIMER");
1393     return sw_previous_;
1394   }
1395   ret = 0;
1396   ret += t[AS_USR_RUN].tv_sec * I64_C(1000000000); // sec to nsec  (user)
1397   ret += t[AS_SYS_RUN].tv_sec * I64_C(1000000000); // sec to nsec  (sys)
1398   ret += t[AS_USR_RUN].tv_nsec;   // add in nsec (user)
1399   ret += t[AS_SYS_RUN].tv_nsec;   // add in nsec (sys)
1400   
1401   // sanity check: time should not go backwards
1402   if (ret < sw_previous_) {
1403     logLine("*** time going backwards in paradynd ***\n");
1404     ret = sw_previous_;
1405   }
1406   else {
1407     sw_previous_ = ret;
1408   }
1409   return ret;
1410 }
1411 #endif
1412
1413 //  Here we start the MPI application by fork/exec.
1414 //
1415 //  The application will load libmpi and execute the init section of
1416 //  this library.  Our child becomes the MPI daemon process, which
1417 //  forks the appropriate number of worker processes.
1418 //
1419 //  We attach to the child before exec'ing and set flags
1420 //  to make sure that we can attach to the children of
1421 //  the MPI daemon.
1422 //
1423 //  Attaching to the children is handled in handleSigChild.
1424
1425 bool execIrixMPIProcess(pdvector<pdstring> &argv)
1426 {
1427   int pipeFlag[2], retval;
1428   char processFile[64];
1429   char flag;
1430         
1431   if ( pipe(pipeFlag) == -1)
1432     assert(false);
1433         
1434   if ( (masterMPIpid = fork()) )
1435   {
1436     // parent
1437     // attach to child process
1438     sprintf(processFile, "/proc/%d", masterMPIpid);
1439     masterMPIfd = open(processFile, O_RDWR);
1440     irixMPIappName = strdup(argv[0].c_str()); // used to identify MPI app processes
1441                 
1442     if ( masterMPIfd == -1 )
1443     {
1444       perror("startIrixMPIProcess failed to attach to child");
1445       return(false);
1446     }
1447
1448     flag = 'x';
1449     if ( write(pipeFlag[1], &flag, 1) != 1)
1450       perror("startIrixMPIProcess:parent pipe flag");
1451                 
1452     close(pipeFlag[0]);
1453     close(pipeFlag[1]);
1454   }
1455   else
1456   {
1457     int proc_fh;
1458     sysset_t exitCallset;
1459     premptyset(&exitCallset);
1460     praddset(&exitCallset, SYS_fork);   
1461
1462     // child
1463     // This process becomes the master MPI application process/daemon
1464
1465     // MPI on IRIX is started using mpirun
1466     // mpirun forks/execs local copies of the application process
1467     //   and starts remote processes using the array_services call asremexec().
1468     // The first copy of the application process on any machine, loads the libmpi.so
1469     // library and from within the libmpi.so init section,
1470     // forks the appropriate number of local MPI applications.
1471     // Note that the original/master application process never leaves
1472     // the init section (i.e. never reaches main).  Its purpose
1473     // is to communicate with the controlling mpirun process.
1474
1475     // make sure parent has attached before proceeding
1476
1477     int size = read(pipeFlag[0], &flag, 1);
1478     close(pipeFlag[0]);
1479     close(pipeFlag[1]);
1480
1481     if ( size < 0 )
1482       perror("addIrixMPIprocesses read parent flag");
1483
1484     //  set trace information so that this process stops at fork exits
1485
1486     sprintf(processFile, "/proc/%d", getpid());
1487     proc_fh = open(processFile, O_RDWR);
1488
1489     retval = ioctl(proc_fh, PIOCSEXIT, &exitCallset);
1490     if ( retval == -1 )
1491       perror("PIOCSEXIT");
1492
1493     close(proc_fh);
1494
1495     char **args;
1496     args = new char*[argv.size()+1];
1497     for (unsigned ai=0; ai<argv.size(); ai++)
1498       args[ai] = P_strdup(argv[ai].c_str());
1499     args[argv.size()] = NULL;
1500
1501     if ( P_execvp(args[0], args) == -1 )
1502     {
1503       perror("MPI application exec");
1504       exit(-1);
1505     }
1506   }
1507         
1508   return(true);
1509 }
1510
1511 fileDescriptor *getExecFileDescriptor(pdstring filename,
1512                                      int &,
1513                                      bool)
1514 {
1515   fileDescriptor *desc = new fileDescriptor(filename);
1516   return desc;
1517 }
1518
1519 bool dyn_lwp::realLWP_attach_() {
1520    assert( false && "threads not yet supported on IRIX");
1521    return false;
1522 }
1523
1524 bool dyn_lwp::representativeLWP_attach_() {
1525    char procName[128];    
1526    sprintf(procName, "/proc/%05d", getPid());
1527    fd_ = P_open(procName, O_RDWR, 0);
1528    if (fd_ == (unsigned) -1) {
1529       perror("Error opening process file descriptor");
1530       return false;
1531    }
1532
1533    // QUESTION: does this attach operation lead to a SIGTRAP being forwarded
1534    // to paradynd in all cases?  How about when we are attaching to an
1535    // already-running process?  (Seems that in the latter case, no SIGTRAP
1536    // is automatically generated) TODO
1537    
1538    // step 1 - /proc open: attach to the inferior process
1539    // Note: opening /proc is done in the dyn_lwp constructor
1540    // THIS STEP IS DONE IN THE OS INDEPENDENT FUNCTION process::attach()
1541    
1542    // step 2 - /proc PIOCSTRACE: define which signals should be forwarded to
1543    // daemon these are (1) SIGSTOP and (2) either SIGTRAP (sparc/mips) or
1544    // SIGILL (x86), to implement inferiorRPC completion detection.
1545    sigset_t sigs;
1546    premptyset(&sigs);
1547    (void)praddset(&sigs, SIGSTOP);
1548    (void)praddset(&sigs, SIGTRAP);
1549    (void)praddset(&sigs, SIGILL);
1550 #if defined(bug_irix_broken_sigstop)
1551    // we need to use SIGEMT for breakpoints in IRIX due to a bug with
1552    // tracing SIGSTOP in a process and then waitpid()ing for it
1553    // --wcb 10/4/2000
1554    (void)praddset(&sigs, SIGEMT);
1555 #endif
1556    if (ioctl(fd_, PIOCSTRACE, &sigs) < 0) {
1557       perror("process::attach(PIOCSTRACE)");
1558       return false;
1559    }
1560    return true;
1561 }
1562
1563 void dyn_lwp::realLWP_detach_()
1564 {
1565    assert(is_attached());  // dyn_lwp::detach() shouldn't call us otherwise
1566 }
1567
1568 void dyn_lwp::representativeLWP_detach_()
1569 {
1570    assert(is_attached());  // dyn_lwp::detach() shouldn't call us otherwise
1571    if (fd_) close(fd_);
1572 }
1573
1574 void loadNativeDemangler() {}
1575
1576 Frame dyn_thread::getActiveFrameMT() {
1577    return Frame();
1578 }  // not used until MT supported
1579
1580
1581 bool process::trapDueToDyninstLib()
1582 {
1583   Address pc = getRepresentativeLWP()->getActiveFrame().getPC();
1584   bool ret = (pc == dyninstlib_brk_addr);
1585   //if (ret) bperr( ">>> process::trapDueToDyninstLib()\n");
1586   return ret;
1587 }
1588
1589 bool process::trapAtEntryPointOfMain(Address)
1590 {
1591   Address pc = getRepresentativeLWP()->getActiveFrame().getPC();
1592   bool ret = (pc == main_brk_addr);
1593   //if (ret) bperr( ">>> process::trapAtEntryPointOfMain(true)\n");
1594   return ret;
1595 }
1596
1597 /* insertTrapAtEntryPointOfMain(): For some Fortran apps, main() is
1598    defined in a shared library.  If main() cannot be found, then we
1599    check if the executable image contained a call to main().  This is
1600    usually inside __start(). */
1601 bool process::insertTrapAtEntryPointOfMain()
1602 {
1603     // insert trap near "main"
1604     main_brk_addr = lookup_fn(this, "main");
1605     if (main_brk_addr == 0) {
1606         main_brk_addr = getImage()->get_main_call_addr();
1607     }
1608     if (!main_brk_addr) return false;
1609     
1610     // save original instruction
1611     if (!readDataSpace((void *)main_brk_addr, INSN_SIZE, savedCodeBuffer, true))
1612         return false;
1613     
1614     // insert trap instruction
1615     instruction trapInsn;
1616     genTrap(&trapInsn);
1617     if (!writeDataSpace((void *)main_brk_addr, INSN_SIZE, &trapInsn))
1618         return false;
1619     return true;
1620 }
1621
1622 bool process::handleTrapAtEntryPointOfMain()
1623 {
1624   // restore original instruction to entry point of main()
1625     if (!writeDataSpace((void *)main_brk_addr, INSN_SIZE, savedCodeBuffer))
1626         return false;
1627     return true;
1628 }
1629
1630
1631 bool process::getDyninstRTLibName() {
1632     // find runtime library
1633     char *rtlib_var;
1634     char *rtlib_prefix;
1635     
1636     rtlib_var = "DYNINSTAPI_RT_LIB";
1637     rtlib_prefix = "libdyninstAPI_RT";
1638     
1639     if (!dyninstRT_name.length()) {
1640         dyninstRT_name = getenv(rtlib_var);
1641         if (!dyninstRT_name.length()) {
1642             pdstring msg = pdstring("Environment variable ") + pdstring(rtlib_var)
1643             + pdstring(" has not been defined for process ") + pdstring(pid);
1644             showErrorCallback(101, msg);
1645             return false;
1646         }
1647     }
1648     
1649     const char *rtlib_val = dyninstRT_name.c_str();
1650     assert(strstr(rtlib_val, rtlib_prefix));
1651     
1652     // for 32-bit apps, modify the rtlib environment variable
1653     char *rtlib_mod = "_n32";
1654     if (!getImage()->getObject().is_elf64() &&
1655         !strstr(rtlib_val, rtlib_mod)) 
1656     {
1657         char *rtlib_suffix = ".so.1";
1658         // truncate suffix
1659         char *ptr_suffix = strstr(rtlib_val, rtlib_suffix);
1660         assert(ptr_suffix);
1661         *ptr_suffix = 0;
1662         // construct environment variable
1663         char buf[512];
1664         sprintf(buf, "%s=%s%s%s", rtlib_var, rtlib_val, rtlib_mod, rtlib_suffix);
1665         dyninstRT_name = pdstring(rtlib_val)+pdstring(rtlib_mod)+pdstring(rtlib_suffix);
1666     }
1667
1668     if (access(dyninstRT_name.c_str(), R_OK)) {
1669         pdstring msg = pdstring("Runtime library ") + dyninstRT_name
1670         + pdstring(" does not exist or cannot be accessed!");
1671         showErrorCallback(101, msg);
1672         assert(0 && "Dyninst RT lib cannot be accessed!");
1673         return false;
1674     }
1675     return true;
1676 }
1677
1678
1679 bool process::loadDYNINSTlib()
1680 {
1681   //bperr( ">>> loadDYNINSTlib()\n");
1682
1683   // use "_start" as scratch buffer to invoke dlopen() on DYNINST
1684   Address baseAddr = lookup_fn(this, "_start");
1685   char buf_[BYTES_TO_SAVE], *buf = buf_;
1686   Address bufSize = 0;
1687   
1688   // step 0: illegal instruction (code)
1689   genIll((instruction *)(buf + bufSize));
1690   bufSize += INSN_SIZE;
1691   
1692   // step 1: DYNINST library pdstring (data)
1693   //Address libStart = bufSize; // debug
1694   Address libAddr = baseAddr + bufSize;
1695   if (access(dyninstRT_name.c_str(), R_OK)) {
1696        pdstring msg = pdstring("Runtime library ") + dyninstRT_name + 
1697                     pdstring(" does not exist or cannot be accessed");
1698        showErrorCallback(101, msg);
1699        return false;
1700   }
1701   int libSize = strlen(dyninstRT_name.c_str()) + 1;
1702   strcpy(buf + bufSize, dyninstRT_name.c_str());
1703   bufSize += libSize;
1704   // pad to aligned instruction boundary
1705   if (!isAligned(baseAddr + bufSize)) {
1706     int npad = INSN_SIZE - ((baseAddr + bufSize) % INSN_SIZE);
1707     for (int i = 0; i < npad; i++)
1708       buf[bufSize + i] = 0;
1709     bufSize += npad;
1710     assert(isAligned(baseAddr + bufSize));
1711   }
1712
1713   // step 2: inferior dlopen() call (code)
1714   Address codeAddr = baseAddr + bufSize;
1715   registerSpace *regs = new registerSpace(nDead, Dead, 0, (Register *)0);
1716   pdvector<AstNode*> args(2);
1717   int dlopen_mode = RTLD_NOW | RTLD_GLOBAL;
1718   AstNode *call;
1719   pdstring callee = "dlopen";
1720   // inferior dlopen(): build AstNodes
1721   args[0] = new AstNode(AstNode::Constant, (void *)libAddr);
1722   args[1] = new AstNode(AstNode::Constant, (void *)dlopen_mode);
1723   call = new AstNode(callee, args);
1724   removeAst(args[0]);
1725   removeAst(args[1]);
1726   // inferior dlopen(): generate code
1727   regs->resetSpace();
1728   //Address codeStart = bufSize; // debug
1729   call->generateCode(this, regs, buf, bufSize, true, true);
1730   removeAst(call);
1731   
1732   // step 3: trap instruction (code)
1733   Address trapAddr = baseAddr + bufSize;
1734   genTrap((instruction *)(buf + bufSize));
1735   bufSize += INSN_SIZE;
1736   //int trapEnd = bufSize; // debug
1737
1738   // debug
1739   /*
1740   bperr( "inferior dlopen code: (%i bytes)\n", bufSize);
1741   dis(buf, baseAddr);
1742   bperr( "%0#10x      \"%s\"\n", baseAddr + libStart, buf + libStart);
1743   for (int i = codeStart; i < bufSize; i += INSN_SIZE) {
1744     dis(buf + i, baseAddr + i);
1745   }
1746   */
1747   
1748   // save registers and "_start" code
1749   readDataSpace((void *)baseAddr, BYTES_TO_SAVE, savedCodeBuffer, true);
1750   assert(savedRegs == NULL);
1751   savedRegs = new dyn_saved_regs;
1752   bool status = getRepresentativeLWP()->getRegisters(savedRegs);
1753   assert(status == true);
1754
1755   // write inferior dlopen code and set PC
1756   assert(bufSize <= BYTES_TO_SAVE);
1757   //bperr( "writing %i bytes to <0x%08x:_start>, $pc = 0x%08x\n",
1758   //bufSize, baseAddr, codeAddr);
1759   //bperr( ">>> loadDYNINSTlib <0x%08x(_start): %i insns>\n",
1760   //baseAddr, bufSize/INSN_SIZE);
1761   writeDataSpace((void *)baseAddr, bufSize, (void *)buf);
1762   bool ret = getRepresentativeLWP()->changePC(codeAddr, savedRegs);
1763   assert(ret);
1764
1765   // debug
1766   /*
1767   bperr( "inferior dlopen code: (%i bytes)\n", bufSize - codeStart);
1768   disDataSpace(this, (void *)(baseAddr + codeStart), 
1769                (bufSize - codeStart) / INSN_SIZE, "  ");
1770   */
1771
1772   dyninstlib_brk_addr = trapAddr;
1773   setBootstrapState(loadingRT);
1774
1775   return true;
1776 }
1777