BPatch functions that block are now locked (on a finer grain than the rest of the...
[dyninst.git] / dyninstAPI / src / osf.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: osf.C,v 1.73 2005/02/25 07:04:46 jaw Exp $
43
44 #include "common/h/headers.h"
45 #include "os.h"
46 #include "process.h"
47 #include "dyn_lwp.h"
48 #include "stats.h"
49 #include "common/h/Types.h"
50 #include <sys/ioctl.h>
51 #include <sys/wait.h>
52 #include <sys/ptrace.h>
53 #include <sys/syscall.h>
54 #include <filehdr.h>
55 #include <scnhdr.h>
56 #include <fcntl.h>
57 #include <ldfcn.h>
58 #include "showerror.h"
59 #ifndef BPATCH_LIBRARY
60 #include "main.h"
61 #endif 
62 #include <sys/procfs.h>
63 #include <sys/poll.h>
64 #include <sys/fault.h>
65 #include <dlfcn.h>
66
67 #include "common/h/osfKludges.h"
68 #include "dyninstAPI/src/rpcMgr.h"
69 #include "dyninstAPI/src/signalhandler.h"
70 #include "dyninstAPI/src/dyn_thread.h"
71
72 #define V0_REGNUM 0     /* retval from integer funcs */
73 #define PC_REGNUM 31
74 #define SP_REGNUM 30
75 #define FP_REGNUM 15
76 #define A0_REGNUM 16    /* first param to funcs and syscalls */
77 #define RA_REGNUM 26
78 extern bool exists_executable(const pdstring &fullpathname);
79
80 extern unsigned enable_pd_attach_detach_debug;
81
82   extern void generateBreakPoint(instruction &);
83
84 #if ENABLE_DEBUG_CERR == 1
85 #define attach_cerr if (enable_pd_attach_detach_debug) cerr
86 #else
87 #define attach_cerr if (0) cerr
88 #endif /* ENABLE_DEBUG_CERR == 1 */
89
90 int getNumberOfCPUs()
91 {
92   return(1);
93 }
94
95
96 bool rpcMgr::emitInferiorRPCheader(void *insnPtr, Address &baseBytes) {
97
98   extern void emitSaveConservative(process *, char *, Address &baseBytes);
99
100   emitSaveConservative(proc_, (char *) insnPtr, baseBytes);
101
102   return true;
103 }
104
105 bool rpcMgr::emitInferiorRPCtrailer(void *insnPtr, Address &baseBytes,
106                                      unsigned &breakOffset,
107                                      bool stopForResult,
108                                      unsigned &stopForResultOffset,
109                                      unsigned &justAfter_stopForResultOffset) {
110   instruction *insn = (instruction *)insnPtr;
111   Address baseInstruc = baseBytes / sizeof(instruction);
112
113
114   extern void generate_nop(instruction*);
115   extern void emitRestoreConservative(process *, char *, Address &baseBytes);
116
117   emitRestoreConservative(proc_, (char *) insnPtr, baseBytes);
118
119   if (stopForResult) {
120     generateBreakPoint(insn[baseInstruc]);
121     stopForResultOffset = baseInstruc * sizeof(instruction);
122     baseInstruc++;
123
124     justAfter_stopForResultOffset = baseInstruc * sizeof(instruction);
125   }
126   
127   // Trap instruction (breakpoint):
128   generateBreakPoint(insn[baseInstruc]);
129   breakOffset = baseInstruc * sizeof(instruction);
130   baseInstruc++;
131
132   // And just to make sure that we don't continue, we put an illegal
133   // insn here:
134   extern void generateIllegalInsn(instruction &);
135   generateIllegalInsn(insn[baseInstruc++]);
136
137   baseBytes = baseInstruc * sizeof(instruction); // convert back
138
139   return true;
140 }
141
142 Address dyn_lwp::readRegister(Register /*reg*/)
143 {  
144   gregset_t theIntRegs;
145   if (-1 == ioctl(fd_, PIOCGREG, &theIntRegs)) {
146     perror("process::readRegister PIOCGREG");
147     if (errno == EBUSY) {
148       cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
149       assert(false);
150     }
151     return 0; // assert(false)?
152   }
153   return theIntRegs.regs[0];
154 }
155
156 //void OS::osTraceMe(void) { P_ptrace(PT_TRACE_ME, 0, 0, 0); }
157
158
159 // getActiveFrame(): populate Frame object using toplevel frame
160 Frame dyn_lwp::getActiveFrame()
161 {
162   Address pc, fp;
163   Frame theFrame;
164   gregset_t theIntRegs;
165 //  int proc_fd = p->getProcFileDescriptor();
166   if (ioctl(fd_, PIOCGREG, &theIntRegs) != -1) {
167     fp = theIntRegs.regs[SP_REGNUM];  
168     pc = theIntRegs.regs[PC_REGNUM]-4; /* -4 because the PC is updated */
169     theFrame = Frame(pc, fp, 0, proc_->getPid(), proc_, NULL, this, true);
170   }
171   return theFrame;
172 }
173
174 /* 
175  * Syscall tracing wrappers
176  */
177 bool process::get_entry_syscalls(sysset_t *entries) {
178     dyn_lwp *replwp = getRepresentativeLWP();    
179     if (ioctl(replwp->get_fd(), PIOCGENTRY, entries) < 0) {
180         perror("get_entry_syscalls");
181         return false;
182     }
183     return true;
184 }
185
186 bool process::set_entry_syscalls(sysset_t *entries) {
187     dyn_lwp *replwp = getRepresentativeLWP();    
188     if (ioctl(replwp->get_fd(), PIOCSENTRY, entries) < 0) {
189         perror("set_entry_syscalls");
190         return false;
191     }
192     return true;
193 }
194
195 bool process::get_exit_syscalls(sysset_t *exits) {
196     dyn_lwp *replwp = getRepresentativeLWP();    
197     if (ioctl(replwp->get_fd(), PIOCGEXIT, exits) < 0) {
198         perror("get_exit_syscalls");
199         return false;
200     }
201     return true;
202 }
203
204 bool process::set_exit_syscalls(sysset_t *exits) {
205     dyn_lwp *replwp = getRepresentativeLWP();    
206     if (ioctl(replwp->get_fd(), PIOCSEXIT, exits) < 0) {
207         perror("set_exit_syscalls");
208         return false;
209     }
210     return true;
211 }
212
213
214 /*
215  * Use by dyninst to set events we care about from procfs
216  *
217  */
218 bool process::setProcessFlags()
219 {
220
221   long flags = 0;
222   // cause the child to inherit trap-on-exit from exec and other traps
223   // so we can learn of the child (if the user cares)
224   flags = PR_FORK | PR_ASYNC;
225
226   dyn_lwp *replwp = getRepresentativeLWP();
227   if (ioctl(replwp->get_fd(), PIOCSET, &flags) < 0) {
228     bperr( "attach: PIOCSET failed: %s\n", sys_errlist[errno]);
229     return false;
230   }
231
232    /* we don't catch any child signals, except SIGSTOP */
233    sigset_t sigs;
234    fltset_t faults;
235    premptyset(&sigs);
236    praddset(&sigs, SIGSTOP);
237    praddset(&sigs, SIGTRAP);
238    praddset(&sigs, SIGSEGV);
239    
240    if (ioctl(replwp->get_fd(), PIOCSTRACE, &sigs) < 0) {
241        perror("setProcessFlags: PIOCSTRACE");
242       return false;
243    }
244    
245    premptyset(&faults);
246    praddset(&faults,FLTBPT);
247    if (ioctl(replwp->get_fd(), PIOCSFAULT, &faults) <0) {
248        perror("setProcessFlags: PIOCSFAULT");
249       return false;
250   }
251
252    // Clear the list of traced syscalls 
253    sysset_t sysset;
254    premptyset(&sysset);
255    if (!set_entry_syscalls(&sysset)) return false;
256    if (!set_exit_syscalls(&sysset)) return false;
257     
258
259   return true;
260 }
261
262 bool process::unsetProcessFlags()
263 {
264
265   long flags = 0;
266   // cause the child to inherit trap-on-exit from exec and other traps
267   // so we can learn of the child (if the user cares)
268   flags = PR_FORK | PR_ASYNC;
269
270   dyn_lwp *replwp = getRepresentativeLWP();
271   if (ioctl(replwp->get_fd(), PIOCRESET, &flags) < 0) {
272       perror("unsetProcessFlags: PIOCRESET");
273       return false;
274   }
275   
276    sigset_t sigs;
277    premptyset(&sigs);
278
279    if (ioctl(replwp->get_fd(), PIOCSTRACE, &sigs) < 0) {
280        perror("unsetProcessFlags: PIOCSTRACE");
281        return false;
282    }
283   return true;
284 }
285
286
287 static inline bool execResult(prstatus_t stat) 
288 {
289   return (stat.pr_reg.regs[V0_REGNUM] == 0);
290 }
291
292 #ifndef OPEN_MAX
293 #define OPEN_MAX 1024
294 #endif
295
296
297 #if 0
298 #ifdef BPATCH_LIBRARY
299 int process::waitforRPC(int *status, bool /* block */)
300 {
301   static struct pollfd fds[OPEN_MAX];  // argument for poll
302   static int selected_fds;             // number of selected
303   static int curr;                     // the current element of fds
304
305   if (selected_fds == 0) {
306       for (unsigned u = 0; u < processVec.size(); u++) {
307           if (processVec[u] &&
308               (processVec[u]->status() == running || 
309                processVec[u]->status() == neonatal)) {
310               fds[u].fd = processVec[u]->getRepresentativeLWP()->get_fd();
311               selected_fds++;
312           } else {
313               fds[u].fd = -1;
314           }
315           fds[u].events = 0xffff;
316           fds[u].revents = 0;
317       }
318       curr = 0;
319   }
320   if (selected_fds > 0)
321     {
322       while(fds[curr].fd == -1) ++curr;
323       prstatus_t stat;
324       int ret = 0;
325       int flag = 0;
326       // Busy wait till the process actually stops on a fault
327       while(!flag)
328         {
329           if (ioctl(fds[curr].fd,PIOCSTATUS,&stat) != -1 && (stat.pr_flags & PR_STOPPED || stat.pr_flags & PR_ISTOP)) {
330             switch(stat.pr_why) {
331             case PR_FAULTED:
332             case PR_SIGNALLED:
333           *status = SIGTRAP << 8 | 0177;
334           ret = processVec[curr]->getPid();
335           flag = 1;
336           break;
337             }
338           }
339         }
340       --selected_fds;
341       ++curr;
342       if (ret > 0) return ret;
343     }
344   return 0;
345 }
346 #endif
347 #endif
348
349 procSyscall_t decodeSyscall(process *p, procSignalWhat_t syscall)
350 {
351     if (syscall == SYS_fork ||
352         syscall == SYS_vfork)
353         return procSysFork;
354     if (syscall == SYS_execv ||
355         syscall == SYS_execve)
356         return procSysExec;
357     if (syscall == SYS_exit)
358         return procSysExit;
359     return procSysOther;
360 }
361
362 int decodeProcStatus(process *proc,
363                      procProcStatus_t status,
364                      procSignalWhy_t &why,
365                      procSignalWhat_t &what,
366                      procSignalInfo_t &info) {
367     
368     switch (status.pr_why) {
369   case PR_SIGNALLED:
370       why = procSignalled;
371       what = status.pr_what;
372       break;
373   case PR_SYSENTRY:
374       why = procSyscallEntry;
375       what = status.pr_what;
376       info = status.pr_reg.regs[A0_REGNUM];
377       break;
378   case PR_SYSEXIT:
379       why = procSyscallExit;
380       what = status.pr_what;
381       info = status.pr_reg.regs[V0_REGNUM];
382       break;
383   case PR_REQUESTED:
384       // We don't expect PR_REQUESTED in the signal handler
385       assert(0 && "PR_REQUESTED not handled");
386       break;
387   case PR_JOBCONTROL:
388   case PR_FAULTED:
389   default:
390       assert(0);
391       break;
392     }
393     return 1;
394 }
395
396
397 // Get and decode a signal for a process
398 // We poll /proc for process events, and so it's possible that
399 // we'll get multiple hits. In this case we return one and queue
400 // the rest. Further calls of decodeProcessEvent will burn through
401 // the queue until there are none left, then re-poll.
402 // Return value: 0 if nothing happened, or process pointer
403
404 // the pertinantLWP and wait_options are ignored on Solaris, AIX
405
406 bool signalHandler::checkForProcessEvents(pdvector<procevent *> *events,
407                                           int wait_arg, int &timeout)
408 {
409     procSignalWhy_t  why  = procUndefined;
410     procSignalWhat_t what = 0;
411     procSignalInfo_t info = 0;
412
413     extern pdvector<process*> processVec;
414     static struct pollfd fds[OPEN_MAX];  // argument for poll
415     // Number of file descriptors with events pending
416     static int selected_fds = 0; 
417     // The current FD we're processing.
418     static int curr = 0;
419     prstatus_t stat;
420
421     if (selected_fds == 0) {
422         for (unsigned u = 0; u < processVec.size(); u++) {
423             //bperr("checking %d\n", processVec[u]->getPid());
424             if (processVec[u] && 
425                 (processVec[u]->status() == running || 
426                  processVec[u]->status() == neonatal)) {
427                 if (wait_arg == -1 ||
428                     processVec[u]->getPid() == wait_arg) {
429                     fds[u].fd =processVec[u]->getRepresentativeLWP()->get_fd();
430                     // Apparently, exit doesn't cause a poll event. Odd...
431                     int status;
432                     int retWait = waitpid(processVec[u]->getPid(), &status, WNOHANG|WNOWAIT);
433                     if (retWait == -1) {
434                         perror("Initial waitpid");
435                     }
436                     else if (retWait > 1) {
437                         decodeWaitPidStatus(processVec[u], status, &why,&what);
438                         // In this case we return directly
439                         procevent *new_event = new procevent;
440                         new_event->proc = processVec[u];
441                         new_event->lwp  =processVec[u]->getRepresentativeLWP();
442                         new_event->why  = why;
443                         new_event->what = what;
444                         new_event->info = info;
445                         (*events).push_back(new_event);
446                         return true;
447                     }
448                 }
449             } else {
450                 fds[u].fd = -1;
451             }   
452             fds[u].events = POLLPRI;
453             fds[u].revents = 0;
454         }
455         if (selected_fds == 0) {
456             int wait_time = timeout;
457             // Exit doesn't provide an event, so we need a timeout eventually
458             if (timeout == -1) wait_time = 5;
459             selected_fds = poll(fds, processVec.size(), wait_time);
460         }
461         if (selected_fds <= 0) {
462             if (selected_fds < 0) {
463                 bperr( "decodeProcessEvent: poll failed: %s\n",
464                         sys_errlist[errno]);
465                 selected_fds = 0;
466             }
467             else {
468                //  poll timed out, indicate this by setting timeout to 0
469                timeout = 0;
470             }
471             return false;
472         }
473         
474         // Reset the current pointer to the beginning of the poll list
475         curr = 0;
476     } // if selected_fds == 0
477     // We have one or more events to work with.
478     while (fds[curr].revents == 0) {
479         // skip
480         ++curr;
481     }
482     // fds[curr] has an event of interest
483     prstatus_t procstatus;
484     process *currProcess = processVec[curr];
485     
486     if (fds[curr].revents & POLLHUP) {
487         // True if the process exited out from under us
488         int status;
489         int ret;
490         // Process exited, get its return status
491         do {
492             ret = waitpid(currProcess->getPid(), &status, 0);
493         } while ((ret < 0) && (errno == EINTR));
494         if (ret < 0) {
495             // This means that the application exited, but was not our child
496             // so it didn't wait around for us to get it's return code.  In
497             // this case, we can't know why it exited or what it's return
498             // code was.
499             ret = currProcess->getPid();
500             status = 0;
501             // is this the bug??
502             // processVec[curr]->continueProc_();
503         }
504         if (!decodeWaitPidStatus(currProcess, status, &why, &what)) {
505             cerr << "decodeProcessEvent: failed to decode waitpid return" << endl;
506             return false;
507         }
508     } else {
509         // Real return from poll
510         if (ioctl(currProcess->getRepresentativeLWP()->get_fd(), 
511                   PIOCSTATUS, &procstatus) != -1) {
512             // Check if the process is stopped waiting for us
513             if (procstatus.pr_flags & PR_STOPPED ||
514                 procstatus.pr_flags & PR_ISTOP) {
515                 if (!decodeProcStatus(currProcess, procstatus, why, what, info))
516                    return false;
517             }
518         }
519         else {
520             // Process exited on us
521         }
522     }
523     // Skip this FD the next time through
524
525     bool foundEvent = false;
526     if (currProcess) {
527         foundEvent = true;
528         procevent *new_event = new procevent;
529         new_event->proc = currProcess;
530         new_event->lwp  = currProcess->getRepresentativeLWP();
531         new_event->why  = why;
532         new_event->what = what;
533         new_event->info = info;
534         (*events).push_back(new_event);
535
536         currProcess->set_status(stopped);
537     }
538     
539
540     --selected_fds;
541     ++curr;    
542     return foundEvent;
543
544
545 Frame Frame::getCallerFrame()
546 {
547   Frame ret;
548   Address values[2];
549   gregset_t theIntRegs;
550   int_function *currFunc;
551   if (fp_ == 0) return Frame();
552   ret.proc_ = proc_;
553
554   if (uppermost_) {
555       int proc_fd = getProc()->getRepresentativeLWP()->get_fd();
556       if (ioctl(proc_fd, PIOCGREG, &theIntRegs) != -1) {
557           ret.pc_ = theIntRegs.regs[PC_REGNUM];  
558
559           currFunc = getProc()->findFuncByAddr(ret.pc_);
560           if (currFunc && currFunc->frame_size) {
561               ret.fp_ = theIntRegs.regs[SP_REGNUM] + currFunc->frame_size;  
562               ret.sp_ = theIntRegs.regs[SP_REGNUM];
563               //bperr(" %s fp=%lx\n",currFunc->prettyName().c_str(), ret.fp_);
564           } else {
565               ret.fp_ = 0;
566               sprintf(errorLine, "%s[%d]: pc %lx, not in a known function\n", 
567                                   __FILE__, __LINE__, ret.pc_);
568               logLine(errorLine);
569           }
570           
571       } else {
572           return Frame(); // zero frame
573       }
574   } else {
575       if (!getProc()->readDataSpace((void *)sp_, sizeof(Address), values, false)){
576           bperr("error reading frame at %lx\n", fp_);
577           return Frame(); // zero frame
578       } else {
579           // (*sp_) = RA
580           // fp_ + frame_size = saved fp
581           ret.pc_ = values[0];
582           
583           currFunc = getProc()->findFuncByAddr(ret.pc_);
584           if (currFunc && currFunc->frame_size) {
585               ret.sp_ = fp_;            /* current stack pointer is old fp */
586               ret.fp_ = fp_ + currFunc->frame_size;  
587               //bperr(" %s fp=%lx\n",currFunc->prettyName().c_str(), ret.fp_);
588           } else {
589               sprintf(errorLine, "%s[%d]: pc %lx, not in a known function\n", 
590                                   __FILE__, __LINE__, ret.pc_);
591               logLine(errorLine);
592               ret.fp_ = 0;
593           }
594       }
595   }
596   return ret;
597 }
598
599 bool Frame::setPC(Address newpc) {
600   fprintf(stderr, "Implement me! Changing frame PC from %x to %x\n",
601           pc_, newpc);
602   return true;
603 }
604
605 bool process::dumpCore_(const pdstring coreFile) 
606 {
607   //bperr( ">>> process::dumpCore_()\n");
608   bool ret;
609 #ifdef BPATCH_LIBRARY
610   ret = dumpImage(coreFile);
611 #else
612   ret = dumpImage();
613 #endif
614   return ret;
615
616 }
617
618 pdstring process::tryToFindExecutable(const pdstring &progpath, int pid) 
619 {
620    // returns empty string on failure
621
622    if (exists_executable(progpath)) // util lib
623       return progpath;
624
625    char buffer[128];
626    sprintf(buffer, "/proc/%05d", pid);
627    int procfd = open(buffer, O_RDONLY, 0);
628    if (procfd == -1) {
629       attach_cerr << "tryToFindExecutable failed since open of /proc failed" << endl;
630       return "";
631    }
632    attach_cerr << "tryToFindExecutable: opened /proc okay" << endl;
633
634    struct prpsinfo the_psinfo;
635
636    if (ioctl(procfd, PIOCPSINFO, &the_psinfo) == -1) {
637        close(procfd);
638        return "";
639    }
640
641    char commandName[256];
642    strcpy(commandName, the_psinfo.pr_psargs);
643    if (strchr(commandName, ' ')) *(strchr(commandName, ' ')) = '\0';
644
645    if (!access(commandName, X_OK)) {
646        // found the file, return the results
647        (void)close(procfd);
648        return commandName;
649    }
650
651    bperr("access to  %s failed \n", commandName);
652    attach_cerr << "tryToFindExecutable: giving up" << endl;
653
654    (void)close(procfd);
655
656    return ""; // failure
657 }
658
659
660 //
661 // Write out the current contents of the text segment to disk.  This is useful
662 //    for debugging dyninst.
663 //
664 #ifdef BPATCH_LIBRARY
665 bool process::dumpImage(pdstring outFile)
666 #else
667 bool process::dumpImage()
668 #endif
669 {
670 #if !defined(BPATCH_LIBRARY)
671   pdstring outFile = getImage()->file() + ".real";
672 #endif
673   int i;
674   int rd;
675   int ifd;
676   int ofd;
677   int total;
678   int length;
679   Address baseAddr;
680     //extern int errno;
681     const int COPY_BUF_SIZE = 4*4096;
682     char buffer[COPY_BUF_SIZE];
683     struct filehdr hdr;
684     struct stat statBuf;
685     SCNHDR sectHdr;
686     LDFILE      *ldptr = NULL;
687     image       *im;
688     long text_size , text_start,file_ofs;
689
690     im = getImage();
691     pdstring origFile = im->file();
692
693     ifd = open(origFile.c_str(), O_RDONLY, 0);
694     if (ifd < 0) {
695       sprintf(errorLine, "Unable to open %s\n", origFile.c_str());
696       logLine(errorLine);
697       showErrorCallback(41, (const char *) errorLine);
698       perror("open");
699       return true;
700     }
701
702     rd = fstat(ifd, &statBuf);
703     if (rd != 0) {
704       perror("fstat");
705       sprintf(errorLine, "Unable to stat %s\n", origFile.c_str());
706       logLine(errorLine);
707       showErrorCallback(72, (const char *) errorLine);
708       return true;
709     }
710     length = statBuf.st_size;
711
712     sprintf(errorLine, "saving program to %s\n", outFile.c_str());
713     logLine(errorLine);
714
715     ofd = open(outFile.c_str(), O_WRONLY|O_CREAT, 0777);
716     if (ofd < 0) {
717       perror("open");
718       exit(-1);
719     }
720
721     /* read header and section headers */
722     /* Uses ldopen to parse the section headers */
723     /* try */ 
724     if (!(ldptr = ldopen((char *) origFile.c_str(), ldptr))) {
725        perror("Error in Open");
726        exit(-1);
727      }
728      
729      if (TYPE(ldptr) != ALPHAMAGIC) {
730        bperr("%s is not an alpha executable\n", outFile.c_str());
731        exit(-1);
732      }
733      // Read the text and data sections
734      hdr = HEADER(ldptr);
735      /* Find text segment and then */
736      /* compute text segment length and start offset */
737      for (int k=0;k<hdr.f_nscns;k++) {
738          if (ldshread(ldptr, k , &sectHdr) == SUCCESS) {
739            // sprintf(errorLine,"Section: %s  Start: %ld ",sectHdr.s_name,
740            //  sectHdr.s_vaddr); 
741            // logLine(errorLine);
742            // cout << "Section: " << sectHdr.s_name << "\tStart: " << sectHdr.s_vaddr 
743            // << "\tEnd: " << sectHdr.s_vaddr + sectHdr.s_size << endl;
744            // cout.flush();
745          } else {
746              perror("Error reading section header");
747              exit(-1);
748          }
749
750          if (!P_strcmp(sectHdr.s_name, ".text")) {
751            text_size = sectHdr.s_size;
752            text_start = sectHdr.s_vaddr;
753            file_ofs = sectHdr.s_scnptr;
754          }
755        }
756      ldclose(ldptr);
757     /* ---------end section header read ------------*/
758
759     /* now copy the entire file */
760     lseek(ofd, 0, SEEK_SET);
761     lseek(ifd, 0, SEEK_SET);
762     for (i=0; i < length; i += COPY_BUF_SIZE) {
763         rd = read(ifd, buffer, COPY_BUF_SIZE);
764         write(ofd, buffer, rd);
765         total += rd;
766     }
767
768     baseAddr = (Address) text_start;
769     sprintf(errorLine, "seeking to %ld as the offset of the text segment \n",
770             file_ofs);
771     logLine(errorLine);
772     sprintf(errorLine, " code offset= %ld\n", baseAddr);
773     logLine(errorLine);
774
775     /* seek to the text segment */
776     lseek(ofd,(off_t)file_ofs, SEEK_SET);
777     for (i=0; i < text_size; i+= 1024) {
778        errno = 0;
779        length = ((i + 1024) < text_size) ? 1024 : text_size -i;
780        dyn_lwp *replwp = getRepresentativeLWP();
781        if (lseek(replwp->get_fd(),(off_t)(baseAddr + i), SEEK_SET) !=
782            (long)(baseAddr + i))
783        {
784           bperr("Error_:%s\n",sys_errlist[errno]);
785           bperr("[%d] Couldn't lseek to the designated point\n",i);
786        }
787        read(replwp->get_fd(),buffer,length);
788        write(ofd, buffer, length);
789     }
790
791     close(ofd);
792     close(ifd);
793
794     return true;
795 }
796
797 /*
798    terminate execution of a process
799  */
800 terminateProcStatus_t process::terminateProc_()
801 {
802     long flags = PRFS_KOLC;
803     if (ioctl (getRepresentativeLWP()->get_fd(), PIOCSSPCACT, &flags) < 0)
804         return terminateFailed;
805
806     // just to make sure it is dead
807     if (kill(getPid(), 9)) {
808       if (errno == ESRCH)
809         return alreadyTerminated;
810       else
811         return terminateFailed;
812     }
813     return terminateSucceeded;
814 }
815
816 dyn_lwp *process::createRepresentativeLWP() {
817    // don't register the representativeLWP in real_lwps since it's not a true
818    // lwp
819    representativeLWP = createFictionalLWP(0);
820    return representativeLWP;
821 }
822
823 #if !defined(BPATCH_LIBRARY)
824 rawTime64 dyn_lwp::getRawCpuTime_hw()
825 {
826   return 0;
827 }
828
829 /* return unit: nsecs */
830 rawTime64 dyn_lwp::getRawCpuTime_sw() 
831 {
832   // returns user+sys time from the u or proc area of the inferior process,
833   // which in turn is presumably obtained by mmapping it (sunos)
834   // or by using a /proc ioctl to obtain it (solaris).
835   // It must not stop the inferior process in order to obtain the result,
836   // nor can it assue that the inferior has been stopped.
837   // The result MUST be "in sync" with rtinst's DYNINSTgetCPUtime().
838   
839   // We use the PIOCUSAGE /proc ioctl
840   
841   // Other /proc ioctls that should work too: PIOCPSINFO and the
842   // lower-level PIOCGETPR and PIOCGETU which return copies of the proc
843   // and u areas, respectively.
844   // PIOCSTATUS does _not_ work because its results are not in sync
845   // with DYNINSTgetCPUtime
846   
847   rawTime64 now;
848   
849   prpsinfo_t procinfo;
850   
851   if (ioctl(fd_, PIOCPSINFO, &procinfo) == -1) {
852     perror("process::getInferiorProcessCPUtime - PIOCPSINFO");
853     abort();
854   }
855   
856   /* Put secs and nsecs into usecs */
857   now = procinfo.pr_time.tv_sec;
858   now *= I64_C(1000000000);
859   now += procinfo.pr_time.tv_nsec;
860   
861   if (now<sw_previous_) {
862     // time shouldn't go backwards, but we have seen this happening
863     // before, so we better check it just in case - naim 5/30/97
864     logLine("********* time going backwards in paradynd **********\n");
865     now=sw_previous_;
866   }
867   else {
868     sw_previous_=now;
869   }
870   
871   return now;
872 }
873 #endif
874
875 fileDescriptor *getExecFileDescriptor(pdstring filename,
876                                      int &,
877                                      bool)
878 {
879   fileDescriptor *desc = new fileDescriptor(filename);
880   return desc;
881 }
882
883 bool dyn_lwp::realLWP_attach_() {
884    assert( false && "threads not yet supported on OSF");
885    return false;
886 }
887
888 bool dyn_lwp::representativeLWP_attach_() {
889    /*
890      Open the /proc file correspoding to process pid, 
891      set the signals to be caught to be only SIGSTOP,
892      and set the kill-on-last-close and inherit-on-fork flags.
893    */
894
895    char procName[128];    
896    sprintf(procName, "/proc/%d", (int)getPid());
897    fd_ = P_open(procName, O_RDWR, 0);
898    if (fd_ == (unsigned) -1) {
899       perror("Error opening process file descriptor");
900       return false;
901    }
902
903    return true;
904 }
905
906 void dyn_lwp::realLWP_detach_()
907 {
908    assert(is_attached());  // dyn_lwp::detach() shouldn't call us otherwise
909 }
910
911 void dyn_lwp::representativeLWP_detach_()
912 {
913    assert(is_attached());  // dyn_lwp::detach() shouldn't call us otherwise
914    if (fd_) close(fd_);
915 }
916
917
918 void loadNativeDemangler() {}
919
920
921
922
923 bool process::trapDueToDyninstLib()
924 {
925   Address pc;
926   prstatus_t stat;
927
928   if (dyninstlib_brk_addr == 0) return false;
929
930   if (ioctl(getRepresentativeLWP()->get_fd(), PIOCSTATUS, &stat) < 0) {
931       perror("ioctl");
932   }
933
934   //pc = Frame(this).getPC();
935   pc = getRepresentativeLWP()->getActiveFrame().getPC();
936
937   // bperr("testing for trap at entry to DyninstLib, current pc = 0x%lx\n",pc);
938   // bperr("    breakpoint addr = 0x%lx\n", dyninstlib_brk_addr);
939
940   bool ret = (pc == dyninstlib_brk_addr);
941
942   // XXXX - Hack, Tru64 is giving back an invalid pc here, we check for a pc == 0 and
943   //   conclude if we are waiting for a trap for dlopen, then this must be it.
944   //   Need to figure out why this happens. - jkh 1/30/02
945   if (!ret && (stat.pr_reg.regs[31] == 0)) ret = true;
946
947   return ret;
948 }
949
950 bool process::loadDYNINSTlibCleanup()
951 {
952     dyninstlib_brk_addr = 0x0;
953     
954   // restore code and registers
955   bool err;
956   Address code = findInternalAddress("_start", false, err);
957   assert(code);
958   writeDataSpace((void *)code, sizeof(savedCodeBuffer), savedCodeBuffer);
959
960   getRepresentativeLWP()->restoreRegisters(*savedRegs);
961
962   delete savedRegs;
963   savedRegs = NULL;
964   dyninstlib_brk_addr = 0;
965
966   return true;
967 }
968
969
970
971
972
973 bool osfTestProc(int proc_fd, const void *mainLoc)
974 // This function is used to test if the child program is
975 // ready to be read or written to.  mainLoc should be the
976 // address of main() in the mutatee.
977 //
978 // See process::insertTrapAtEntryPointOfMain() below for a
979 // detailed explination of why this function is needed.
980 //
981 // Ray Chen 6/18/2002
982 {
983     return (lseek(proc_fd, reinterpret_cast<off_t>(mainLoc), SEEK_SET) == (off_t)mainLoc);
984 }
985
986 void osfWaitProc(int fd)
987 {
988     int ret;
989     struct pollfd pollFD;
990     struct prstatus status;
991
992     // now wait for the signal
993     memset(&pollFD, '\0', sizeof(pollFD));
994     pollFD.fd = fd;
995     pollFD.events = POLLPRI | POLLNORM;
996     pollFD.revents = 0;
997     ret = poll(&pollFD, 1, -1);
998     if (ret < 0) {
999          pdstring msg("poll failed");
1000          showErrorCallback(101, msg);
1001          return;
1002     }
1003
1004     if (ioctl(fd, PIOCSTATUS, &status) < 0) {
1005          pdstring msg("PIOCSTATUS failed");
1006          showErrorCallback(101, msg);
1007          return;
1008     }
1009 #ifdef DEBUG
1010     bperr("status = %d\n", status.pr_why);
1011     if (status.pr_flags & PR_STOPPED) {
1012         if (status.pr_why == PR_SIGNALLED) {
1013             bperr("stopped for signal %d\n", status.pr_what);
1014         } else if (status.pr_why == PR_FAULTED) {
1015             bperr("stopped for fault %d\n", status.pr_what);
1016         } else if (status.pr_why == PR_SYSEXIT) {
1017             bperr("stopped for exist system call %d\n", status.pr_what);
1018         } else {
1019             bperr("stopped for pr+why = %d\n", status.pr_why);
1020         }
1021     } else {
1022         bperr("process is *not* stopped\n");
1023     }
1024 #endif
1025 }
1026
1027 /*
1028  * Place a trap at the entry point to main.  We need to prod the program
1029  *    along a bit since at the entry to this function, the program is in
1030  *    the dynamic loader and has not yet loaded the segment that contains
1031  *    main.  All we need to do is wait for a SIGTRAP that the loader gives
1032  *    us just after it completes loading.
1033  */
1034 bool process::insertTrapAtEntryPointOfMain()
1035 {
1036   // XXX - Should check if it's statically linked and skip the prod. - jkh
1037   // continueProc_();
1038   // waitProc(proc_fd, SIGTRAP);
1039
1040   // continueProc_();
1041   // waitProc(proc_fd, SIGTRAP);
1042
1043   // save trap address: start of main()
1044   // TODO: use start of "_main" if exists?
1045   bool err;
1046   int countdown = 10;
1047
1048   main_brk_addr = findInternalAddress("main", false, err);
1049   if (!main_brk_addr) {
1050       // failed to locate main
1051       showErrorCallback(108,"Failed to locate main().\n");
1052       return false;
1053   }
1054   assert(main_brk_addr);
1055
1056   // dumpMap(proc_fd);
1057
1058   while (!osfTestProc(getRepresentativeLWP()->get_fd(), (void *)main_brk_addr))
1059   {
1060       // POSSIBLE BUG:  We expect the first SIGTRAP to occur after a
1061       // successful exec call, but we seem to get an early signal.
1062       // At the time of the first SIGTRAP, attempts to read or write the
1063       // child data space fail.
1064       //
1065       // If the child is instructed to continue, it will eventually stop
1066       // in a useable state (before the first instruction of main).  However,
1067       // a SIGTRAP will *NOT* be generated on the second stop.  PROCFS also
1068       // stops in a strange state (prstatus_t.pr_info.si_code == 0).
1069       //
1070       // Looks like this code was in place before.  I don't know why it was
1071       // removed. (I renamed waitProc() to osfWaitProc() to avoid confusion
1072       // with process' waitProcs() class method)
1073       //
1074       // Ray Chen 03/22/02
1075       if (--countdown < 0) {
1076          // looped too many times.
1077          showErrorCallback(108, "Could not access mutatee (even after 10 tries).\n");
1078          return false;
1079       }
1080       
1081       getRepresentativeLWP()->continueLWP_(NoSignal);
1082       osfWaitProc(getRepresentativeLWP()->get_fd());
1083   }
1084   readDataSpace((void *)main_brk_addr, INSN_SIZE, savedCodeBuffer, true);
1085
1086   // insert trap instruction
1087   instruction trapInsn;
1088   generateBreakPoint(trapInsn);
1089
1090   writeDataSpace((void *)main_brk_addr, INSN_SIZE, &trapInsn);
1091   return true;
1092 }
1093
1094 bool process::trapAtEntryPointOfMain(Address)
1095 {
1096   Address pc;
1097
1098   if (main_brk_addr == 0) return false;
1099
1100   //pc = Frame(this).getPC();
1101   pc = getRepresentativeLWP()->getActiveFrame().getPC();
1102
1103   // bperr("testing for trap at enttry to main, current pc = %lx\n", pc);
1104
1105   bool ret = (pc == main_brk_addr);
1106   // if (ret) bperr( ">>> process::trapAtEntryPointOfMain()\n");
1107   return ret;
1108 }
1109
1110 bool process::handleTrapAtEntryPointOfMain()
1111 {
1112     // restore original instruction to entry point of main()
1113     writeDataSpace((void *)main_brk_addr, INSN_SIZE, savedCodeBuffer);
1114
1115     // set PC to be value at the address.
1116    gregset_t theIntRegs;
1117    dyn_lwp *replwp = getRepresentativeLWP();
1118    if (ioctl(replwp->get_fd(), PIOCGREG, &theIntRegs) == -1) {
1119       perror("dyn_lwp::getRegisters PIOCGREG");
1120       if (errno == EBUSY) {
1121          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1122          assert(false);
1123       }
1124       return false;
1125    }
1126    theIntRegs.regs[PC_REGNUM] -= 4;
1127    replwp->changePC(theIntRegs.regs[PC_REGNUM], NULL);
1128    
1129    prstatus info;
1130    ioctl(replwp->get_fd(), PIOCSTATUS,  &info);
1131    while (!prismember(&info.pr_flags, PR_STOPPED))
1132    {
1133        sleep(1);
1134        ioctl(replwp->get_fd(), PIOCSTATUS,  &info);
1135    }
1136    if (ioctl(replwp->get_fd(), PIOCSREG, &theIntRegs) == -1) {
1137        perror("dyn_lwp::getRegisters PIOCGREG");
1138        if (errno == EBUSY) {
1139            cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1140            assert(false);
1141        }
1142        return false;
1143    }
1144    return true;
1145 }
1146
1147
1148 bool process::getDyninstRTLibName() {
1149    if (dyninstRT_name.length() == 0) {
1150       // Get env variable
1151       if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
1152          dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
1153       }
1154       else {
1155          pdstring msg = pdstring("Environment variable ") +
1156                         pdstring("DYNINSTAPI_RT_LIB") +
1157                         pdstring(" has not been defined for process ") +
1158                         pdstring(pid);
1159          showErrorCallback(101, msg);
1160          return false;
1161       }
1162    }
1163    // Check to see if the library given exists.
1164    if (access(dyninstRT_name.c_str(), R_OK)) {
1165       pdstring msg = pdstring("Runtime library ") + dyninstRT_name +
1166                      pdstring(" does not exist or cannot be accessed!");
1167       showErrorCallback(101, msg);
1168       return false;
1169    }
1170    return true;
1171 }
1172
1173
1174
1175 bool process::loadDYNINSTlib()
1176 {
1177     //bperr( ">>> process::loadDYNINSTlib()\n");
1178
1179   // use "_start" as scratch buffer to invoke dlopen() on DYNINST
1180   bool err;
1181   extern bool skipSaveCalls;
1182   Address baseAddr = findInternalAddress("_start", false, err);
1183   assert(baseAddr);
1184   char buf_[BYTES_TO_SAVE];
1185   char *buf = buf_;
1186   instruction illegalInsn;
1187   Address bufSize = 0;
1188
1189   memset(buf, '\0', BYTES_TO_SAVE);
1190
1191   // step 0: illegal instruction (code)
1192   extern void generateIllegalInsn(instruction &);
1193   generateIllegalInsn((instruction &) illegalInsn);
1194   bcopy((char *) &illegalInsn, buf, INSN_SIZE);
1195   bufSize += INSN_SIZE;
1196
1197   // step 1: DYNINST library string (data)
1198   Address libAddr = baseAddr + bufSize;
1199 #ifdef BPATCH_LIBRARY
1200   char *libVar = "DYNINSTAPI_RT_LIB";
1201 #else
1202   char *libVar = "PARADYN_LIB";
1203 #endif
1204   char *libName = getenv(libVar);
1205   if (!libName) {
1206     pdstring msg = pdstring("Environment variable DYNINSTAPI_RT_LIB is not defined,"
1207         " should be set to the pathname of the dyninstAPI_RT runtime library.");
1208     showErrorCallback(101, msg);
1209     return false;
1210   }
1211
1212   int libSize = strlen(libName) + 1;
1213   strcpy((char *) &buf[bufSize], libName);
1214
1215   int npad = INSN_SIZE - (libSize % INSN_SIZE);
1216   bufSize += (libSize + npad);
1217
1218   // step 2: inferior dlopen() call (code)
1219   Address codeAddr = baseAddr + bufSize;
1220
1221   extern registerSpace *createRegisterSpace();
1222   registerSpace *regs = createRegisterSpace();
1223
1224   pdvector<AstNode*> args(2);
1225   AstNode *call;
1226   pdstring callee = "dlopen";
1227   // inferior dlopen(): build AstNodes
1228   args[0] = new AstNode(AstNode::Constant, (void *)libAddr);
1229   args[1] = new AstNode(AstNode::Constant, (void *)RTLD_NOW);
1230   call = new AstNode(callee, args);
1231   removeAst(args[0]);
1232   removeAst(args[1]);
1233
1234   // inferior dlopen(): generate code
1235   regs->resetSpace();
1236
1237   skipSaveCalls = true;         // don't save register, we've done it!
1238   call->generateCode(this, regs, buf, bufSize, true, true);
1239   skipSaveCalls = false;
1240
1241   removeAst(call);
1242
1243   // save registers and "_start" code
1244   readDataSpace((void *)baseAddr, BYTES_TO_SAVE, (void *) savedCodeBuffer,true);
1245   savedRegs = new dyn_saved_regs;
1246   bool status = getRepresentativeLWP()->getRegisters(savedRegs);
1247   assert(status == true);
1248
1249   // step 3: trap instruction (code)
1250   Address trapAddr = baseAddr + bufSize;
1251   instruction bkpt;
1252   generateBreakPoint((instruction &) bkpt);
1253   bcopy((char *) &bkpt, &buf[bufSize], INSN_SIZE);
1254   bufSize += INSN_SIZE;
1255
1256   // step 4: write inferior dlopen code and set PC
1257   assert(bufSize <= BYTES_TO_SAVE);
1258   // bperr( "writing %ld bytes to <0x%08lx:_start>, $pc = 0x%lx\n",
1259       // bufSize, baseAddr, codeAddr);
1260   // bperr( ">>> loadDYNINSTlib <0x%lx(_start): %ld insns>\n",
1261       // baseAddr, bufSize/INSN_SIZE);
1262   writeDataSpace((void *)baseAddr, bufSize, (void *)buf);
1263   bool ret = getRepresentativeLWP()->changePC(codeAddr, savedRegs);
1264   assert(ret);
1265
1266   dyninstlib_brk_addr = trapAddr;
1267   setBootstrapState(loadingRT);
1268   
1269   return true;
1270 }
1271
1272 void process::determineLWPs(pdvector<unsigned> *all_lwps)
1273 {
1274   return;
1275 }