patch to fix exclude whole module
[dyninst.git] / dyninstAPI / src / solaris.C
1 /*
2  * Copyright (c) 1996 Barton P. Miller
3  * 
4  * We provide the Paradyn Parallel Performance Tools (below
5  * described as Paradyn") on an AS IS basis, and do not warrant its
6  * validity or performance.  We reserve the right to update, modify,
7  * or discontinue this software at any time.  We shall have no
8  * obligation to supply such updates or modifications or any other
9  * form of support to you.
10  * 
11  * This license is for research uses.  For such uses, there is no
12  * charge. We define "research use" to mean you may freely use it
13  * inside your organization for whatever purposes you see fit. But you
14  * may not re-distribute Paradyn or parts of Paradyn, in any form
15  * source or binary (including derivatives), electronic or otherwise,
16  * to any other organization or entity without our permission.
17  * 
18  * (for other uses, please contact us at paradyn@cs.wisc.edu)
19  * 
20  * All warranties, including without limitation, any warranty of
21  * merchantability or fitness for a particular purpose, are hereby
22  * excluded.
23  * 
24  * By your use of Paradyn, you understand and agree that we (or any
25  * other person or entity with proprietary rights in Paradyn) are
26  * under no obligation to provide either maintenance services,
27  * update services, notices of latent defects, or correction of
28  * defects for Paradyn.
29  * 
30  * Even if advised of the possibility of such damages, under no
31  * circumstances shall we (or any other person or entity with
32  * proprietary rights in the software licensed hereunder) be liable
33  * to you or any third party for direct, indirect, or consequential
34  * damages of any character regardless of type of action, including,
35  * without limitation, loss of profits, loss of use, loss of good
36  * will, or computer failure or malfunction.  You agree to indemnify
37  * us (and any other person or entity with proprietary rights in the
38  * software licensed hereunder) for any and all liability it may
39  * incur to third parties resulting from your use of Paradyn.
40  */
41
42 #include "dyninstAPI/src/symtab.h"
43 #include "util/h/headers.h"
44 #include "dyninstAPI/src/os.h"
45 #include "dyninstAPI/src/process.h"
46 #include "dyninstAPI/src/stats.h"
47 #include "util/h/Types.h"
48 #include <sys/ioctl.h>
49 #include <fcntl.h>
50 #include <sys/termios.h>
51 #include <unistd.h>
52 #include "paradynd/src/showerror.h"
53 #include "util/h/pathName.h" // concat_pathname_components()
54 #include "util/h/debugOstream.h"
55 #include "util/h/solarisKludges.h"
56
57 #if defined (sparc_sun_solaris2_4)
58 #include "dyninstAPI/src/inst-sparc.h"
59 #else
60 #include "dyninstAPI/src/inst-x86.h"
61 #endif
62
63 #include "instPoint.h"
64
65 #include <sys/procfs.h>
66 #include <poll.h>
67 #include <limits.h>
68 #include <link.h>
69 #include <dlfcn.h>
70
71 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
72
73 extern "C" {
74 extern int ioctl(int, int, ...);
75 extern long sysconf(int);
76 };
77
78 // The following were defined in process.C
79 extern debug_ostream attach_cerr;
80 extern debug_ostream inferiorrpc_cerr;
81 extern debug_ostream shmsample_cerr;
82 extern debug_ostream forkexec_cerr;
83 extern debug_ostream metric_cerr;
84 extern debug_ostream signal_cerr;
85
86 /*
87    Define the indices of some registers to be used with pr_reg.
88    These values are different on sparc and x86 platforms.
89    RETVAL_REG: the registers that holds the return value of calls ($o0 on sparc,
90                %eax on x86).
91    PC_REG: program counter
92    FP_REG: frame pointer (%i7 on sparc, %ebp on x86) 
93 */
94 #ifdef sparc_sun_solaris2_4
95 #define RETVAL_REG (R_O0)
96 #define PC_REG (R_PC)
97 #define FP_REG (R_O6)
98 #endif
99 #ifdef i386_unknown_solaris2_5
100 #define RETVAL_REG (EAX)
101 #define PC_REG (EIP)
102 #define FP_REG (EBP)
103 #endif
104
105
106 extern bool isValidAddress(process *proc, Address where);
107 extern void generateBreakPoint(instruction &insn);
108
109 /*
110    osTraceMe is called after we fork a child process to set
111    a breakpoint on the exit of the exec system call.
112    When /proc is used, this breakpoint **will not** cause a SIGTRAP to 
113    be sent to the process. The parent should use PIOCWSTOP to wait for 
114    the child.
115 */
116 void OS::osTraceMe(void) {
117   sysset_t exitSet;
118   char procName[128];
119
120   sprintf(procName,"/proc/%05d", (int)getpid());
121   int fd = P_open(procName, O_RDWR, 0);
122   if (fd < 0) {
123     fprintf(stderr, "osTraceMe: open failed: %s\n", sys_errlist[errno]); 
124     fflush(stderr);
125     P__exit(-1); // must use _exit here.
126   }
127
128   /* set a breakpoint at the exit of exec/execve */
129   premptyset(&exitSet);
130   praddset(&exitSet, SYS_exec);
131   praddset(&exitSet, SYS_execve);
132
133   if (ioctl(fd, PIOCSEXIT, &exitSet) < 0) {
134     fprintf(stderr, "osTraceMe: PIOCSEXIT failed: %s\n", sys_errlist[errno]); 
135     fflush(stderr);
136     P__exit(-1); // must use _exit here.
137   }
138
139   errno = 0;
140   close(fd);
141   return;
142 }
143
144
145 // already setup on this FD.
146 // disconnect from controlling terminal 
147 void OS::osDisconnect(void) {
148   int ttyfd = open ("/dev/tty", O_RDONLY);
149   ioctl (ttyfd, TIOCNOTTY, NULL); 
150   P_close (ttyfd);
151 }
152
153 bool process::continueWithForwardSignal(int) {
154    if (-1 == ioctl(proc_fd, PIOCRUN, NULL)) {
155       perror("could not forward signal in PIOCRUN");
156       return false;
157    }
158
159    return true;
160 }
161
162 bool process::dumpImage() {return false;}
163
164
165 /* 
166    execResult: return the result of an exec system call - true if succesful.
167    The traced processes will stop on exit of an exec system call, just before
168    returning to user code. At this point the return value (errno) is already
169    written to a register, and we need to check if the return value is zero.
170  */
171 static inline bool execResult(prstatus_t stat) {
172   return (stat.pr_reg[RETVAL_REG] == 0);
173 }
174
175 /*
176    wait for inferior processes to terminate or stop.
177 */
178 int process::waitProcs(int *status) {
179    extern vector<process*> processVec;
180
181    static struct pollfd fds[OPEN_MAX];  // argument for poll
182    static int selected_fds;             // number of selected
183    static int curr;                     // the current element of fds
184
185    /* Each call to poll may return many selected fds. Since we only report the status
186       of one process per each call to waitProcs, we keep the result of the last
187       poll buffered, and simply process an element from the buffer until all of
188       the selected fds in the last poll have been processed.
189    */
190
191    if (selected_fds == 0) {
192      for (unsigned u = 0; u < processVec.size(); u++) {
193        if (processVec[u] && (processVec[u]->status() == running || processVec[u]->status() == neonatal))
194          fds[u].fd = processVec[u]->proc_fd;
195        else
196          fds[u].fd = -1;
197        fds[u].events = POLLPRI;
198        fds[u].revents = 0;
199      }
200
201      selected_fds = poll(fds, processVec.size(), 0);
202      if (selected_fds < 0) {
203        fprintf(stderr, "waitProcs: poll failed: %s\n", sys_errlist[errno]);
204        selected_fds = 0;
205        return 0;
206      }
207
208      curr = 0;
209    }
210    
211    if (selected_fds > 0) {
212      while (fds[curr].revents == 0)
213        ++curr;
214
215      // fds[curr] has an event of interest
216      prstatus_t stat;
217      int ret = 0;
218
219      if (ioctl(fds[curr].fd, PIOCSTATUS, &stat) != -1 
220          && ((stat.pr_flags & PR_STOPPED) || (stat.pr_flags & PR_ISTOP))) {
221        switch (stat.pr_why) {
222        case PR_SIGNALLED:
223          // return the signal number
224          *status = stat.pr_what << 8 | 0177;
225          ret = processVec[curr]->getPid();
226 #if defined(USES_LIBDYNINSTRT_SO)
227          if (!processVec[curr]->dyninstLibAlreadyLoaded() && 
228              processVec[curr]->wasCreatedViaAttach()) {
229            // make sure we are stopped in the eyes of paradynd - naim
230            bool wasRunning = (processVec[curr]->status() == running);
231            if (processVec[curr]->status() != stopped)
232              processVec[curr]->Stopped();   
233            if(processVec[curr]->isDynamicallyLinked()) {
234              processVec[curr]->handleIfDueToSharedObjectMapping();
235            }
236            if (processVec[curr]->trapDueToDyninstLib()) {
237              // we need to load libdyninstRT.so.1 - naim
238              processVec[curr]->handleIfDueToDyninstLib();
239            }
240            if (wasRunning) 
241              if (!processVec[curr]->continueProc()) assert(0);
242          }
243 #endif
244          break;
245        case PR_SYSEXIT: {
246          // exit of a system call.
247          process *p = processVec[curr];
248
249          if (p->RPCs_waiting_for_syscall_to_complete) {
250             // reset PIOCSEXIT mask
251             inferiorrpc_cerr << "solaris got PR_SYSEXIT!" << endl;
252             assert(p->save_exitset_ptr != NULL);
253             if (-1 == ioctl(p->proc_fd, PIOCSEXIT, p->save_exitset_ptr))
254                assert(false);
255             delete [] p->save_exitset_ptr;
256             p->save_exitset_ptr = NULL;
257
258             // fall through on purpose (so status, ret get set)
259          }
260          else if (!execResult(stat)) {
261            // a failed exec. continue the process
262            processVec[curr]->continueProc_();
263            break;
264          }          
265
266          *status = SIGTRAP << 8 | 0177;
267          ret = processVec[curr]->getPid();
268          break;
269        }
270        case PR_REQUESTED:
271          assert(0);
272        case PR_JOBCONTROL:
273          assert(0);
274          break;
275        }        
276       }
277
278      --selected_fds;
279      ++curr;
280
281      if (ret > 0) {
282        return ret;
283      }
284    }
285
286    return waitpid(0, status, WNOHANG);
287 }
288
289
290 static char *extract_string_ptr(int procfd, char **ptr) {
291    // we want to return *ptr.
292
293    if (-1 == lseek(procfd, (long)ptr, SEEK_SET))
294       assert(false);
295
296    char *result;
297    if (-1 == read(procfd, &result, sizeof(result)))
298       assert(false);
299
300    return result;   
301 }
302
303 string extract_string(int procfd, const char *inferiorptr) {
304    // assuming inferiorptr points to a null-terminated string in the inferior
305    // process, extract it and return it.
306
307    if (-1 == lseek(procfd, (long)inferiorptr, SEEK_SET))
308       return "";
309
310    string result;
311    while (true) {
312       char buffer[100];
313       if (-1 == read(procfd, &buffer, 80))
314          return "";
315       buffer[80] = '\0';
316       result += buffer;
317
318       // was there a '\0' anywhere in chars 0 thru 79?  If so then
319       // we're done
320       for (unsigned lcv=0; lcv < 80; lcv++)
321          if (buffer[lcv] == '\0') {
322             //attach_cerr << "extract_string returning " << result << endl;
323             return result;
324          }
325    }
326 }
327
328 bool get_ps_stuff(int proc_fd, string &argv0, string &pathenv, string &cwdenv) {
329    // Use ps info to obtain argv[0], PATH, and curr working directory of the
330    // inferior process designated by proc_fd.  Writes to argv0, pathenv, cwdenv.
331
332    prpsinfo the_psinfo;
333    if (-1 == ioctl(proc_fd, PIOCPSINFO, &the_psinfo))
334        return false;
335
336    if (the_psinfo.pr_zomb)
337        return false;
338
339    // get argv[0].  It's in the_psinfo.pr_argv[0], but that's a ptr in the inferior
340    // space, so we need to /proc read() it out.  Also, the_psinfo.pr_argv is a char **
341    // not a char* so we even need to /proc read() to get a pointer value.  Ick.
342    assert(the_psinfo.pr_argv != NULL);
343    char *ptr_to_argv0 = extract_string_ptr(proc_fd, the_psinfo.pr_argv);
344    argv0 = extract_string(proc_fd, ptr_to_argv0);
345
346    // Get the PWD and PATH environment variables from the application.
347    char **envptr = the_psinfo.pr_envp;
348    while (true) {
349       // dereference envptr; check for NULL
350       char *env = extract_string_ptr(proc_fd, envptr);
351       if (env == NULL)
352          break;
353
354       string env_value = extract_string(proc_fd, env);
355       if (env_value.prefixed_by("PWD=") || env_value.prefixed_by("CWD=")) {
356          cwdenv = env_value.string_of() + 4; // skip past "PWD=" or "CWD="
357          attach_cerr << "get_ps_stuff: using PWD value of: " << cwdenv << endl;
358       }
359       else if (env_value.prefixed_by("PATH=")) {
360          pathenv = env_value.string_of() + 5; // skip past the "PATH="
361          attach_cerr << "get_ps_stuff: using PATH value of: " << pathenv << endl;
362       }
363
364       envptr++;
365    }
366
367    return true;
368 }
369
370 /*
371    Open the /proc file correspoding to process pid, 
372    set the signals to be caught to be only SIGSTOP and SIGTRAP,
373    and set the kill-on-last-close and inherit-on-fork flags.
374 */
375 extern string pd_flavor ;
376 bool process::attach() {
377   char procName[128];
378
379   // QUESTION: does this attach operation lead to a SIGTRAP being forwarded
380   // to paradynd in all cases?  How about when we are attaching to an
381   // already-running process?  (Seems that in the latter case, no SIGTRAP
382   // is automatically generated)
383
384   // step 1) /proc open: attach to the inferior process
385   sprintf(procName,"/proc/%05d", (int)pid);
386   int fd = P_open(procName, O_RDWR, 0);
387   if (fd < 0) {
388     fprintf(stderr, "attach: open failed: %s\n", sys_errlist[errno]);
389     return false;
390   }
391
392   // step 2) /proc PIOCSTRACE: define which signals should be forwarded to daemon
393   //   These are (1) SIGSTOP and (2) either SIGTRAP (sparc) or SIGILL (x86), to
394   //   implement inferiorRPC completion detection.
395
396   sigset_t sigs;
397
398   /*  ALERT ALERT !!!!  Important do NOT commit....  */
399   prfillset(&sigs);
400
401   /*  ****  UNCOMMENT BEFORE COMMIT!!!!    ****
402   premptyset(&sigs);
403   praddset(&sigs, SIGSTOP);
404
405 #ifndef i386_unknown_solaris2_5
406   praddset(&sigs, SIGTRAP);
407 #endif
408
409 #ifdef i386_unknown_solaris2_5
410   praddset(&sigs, SIGILL);
411 #endif
412   *********************************************/
413
414   if (ioctl(fd, PIOCSTRACE, &sigs) < 0) {
415     fprintf(stderr, "attach: ioctl failed: %s\n", sys_errlist[errno]);
416     close(fd);
417     return false;
418   }
419
420   // Step 3) /proc PIOCSET:
421   // a) turn on the kill-on-last-close flag (kills inferior with SIGKILL when
422   //    the last writable /proc fd closes)
423   // b) turn on inherit-on-fork flag (tracing flags inherited when child forks).
424   // c) turn on breakpoint trap pc adjustment (x86 only).
425   // Also, any child of this process will stop at the exit of an exec call.
426
427   //Tempest, do not need to inherit-on-fork
428   long flags ;
429   if(process::pdFlavor == string("cow"))
430         flags = PR_KLC |  PR_BPTADJ;
431   else
432         flags = PR_KLC | PR_FORK | PR_BPTADJ;
433   if (ioctl (fd, PIOCSET, &flags) < 0) {
434     fprintf(stderr, "attach: PIOCSET failed: %s\n", sys_errlist[errno]);
435     close(fd);
436     return false;
437   }
438
439   proc_fd = fd;
440
441   if (!get_ps_stuff(proc_fd, this->argv0, this->pathenv, this->cwdenv))
442       return false;
443
444   return true;
445 }
446
447 #if defined(USES_LIBDYNINSTRT_SO)
448 bool process::trapAtEntryPointOfMain()
449 {
450   prgregset_t regs;
451   if (ioctl (proc_fd, PIOCGREG, &regs) != -1) {
452     // is the trap instr at main_brk_addr?
453     if(regs[R_PC] == (int)main_brk_addr){ 
454       return(true);
455     }
456   }
457   return(false);
458 }
459
460 bool process::trapDueToDyninstLib()
461 {
462   prgregset_t regs;
463   if (ioctl (proc_fd, PIOCGREG, &regs) != -1) {
464     // is the trap instr at dyninstlib_brk_addr?
465     if(regs[R_PC] == (int)dyninstlib_brk_addr){ 
466       return(true);
467     }
468   }
469   return(false);
470 }
471
472 void process::handleIfDueToDyninstLib() 
473 {
474   // rewrite original instructions in the text segment we use for 
475   // the inferiorRPC - naim
476   unsigned count = sizeof(savedCodeBuffer);
477   //Address codeBase = getImage()->codeOffset();
478
479   Address codeBase = (this->findOneFunction("_start"))->addr();
480   assert(codeBase);
481   writeDataSpace((void *)codeBase, count, (char *)savedCodeBuffer);
482   restoreRegisters(savedRegs); 
483   // this should put the PC at the right position, that is, at the entry point
484   // of main - naim
485 }
486
487 void process::handleTrapAtEntryPointOfMain()
488 {
489   function_base *f_main = findOneFunction("main");
490   assert(f_main);
491   unsigned addr = f_main->addr();
492   // restore original instruction 
493   writeDataSpace((void *)addr, sizeof(instruction), (char *)savedCodeBuffer);
494 }
495
496 void process::insertTrapAtEntryPointOfMain()
497 {
498   function_base *f_main = findOneFunction("main");
499   assert(f_main);
500   unsigned addr = f_main->addr();
501   // save original instruction first
502   readDataSpace((void *)addr, sizeof(instruction), savedCodeBuffer, true);
503   // and now, insert trap
504   instruction insnTrap;
505   generateBreakPoint(insnTrap);
506   //insnTrap.raw = BREAK_POINT_INSN;
507   writeDataSpace((void *)addr, sizeof(instruction), (char *)&insnTrap);  
508   main_brk_addr = addr;
509 }
510
511 bool process::dlopenDYNINSTlib() {
512   // we will write the following into a buffer and copy it into the
513   // application process's address space
514   // [....LIBRARY's NAME...|code for DLOPEN]
515
516   // write to the application at codeOffset. This won't work if we
517   // attach to a running process.
518   //Address codeBase = this->getImage()->codeOffset();
519   // ...let's try "_start" instead
520   Address codeBase = (this->findOneFunction("_start"))->addr();
521   assert(codeBase);
522
523   // Or should this be readText... it seems like they are identical
524   // the remaining stuff is thanks to Marcelo's ideas - this is what 
525   // he does in NT. The major change here is that we use AST's to 
526   // generate code for dlopen.
527
528   // savedCodeBuffer[BYTES_TO_SAVE] is declared in process.h
529   readDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer, true);
530
531   unsigned char scratchCodeBuffer[BYTES_TO_SAVE];
532   vector<AstNode*> dlopenAstArgs(2);
533
534   unsigned count = 0;
535
536 #ifdef BPATCH_LIBRARY   /* dyninst API doesn't load libsocket.so.1 */
537   AstNode *dlopenAst;
538 #else
539   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void*)0); 
540   // library name. We use a scratch value first. We will update this parameter
541   // later, once we determine the offset to find the string - naim
542   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE); // mode
543   AstNode *dlopenAst = new AstNode("dlopen",dlopenAstArgs);
544   removeAst(dlopenAstArgs[0]);
545   removeAst(dlopenAstArgs[1]);
546 #endif
547
548   // deadList and deadListSize are defined in inst-sparc.C - naim
549   extern int deadList[];
550   extern int deadListSize;
551   registerSpace *dlopenRegSpace = new registerSpace(deadListSize/sizeof(int), deadList, 0, NULL);
552   dlopenRegSpace->resetSpace();
553
554 #ifndef BPATCH_LIBRARY /* dyninst API doesn't load libsocket.so.1 */
555   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
556                           count, true);
557   writeDataSpace((void *)codeBase, count, (char *)scratchCodeBuffer);
558   count += sizeof(instruction);
559 #endif
560
561   // we need to make 2 calls to dlopen: one to load libsocket.so.1 and another
562   // one to load libdyninst.so.1 - naim
563
564 #ifndef BPATCH_LIBRARY /* since dyninst API didn't create an ast yet */
565   removeAst(dlopenAst); // to avoid memory leaks - naim
566 #endif
567   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void*)0);
568   // library name. We use a scratch value first. We will update this parameter
569   // later, once we determine the offset to find the string - naim
570   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE); // mode
571   dlopenAst = new AstNode("dlopen",dlopenAstArgs);
572   removeAst(dlopenAstArgs[0]);
573   removeAst(dlopenAstArgs[1]);
574
575   unsigned dyninst_count = 0;
576   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
577                           dyninst_count, true);
578   writeDataSpace((void *)codeBase, dyninst_count, (char *)scratchCodeBuffer);
579   dyninst_count += sizeof(instruction);
580   count += dyninst_count;
581
582 #ifdef ndef
583   // NOTE: this is an example of the code that could go here to check for
584   // the return value of dlopen. If dlopen returns NULL, which means failure,
585   // we won't be able to load libdyninstRT.so.1. If this happens, paradynd
586   // will notice it anyway and it will print a message to the user saying that
587   // dlopen failed for some reason. It might be better to be able to call
588   // dlerror at this point and print the corresponding error message, but we
589   // will need to add a "printOp" or something similar to the AstNode class
590   // to do this, plus we will need to find the address of dlerror first in the
591   // same way we do it for dlopen - naim 8/13/97
592
593   // we now check the return value of dlopen. If it is NULL, which means that
594   // dlopen has failed, we then go ahead and retry calling it again until it
595   // succeeds - naim
596   AstNode *check_dlopen_result;
597   AstNode *expression;
598   AstNode *action;
599   AstNode *part1, *part2;
600   part1 = new AstNode(AstNode::DataReg,(void *)RETVAL_REG);
601   part2 = new AstNode(AstNode::Constant,(void *)0);
602   expression = new AstNode(eqOp, part1, part2);
603   removeAst(part1);
604   removeAst(part2);
605   AstNode *offset;
606   // offset if the number of instructions from this point to the beginning
607   // of codeBase. If the number of instructions generated change, we also
608   // have to change this value (15 for now) - naim
609   offset = new AstNode(AstNode::Constant, (void *)(-15*sizeof(instruction))); 
610   action = new AstNode(branchOp, offset);
611   removeAst(offset);
612   check_dlopen_result = new AstNode(ifOp, expression, action); 
613   removeAst(expression);
614   removeAst(action);
615   unsigned astcount=0;
616   check_dlopen_result->generateCode(this, dlopenRegSpace, 
617                                     (char *)scratchCodeBuffer, astcount, true);
618   writeDataSpace((void *)(codeBase+count), astcount, 
619                  (char *)scratchCodeBuffer);
620   count += astcount;
621   removeAst(check_dlopen_result);
622 #endif
623
624   instruction insnTrap;
625   generateBreakPoint(insnTrap);
626   //insnTrap.raw = BREAK_POINT_INSN;
627   writeDataSpace((void *)(codeBase + count), sizeof(instruction), 
628                  (char *)&insnTrap);
629   dyninstlib_brk_addr = codeBase + count;
630   count += sizeof(instruction);
631
632   char libname[256];
633 #ifdef BPATCH_LIBRARY  /* dyninst API loads a different run-time library */
634   if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
635     strcpy((char*)libname,(char*)getenv("DYNINSTAPI_RT_LIB"));
636   } else {
637     string msg = string("DYNINSTAPI_RT_LIB is not defined");
638     showErrorCallback(101, msg);
639     return false;
640   }
641 #else
642   if (getenv("PARADYN_LIB") != NULL) {
643     strcpy((char*)libname,(char*)getenv("PARADYN_LIB"));
644   } else {
645     string msg = string("PARADYN_LIB has not been defined for ") +
646                  string("process") + string(pid);
647     showErrorCallback(101, msg);
648     return false;
649   }
650 #endif
651
652   unsigned dyninstlib_addr = (unsigned) (codeBase + count);
653
654   writeDataSpace((void *)(codeBase + count), strlen(libname)+1,
655                  (caddr_t)libname);
656   count += strlen(libname)+1;
657   // we have now written the name of the library after the trap - naim
658
659 #ifdef BPATCH_LIBRARY  /* dyninst API doesn't load libsocket.so.1 */
660   assert(count<=BYTES_TO_SAVE);
661   // The dyninst API doesn't load the socket library
662 #else
663   char socketname[256];
664   if (getenv("PARADYN_SOCKET_LIB") != NULL) {
665     strcpy((char*)socketname,(char*)getenv("PARADYN_SOCKET_LIB"));
666   } else {
667     strcpy((char*)socketname,(char *)"/usr/lib/libsocket.so.1");
668   }
669   unsigned socketlib_addr = (unsigned) (codeBase + count);
670   writeDataSpace((void *)(codeBase + count), 
671                  strlen(socketname)+1, (caddr_t)socketname);
672   count += strlen(socketname)+1;
673   // we have now written the name of the socket library after the trap - naim
674   //
675   assert(count<=BYTES_TO_SAVE);
676 #endif
677
678 #ifdef BPATCH_LIBRARY  /* dyninst API doesn't load libsocket.so.1 */
679   count = 0; // reset count
680 #else
681   // at this time, we know the offset for the library name, so we fix the
682   // call to dlopen and we just write the code again! This is probably not
683   // very elegant, but it is easy and it works - naim
684   removeAst(dlopenAst); // to avoid leaking memory
685   //dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void *)(codeBase+count+strlen(libname)+1));
686   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void *)(socketlib_addr));
687   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE);
688   dlopenAst = new AstNode("dlopen",dlopenAstArgs);
689   removeAst(dlopenAstArgs[0]);
690   removeAst(dlopenAstArgs[1]);
691   count = 0; // reset count
692   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
693                           count, true);
694   writeDataSpace((void *)codeBase, count, (char *)scratchCodeBuffer);
695   removeAst(dlopenAst);
696 #endif
697
698   // at this time, we know the offset for the library name, so we fix the
699   // call to dlopen and we just write the code again! This is probably not
700   // very elegant, but it is easy and it works - naim
701   removeAst(dlopenAst); // to avoid leaking memory
702   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void *)(dyninstlib_addr));
703   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE);
704   dlopenAst = new AstNode("dlopen",dlopenAstArgs);
705   removeAst(dlopenAstArgs[0]);
706   removeAst(dlopenAstArgs[1]);
707   dyninst_count = 0; // reset count
708   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
709                           dyninst_count, true);
710   writeDataSpace((void *)(codeBase+count), dyninst_count, (char *)scratchCodeBuffer);
711   removeAst(dlopenAst);
712
713   savedRegs = getRegisters();
714   assert((savedRegs!=NULL) && (savedRegs!=(void *)-1));
715   isLoadingDyninstLib = true;
716   if (!changePC(codeBase,savedRegs)) // this uses the info in "savedRegs"
717   {
718     logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
719     assert(0);
720   }
721
722   return true;
723 }
724
725 unsigned process::get_dlopen_addr() const {
726   if (dyn != NULL)
727     return(dyn->get_dlopen_addr());
728   else 
729     return(0);
730 }
731 #endif
732
733 bool process::isRunning_() const {
734    // determine if a process is running by doing low-level system checks, as
735    // opposed to checking the 'status_' member vrble.  May assume that attach()
736    // has run, but can't assume anything else.
737    prstatus theStatus;
738    if (-1 == ioctl(proc_fd, PIOCSTATUS, &theStatus)) {
739       perror("process::isRunning_()");
740       assert(false);
741    }
742
743    if (theStatus.pr_flags & PR_STOPPED)
744       return false;
745    else
746       return true;
747 }
748
749 bool process::attach_() {assert(false);}
750 bool process::stop_() {assert(false);}
751
752 /* 
753    continue a process that is stopped 
754 */
755 bool process::continueProc_() {
756   ptraceOps++; ptraceOtherOps++;
757   prrun_t flags;
758   prstatus_t stat;
759
760 //cerr << "welcome to continueProc_()" << endl;
761
762   // a process that receives a stop signal stops twice. We need to run the process
763   // and wait for the second stop. (The first run simply absorbs the stop signal;
764   // the second one does the actual continue.)
765   if ((ioctl(proc_fd, PIOCSTATUS, &stat) != -1)
766       && (stat.pr_flags & PR_STOPPED)
767       && (stat.pr_why == PR_SIGNALLED)
768       && (stat.pr_what == SIGSTOP || stat.pr_what == SIGINT)) {
769     flags.pr_flags = PRSTOP;
770     if (ioctl(proc_fd, PIOCRUN, &flags) == -1) {
771       fprintf(stderr, "continueProc_: PIOCRUN failed: %s\n", sys_errlist[errno]);
772       return false;
773     }
774     if (ioctl(proc_fd, PIOCWSTOP, 0) == -1) {
775       fprintf(stderr, "continueProc_: PIOCWSTOP failed: %s\n", sys_errlist[errno]);
776       return false;
777     }
778   }
779   flags.pr_flags = PRCSIG; // clear current signal
780   if (hasNewPC) {
781     // set new program counter
782     //cerr << "continueProc_ doing new currentPC: " << (void*)currentPC_ << endl;
783     flags.pr_vaddr = (caddr_t) currentPC_;
784     flags.pr_flags |= PRSVADDR;
785     hasNewPC = false;
786   }
787   if (ioctl(proc_fd, PIOCRUN, &flags) == -1) {
788     fprintf(stderr, "continueProc_: PIOCRUN 2 failed: %s\n", sys_errlist[errno]);
789     return false;
790   }
791
792   return true;
793 }
794
795 #ifdef BPATCH_LIBRARY
796 /*
797    terminate execution of a process
798  */
799 bool process::terminateProc_()
800 {
801     int sig = SIGKILL;
802     if (ioctl(proc_fd, PIOCKILL, &sig) == -1)
803         return false;
804     else
805         return true;
806 }
807 #endif
808
809 /*
810    pause a process that is running
811 */
812 bool process::pause_() {
813   ptraceOps++; ptraceOtherOps++;
814   int ioctl_ret;
815
816   // /proc PIOCSTOP: direct all LWPs to stop, _and_ wait for them to stop.
817   ioctl_ret = ioctl(proc_fd, PIOCSTOP, 0);
818   if (ioctl_ret == -1) {
819       sprintf(errorLine, "warn : process::pause_ use ioctl to send PICOSTOP returns error : errno = %i\n", errno);
820       perror("warn : process::pause_ ioctl PICOSTOP: ");
821       logLine(errorLine);
822   }
823   return (ioctl_ret != -1);
824 }
825
826 /*
827    close the file descriptor for the file associated with a process
828 */
829 bool process::detach_() {
830   close(proc_fd);
831   return true;
832 }
833
834 #ifdef BPATCH_LIBRARY
835 /*
836    detach from thr process, continuing its execution if the parameter "cont"
837    is true.
838  */
839 bool process::API_detach_(const bool cont)
840 {
841   // Reset the kill-on-close flag, and the run-on-last-close flag if necessary
842   long flags = PR_KLC;
843   if (!cont) flags |= PR_RLC;
844   if (ioctl (proc_fd, PIOCRESET, &flags) < 0) {
845     fprintf(stderr, "detach: PIOCRESET failed: %s\n", sys_errlist[errno]);
846     close(proc_fd);
847     return false;
848   }
849   // Set the run-on-last-close-flag if necessary
850   if (cont) {
851     flags = PR_RLC;
852     if (ioctl (proc_fd, PIOCSET, &flags) < 0) {
853       fprintf(stderr, "detach: PIOCSET failed: %s\n", sys_errlist[errno]);
854       close(proc_fd);
855       return false;
856     }
857   }
858
859   sigset_t sigs;
860   premptyset(&sigs);
861   if (ioctl(proc_fd, PIOCSTRACE, &sigs) < 0) {
862     fprintf(stderr, "detach: PIOCSTRACE failed: %s\n", sys_errlist[errno]);
863     close(proc_fd);
864     return false;
865   }
866   if (ioctl(proc_fd, PIOCSHOLD, &sigs) < 0) {
867     fprintf(stderr, "detach: PIOCSHOLD failed: %s\n", sys_errlist[errno]);
868     close(proc_fd);
869     return false;
870   }
871
872   fltset_t faults;
873   premptyset(&faults);
874   if (ioctl(proc_fd, PIOCSFAULT, &faults) < 0) {
875     fprintf(stderr, "detach: PIOCSFAULT failed: %s\n", sys_errlist[errno]);
876     close(proc_fd);
877     return false;
878   }
879   
880   sysset_t syscalls;
881   premptyset(&syscalls);
882   if (ioctl(proc_fd, PIOCSENTRY, &syscalls) < 0) {
883     fprintf(stderr, "detach: PIOCSENTRY failed: %s\n", sys_errlist[errno]);
884     close(proc_fd);
885     return false;
886   }
887   if (ioctl(proc_fd, PIOCSEXIT, &syscalls) < 0) {
888     fprintf(stderr, "detach: PIOCSEXIT failed: %s\n", sys_errlist[errno]);
889     close(proc_fd);
890     return false;
891   }
892
893   close(proc_fd);
894   return true;
895 }
896 #endif
897
898 bool process::dumpCore_(const string) {
899   return false;
900 }
901
902 bool process::writeTextWord_(caddr_t inTraced, int data) {
903 //  cerr << "writeTextWord @ " << (void *)inTraced << endl; cerr.flush();
904   return writeDataSpace_(inTraced, sizeof(int), (caddr_t) &data);
905 }
906
907 bool process::writeTextSpace_(void *inTraced, int amount, const void *inSelf) {
908 //  cerr << "writeTextSpace pid=" << getPid() << ", @ " << (void *)inTraced << " len=" << amount << endl; cerr.flush();
909   return writeDataSpace_(inTraced, amount, inSelf);
910 }
911
912 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
913 bool process::readTextSpace_(void *inTraced, int amount, const void *inSelf) {
914   return readDataSpace_(inTraced, amount, inSelf);
915 }
916 #endif
917
918 bool process::writeDataSpace_(void *inTraced, int amount, const void *inSelf) {
919   ptraceOps++; ptraceBytes += amount;
920
921 //  cerr << "process::writeDataSpace_ pid " << getPid() << " writing " << amount << " bytes at loc " << inTraced << endl;
922
923   if (lseek(proc_fd, (off_t)inTraced, SEEK_SET) != (off_t)inTraced)
924     return false;
925   return (write(proc_fd, inSelf, amount) == amount);
926 }
927
928 bool process::readDataSpace_(const void *inTraced, int amount, void *inSelf) {
929   ptraceOps++; ptraceBytes += amount;
930   if((lseek(proc_fd, (off_t)inTraced, SEEK_SET)) != (off_t)inTraced) {
931     printf("error in lseek addr = 0x%x amount = %d\n",(u_int)inTraced,amount);
932     return false;
933   }
934   return (read(proc_fd, inSelf, amount) == amount);
935 }
936
937 bool process::loopUntilStopped() {
938   assert(0);
939 }
940
941 #ifdef notdef
942 // TODO -- only call getrusage once per round
943 static struct rusage *get_usage_data() {
944   return NULL;
945 }
946 #endif
947
948 float OS::compute_rusage_cpu() {
949   return 0;
950 }
951
952 float OS::compute_rusage_sys() {
953   return 0;
954 }
955
956 float OS::compute_rusage_min() {
957   return 0;
958 }
959 float OS::compute_rusage_maj() {
960   return 0;
961 }
962
963 float OS::compute_rusage_swap() {
964   return 0;
965 }
966 float OS::compute_rusage_io_in() {
967   return 0;
968 }
969 float OS::compute_rusage_io_out() {
970   return 0;
971 }
972 float OS::compute_rusage_msg_send() {
973   return 0;
974 }
975 float OS::compute_rusage_msg_recv() {
976   return 0;
977 }
978 float OS::compute_rusage_sigs() {
979   return 0;
980 }
981 float OS::compute_rusage_vol_cs() {
982   return 0;
983 }
984 float OS::compute_rusage_inv_cs() {
985   return 0;
986 }
987
988 int getNumberOfCPUs()
989 {
990   // _SC_NPROCESSORS_CONF is the number of processors configured in the
991   // system and _SC_NPROCESSORS_ONLN is the number of those processors that
992   // are online.
993   int numberOfCPUs;
994   numberOfCPUs = (int) sysconf(_SC_NPROCESSORS_ONLN);
995   if (numberOfCPUs) 
996     return(numberOfCPUs);
997   else 
998     return(1);
999 }  
1000
1001
1002 bool process::getActiveFrame(int *fp, int *pc)
1003 {
1004   prgregset_t regs;
1005   bool ok=false;
1006
1007   if (ioctl (proc_fd, PIOCGREG, &regs) != -1) {
1008       *fp=regs[FP_REG];
1009       *pc=regs[PC_REG];
1010       ok=true;
1011   }
1012   return(ok);
1013 }
1014
1015 #ifdef sparc_sun_solaris2_4
1016
1017 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool uppermost)
1018 {
1019   bool readOK=true;
1020   struct {
1021     int fp;
1022     int rtn;
1023   } addrs;
1024
1025   prgregset_t regs;
1026   function_base *func;
1027   int pc = *rtn;
1028
1029   if (uppermost) {
1030       func = this->findFunctionIn(pc);
1031       if (func) {
1032          if (func->hasNoStackFrame()) { // formerly "isLeafFunc()"
1033               if (ioctl (proc_fd, PIOCGREG, &regs) != -1) {
1034                   *rtn = regs[R_O7] + 8;
1035                   return readOK;
1036               }    
1037          }
1038       }
1039   }
1040
1041   //
1042   // For the sparc, register %i7 is the return address - 8 and the fp is
1043   // register %i6. These registers can be located in currentFP+14*5 and
1044   // currentFP+14*4 respectively, but to avoid two calls to readDataSpace,
1045   // we bring both together (i.e. 8 bytes of memory starting at currentFP+14*4
1046   // or currentFP+56).
1047   // These values are copied to the stack when the application is paused,
1048   // so we are assuming that the application is paused at this point
1049
1050   if (readDataSpace((caddr_t) (currentFP + 56),
1051                     sizeof(int)*2, (caddr_t) &addrs, true)) {
1052     // this is the previous frame pointer
1053     *fp = addrs.fp;
1054     // return address
1055     *rtn = addrs.rtn + 8;
1056
1057     // if pc==0, then we are in the outermost frame and we should stop. We
1058     // do this by making fp=0.
1059
1060     if ( (addrs.rtn == 0) || !isValidAddress(this,(Address) addrs.rtn) ) {
1061       readOK=false;
1062     }
1063   }
1064   else {
1065     readOK=false;
1066   }
1067
1068
1069   return(readOK);
1070 }
1071
1072 #endif
1073
1074 #ifdef SHM_SAMPLING
1075 time64 process::getInferiorProcessCPUtime() {
1076    // returns user+sys time from the u or proc area of the inferior process, which in
1077    // turn is presumably obtained by mmapping it (sunos) or by using a /proc ioctl
1078    // to obtain it (solaris).  It must not stop the inferior process in order
1079    // to obtain the result, nor can it assue that the inferior has been stopped.
1080    // The result MUST be "in sync" with rtinst's DYNINSTgetCPUtime().
1081
1082    // We use the PIOCUSAGE /proc ioctl
1083
1084    // Other /proc ioctls that should work too: PIOCPSINFO
1085    // and the lower-level PIOCGETPR and PIOCGETU which return copies of the proc
1086    // and u areas, respectively.
1087    // PIOCSTATUS does _not_ work because its results are not in sync
1088    // with DYNINSTgetCPUtime
1089
1090    time64 result;
1091    prpsinfo_t theUsage;
1092
1093    if (ioctl(proc_fd, PIOCPSINFO, &theUsage) == -1) {
1094       perror("could not read CPU time of inferior PIOCPSINFO");
1095       return 0;
1096    }
1097    result = PDYN_mulMillion(theUsage.pr_time.tv_sec); // sec to usec
1098    result += PDYN_div1000(theUsage.pr_time.tv_nsec);  // nsec to usec
1099
1100    if (result<previous) {
1101      // time shouldn't go backwards, but we have seen this happening
1102      // before, so we better check it just in case - naim 5/30/97
1103      logLine("********* time going backwards in paradynd **********\n");
1104      result=previous;
1105    } else {
1106      previous=result;
1107    }
1108
1109    return result;
1110 }
1111 #endif
1112
1113 void *process::getRegisters() {
1114    // Astonishingly, this routine can be shared between solaris/sparc and
1115    // solaris/x86.  All hail /proc!!!
1116
1117    // assumes the process is stopped (/proc requires it)
1118    assert(status_ == stopped);
1119
1120    prgregset_t theIntRegs;
1121    if (ioctl(proc_fd, PIOCGREG, &theIntRegs) == -1) {
1122       perror("process::getRegisters PIOCGREG");
1123       if (errno == EBUSY) {
1124          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1125          assert(false);
1126       }
1127
1128       return NULL;
1129    }
1130
1131    prfpregset_t theFpRegs;
1132    if (ioctl(proc_fd, PIOCGFPREG, &theFpRegs) == -1) {
1133       perror("process::getRegisters PIOCGFPREG");
1134       if (errno == EBUSY)
1135          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1136       else if (errno == EINVAL)
1137          // what to do in this case?  Probably shouldn't even do a print, right?
1138          // And it certainly shouldn't be an error, right?
1139          // But I wonder if any sparcs out there really don't have floating point.
1140          cerr << "It appears that this machine doesn't have floating-point instructions" << endl;
1141
1142       return NULL;
1143    }
1144
1145    const int numbytesPart1 = sizeof(prgregset_t);
1146    const int numbytesPart2 = sizeof(prfpregset_t);
1147    assert(numbytesPart1 % 4 == 0);
1148    assert(numbytesPart2 % 4 == 0);
1149
1150    void *buffer = new char[numbytesPart1 + numbytesPart2];
1151    assert(buffer);
1152
1153    memcpy(buffer, &theIntRegs, sizeof(theIntRegs));
1154    memcpy((char *)buffer + sizeof(theIntRegs), &theFpRegs, sizeof(theFpRegs));
1155
1156    return buffer;
1157 }
1158
1159 bool process::executingSystemCall() {
1160    prstatus theStatus;
1161    if (ioctl(proc_fd, PIOCSTATUS, &theStatus) != -1) {
1162      if (theStatus.pr_syscall > 0) {
1163        inferiorrpc_cerr << "pr_syscall=" << theStatus.pr_syscall << endl;
1164        return(true);
1165      }
1166    } else assert(0);
1167    return(false);
1168 }
1169
1170 bool process::changePC(unsigned addr, const void *savedRegs) {
1171    assert(status_ == stopped);
1172
1173    prgregset_t theIntRegs = *(const prgregset_t *)savedRegs; // makes a copy, on purpose
1174
1175    theIntRegs[R_PC] = addr; // PC (sparc), EIP (x86)
1176 #ifdef R_nPC  // true for sparc, not for x86
1177    theIntRegs[R_nPC] = addr + 4;
1178 #endif
1179
1180    if (ioctl(proc_fd, PIOCSREG, &theIntRegs) == -1) {
1181       perror("process::changePC PIOCSREG failed");
1182       if (errno == EBUSY)
1183          cerr << "It appears that the process wasn't stopped in the eyes of /proc" << endl;
1184       return false;
1185    }
1186
1187    return true;
1188 }
1189
1190 bool process::changePC(unsigned addr) {
1191    assert(status_ == stopped); // /proc will require this
1192
1193    prgregset_t theIntRegs;
1194    if (-1 == ioctl(proc_fd, PIOCGREG, &theIntRegs)) {
1195       perror("process::changePC PIOCGREG");
1196       if (errno == EBUSY) {
1197          cerr << "It appears that the process wasn't stopped in the eyes of /proc" << endl;
1198          assert(false);
1199       }
1200       return false;
1201    }
1202
1203    theIntRegs[R_PC] = addr;
1204 #ifdef R_nPC
1205    theIntRegs[R_nPC] = addr + 4;
1206 #endif
1207
1208    if (-1 == ioctl(proc_fd, PIOCSREG, &theIntRegs)) {
1209       perror("process::changePC PIOCSREG");
1210       if (errno == EBUSY) {
1211          cerr << "It appears that the process wasn't stopped in the eyes of /proc" << endl;
1212          assert(false);
1213       }
1214       return false;
1215    }
1216
1217    return true;
1218 }
1219
1220 bool process::restoreRegisters(void *buffer) {
1221    // The fact that this routine can be shared between solaris/sparc and
1222    // solaris/x86 is just really, really cool.  /proc rules!
1223
1224    assert(status_ == stopped); // /proc requires it
1225
1226    prgregset_t theIntRegs = *(prgregset_t *)buffer;
1227    prfpregset_t theFpRegs = *(prfpregset_t *)((char *)buffer + sizeof(theIntRegs));
1228
1229    if (ioctl(proc_fd, PIOCSREG, &theIntRegs) == -1) {
1230       perror("process::restoreRegisters PIOCSREG failed");
1231       if (errno == EBUSY) {
1232          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1233          assert(false);
1234       }
1235       return false;
1236    }
1237
1238    if (ioctl(proc_fd, PIOCSFPREG, &theFpRegs) == -1) {
1239       perror("process::restoreRegisters PIOCSFPREG failed");
1240       if (errno == EBUSY) {
1241          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1242          assert(false);
1243       }
1244       return false;
1245    }
1246
1247    return true;
1248 }
1249
1250 #ifdef i386_unknown_solaris2_5
1251
1252 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool )
1253 {
1254   bool readOK=true;
1255   struct {
1256     int fp;
1257     int rtn;
1258   } addrs;
1259
1260   //
1261   // for the x86, the frame-pointer (EBP) points to the previous frame-pointer,
1262   // and the saved return address is in EBP-4.
1263   //
1264
1265   if (readDataSpace((caddr_t) (currentFP),
1266                     sizeof(int)*2, (caddr_t) &addrs, true)) {
1267     // this is the previous frame pointer
1268     *fp = addrs.fp;
1269     // return address
1270     *rtn = addrs.rtn;
1271
1272     // if pc==0, then we are in the outermost frame and we should stop. We
1273     // do this by making fp=0.
1274
1275     if ( (addrs.rtn == 0) || !isValidAddress(this,(Address) addrs.rtn) ) {
1276       readOK=false;
1277     }
1278   }
1279   else {
1280     readOK=false;
1281   }
1282
1283   return(readOK);
1284 }
1285
1286 #endif
1287
1288 #ifdef i386_unknown_solaris2_5
1289 // ******** TODO **********
1290 bool process::needToAddALeafFrame(Frame , Address &) {
1291   return false;
1292 }
1293
1294 #else
1295
1296 // needToAddALeafFrame: returns true if the between the current frame 
1297 // and the next frame there is a leaf function (this occurs when the 
1298 // current frame is the signal handler and the function that was executing
1299 // when the sighandler was called is a leaf function)
1300 bool process::needToAddALeafFrame(Frame current_frame, Address &leaf_pc){
1301
1302    // check to see if the current frame is the signal handler 
1303    Address frame_pc = current_frame.getPC();
1304    Address sig_addr = 0;
1305    const image *sig_image = (signal_handler->file())->exec();
1306    if(getBaseAddress(sig_image, sig_addr)){
1307        sig_addr += signal_handler->getAddress(0);
1308    } else {
1309        sig_addr = signal_handler->getAddress(0);
1310    }
1311    u_int sig_size = signal_handler->size();
1312    if(signal_handler&&(frame_pc >= sig_addr)&&(frame_pc < (sig_addr+sig_size))){
1313        // get the value of the saved PC: this value is stored in the address
1314        // specified by the value in register i2 + 44. Register i2 must contain
1315        // the address of some struct that contains, among other things, the 
1316        // saved PC value.  
1317        u_int reg_i2;
1318        int fp = current_frame.getFramePtr();
1319        if (readDataSpace((caddr_t)(fp+40),sizeof(u_int),(caddr_t)&reg_i2,true)){
1320           if (readDataSpace((caddr_t) (reg_i2+44), sizeof(int),
1321                             (caddr_t) &leaf_pc,true)){
1322               // if the function is a leaf function return true
1323               function_base *func = findFunctionIn(leaf_pc);
1324               if(func && func->hasNoStackFrame()) { // formerly "isLeafFunc()"
1325                   return(true);
1326               }
1327           }
1328       }
1329    }
1330    return false;
1331 }
1332 #endif
1333
1334 string process::tryToFindExecutable(const string &iprogpath, int pid) {
1335    // returns empty string on failure.
1336    // Otherwise, returns a full-path-name for the file.  Tries every
1337    // trick to determine the full-path-name, even though "progpath" may be
1338    // unspecified (empty string).
1339    
1340    // Remember, we can always return the empty string...no need to
1341    // go nuts writing the world's most complex algorithm.
1342
1343    attach_cerr << "welcome to tryToFindExecutable; progpath=" << iprogpath << ", pid=" << pid << endl;
1344
1345    const string progpath = expand_tilde_pathname(iprogpath);
1346
1347    // Trivial case: if "progpath" is specified and the file exists then nothing needed
1348    if (exists_executable(progpath)) {
1349       attach_cerr << "tryToFindExecutable succeeded immediately, returning "
1350                   << progpath << endl;
1351       return progpath;
1352    }
1353
1354    attach_cerr << "tryToFindExecutable failed on filename " << progpath << endl;
1355
1356    char buffer[128];
1357    sprintf(buffer, "/proc/%05d", pid);
1358    int procfd = open(buffer, O_RDONLY, 0);
1359    if (procfd == -1) {
1360       attach_cerr << "tryToFindExecutable failed since open of /proc failed" << endl;
1361       return "";
1362    }
1363    attach_cerr << "tryToFindExecutable: opened /proc okay" << endl;
1364
1365    string argv0, path, cwd;
1366    if (get_ps_stuff(procfd, argv0, path, cwd)) {
1367        // the following routine is implemented in the util lib.
1368        string result;
1369        if (executableFromArgv0AndPathAndCwd(result, argv0, path, cwd)) {
1370           (void)close(procfd);
1371           return result;
1372        }
1373    }
1374
1375    attach_cerr << "tryToFindExecutable: giving up" << endl;
1376
1377    (void)close(procfd);
1378    return "";
1379 }
1380
1381 bool process::set_breakpoint_for_syscall_completion() {
1382    /* Can assume: (1) process is paused and (2) in a system call.
1383       We want to set a TRAP for the syscall exit, and do the
1384       inferiorRPC at that time.  We'll use /proc PIOCSEXIT.
1385       Returns true iff breakpoint was successfully set. */
1386
1387    sysset_t save_exitset;
1388    if (-1 == ioctl(proc_fd, PIOCGEXIT, &save_exitset))
1389       return false;
1390
1391    sysset_t new_exit_set;
1392    prfillset(&new_exit_set);
1393    if (-1 == ioctl(proc_fd, PIOCSEXIT, &new_exit_set))
1394       return false;
1395
1396    assert(save_exitset_ptr == NULL);
1397    save_exitset_ptr = new sysset_t;
1398    memcpy(save_exitset_ptr, &save_exitset, sizeof(save_exitset));
1399
1400    return true;
1401 }
1402
1403 unsigned process::read_inferiorRPC_result_register(reg) {
1404    prgregset_t theIntRegs;
1405    if (-1 == ioctl(proc_fd, PIOCGREG, &theIntRegs)) {
1406       perror("process::read_inferiorRPC_result_register PIOCGREG");
1407       if (errno == EBUSY) {
1408          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1409          assert(false);
1410       }
1411       return 0; // assert(false)?
1412    }
1413
1414    // on x86, the result is always stashed in %EAX; on sparc, it's always %o0.  In
1415    // neither case do we need the argument of this fn.
1416 #ifdef i386_unknown_solaris2_5
1417    return theIntRegs[EAX];
1418 #else
1419    return theIntRegs[R_O0];
1420 #endif
1421 }
1422
1423 void print_read_error_info(const relocationEntry entry, 
1424       pd_Function *&target_pdf, Address base_addr) {
1425
1426     sprintf(errorLine, "  entry      : target_addr 0x%x\n",
1427             entry.target_addr());
1428     logLine(errorLine);
1429     sprintf(errorLine, "               rel_addr 0x%x\n", entry.rel_addr());
1430     logLine(errorLine);
1431     sprintf(errorLine, "               name %s\n", (entry.name()).string_of());
1432     logLine(errorLine);
1433
1434     sprintf(errorLine, "  target_pdf : symTabName %s\n",
1435             (target_pdf->symTabName()).string_of());
1436     logLine(errorLine);    
1437     sprintf(errorLine , "              prettyName %s\n",
1438             (target_pdf->symTabName()).string_of());
1439     logLine(errorLine);
1440     sprintf(errorLine , "              size %i\n",
1441             target_pdf->size());
1442     logLine(errorLine);
1443     sprintf(errorLine , "              addr 0x%x\n",
1444             target_pdf->addr());
1445     logLine(errorLine);
1446
1447     sprintf(errorLine, "  base_addr  0x%x\n", base_addr);
1448     logLine(errorLine);
1449 }
1450
1451 // hasBeenBound: returns true if the runtime linker has bound the
1452 // function symbol corresponding to the relocation entry in at the address
1453 // specified by entry and base_addr.  If it has been bound, then the callee 
1454 // function is returned in "target_pdf", else it returns false.
1455 bool process::hasBeenBound(const relocationEntry entry, 
1456                            pd_Function *&target_pdf, Address base_addr) {
1457
1458 // TODO: the x86 and sparc versions should really go in seperate files 
1459 #if defined(i386_unknown_solaris2_5)
1460
1461     if (status() == exited) return false;
1462
1463     // if the relocationEntry has not been bound yet, then the value
1464     // at rel_addr is the address of the instruction immediately following
1465     // the first instruction in the PLT entry (which is at the target_addr) 
1466     // The PLT entries are never modified, instead they use an indirrect 
1467     // jump to an address stored in the _GLOBAL_OFFSET_TABLE_.  When the 
1468     // function symbol is bound by the runtime linker, it changes the address
1469     // in the _GLOBAL_OFFSET_TABLE_ corresponding to the PLT entry
1470
1471     Address got_entry = entry.rel_addr() + base_addr;
1472     Address bound_addr = 0;
1473     if(!readDataSpace((const void*)got_entry, sizeof(Address), 
1474                         &bound_addr, true)){
1475         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%x, pid=%d\n (readDataSpace returns 0)",got_entry,pid);
1476         logLine(errorLine);
1477         print_read_error_info(entry, target_pdf, base_addr);
1478         return false;
1479     }
1480
1481     if( !( bound_addr == (entry.target_addr()+6+base_addr)) ) {
1482         // the callee function has been bound by the runtime linker
1483         // find the function and return it
1484         target_pdf = findpdFunctionIn(bound_addr);
1485         if(!target_pdf){
1486             return false;
1487         }
1488         return true;    
1489     }
1490     return false;
1491
1492 #else
1493     // if the relocationEntry has not been bound yet, then the second instr 
1494     // in this PLT entry branches to the fist PLT entry.  If it has been   
1495     // bound, then second two instructions of the PLT entry have been changed 
1496     // by the runtime linker to jump to the address of the function.  
1497     // Here is an example:   
1498     //     before binding                       after binding
1499     //     --------------                       -------------
1500     //     sethi  %hi(0x15000), %g1             sethi  %hi(0x15000), %g1
1501     //     b,a  <_PROCEDURE_LINKAGE_TABLE_>     sethi  %hi(0xef5eb000), %g1
1502     //     nop                                  jmp  %g1 + 0xbc ! 0xef5eb0bc
1503
1504     instruction next_insn;
1505     Address next_insn_addr = entry.target_addr() + base_addr + 4; 
1506     if( !(readDataSpace((caddr_t)next_insn_addr, sizeof(next_insn), 
1507                        (char *)&next_insn, true)) ) {
1508         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%x (readDataSpace next_isin_addr returns 0)\n",
1509                 next_insn_addr);
1510         logLine(errorLine);
1511         print_read_error_info(entry, target_pdf, base_addr);
1512     }
1513     // if this is a b,a instruction, then the function has not been bound
1514     if((next_insn.branch.op == FMT2op)  && (next_insn.branch.op2 == BICCop2) 
1515        && (next_insn.branch.anneal == 1) && (next_insn.branch.cond == BAcond)) {
1516         return false;
1517     } 
1518
1519     // if this is a sethi instruction, then it has been bound...get target_addr
1520     instruction third_insn;
1521     Address third_addr = entry.target_addr() + base_addr + 8; 
1522     if( !(readDataSpace((caddr_t)third_addr, sizeof(third_insn), 
1523                        (char *)&third_insn, true)) ) {
1524         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%x (readDataSpace third_addr returns 0)\n",
1525                 third_addr);
1526         logLine(errorLine);
1527         print_read_error_info(entry,target_pdf, base_addr);
1528     }
1529
1530     // get address of bound function, and return the corr. pd_Function
1531     if((next_insn.sethi.op == FMT2op) && (next_insn.sethi.op2 == SETHIop2)
1532         && (third_insn.rest.op == RESTop) && (third_insn.rest.i == 1)
1533         && (third_insn.rest.op3 == JMPLop3)) {
1534         
1535         Address new_target = (next_insn.sethi.imm22 << 10) & 0xfffffc00; 
1536         new_target |= third_insn.resti.simm13;
1537
1538         target_pdf = findpdFunctionIn(new_target);
1539         if(!target_pdf){
1540             return false;
1541         }
1542         return true;
1543     }
1544     // this is a messed up entry
1545     return false;
1546 #endif
1547
1548 }
1549
1550
1551
1552 // findCallee: finds the function called by the instruction corresponding
1553 // to the instPoint "instr". If the function call has been bound to an
1554 // address, then the callee function is returned in "target" and the 
1555 // instPoint "callee" data member is set to pt to callee's function_base.  
1556 // If the function has not yet been bound, then "target" is set to the 
1557 // function_base associated with the name of the target function (this is 
1558 // obtained by the PLT and relocation entries in the image), and the instPoint
1559 // callee is not set.  If the callee function cannot be found, (ex. function
1560 // pointers, or other indirect calls), it returns false.
1561 // Returns false on error (ex. process doesn't contain this instPoint).
1562 //
1563 // The assumption here is that for all processes sharing the image containing
1564 // this instPoint they are going to bind the call target to the same function. 
1565 // For shared objects this is always true, however this may not be true for
1566 // dynamic executables.  Two a.outs can be identical except for how they are
1567 // linked, so a call to fuction foo in one version of the a.out may be bound
1568 // to function foo in libfoo.so.1, and in the other version it may be bound to 
1569 // function foo in libfoo.so.2.  We are currently not handling this case, since
1570 // it is unlikely to happen in practice.
1571 bool process::findCallee(instPoint &instr, function_base *&target){
1572     
1573     if((target = (function_base *)instr.iPgetCallee())) {
1574         return true; // callee already set
1575     }
1576
1577     // find the corresponding image in this process  
1578     const image *owner = instr.iPgetOwner();
1579     bool found_image = false;
1580     Address base_addr = 0;
1581     if(symbols == owner) {  found_image = true; } 
1582     else if(shared_objects){
1583         for(u_int i=0; i < shared_objects->size(); i++){
1584             if(owner == ((*shared_objects)[i])->getImage()) {
1585                 found_image = true;
1586                 base_addr = ((*shared_objects)[i])->getBaseAddress();
1587                 break;
1588             }
1589         }
1590     } 
1591     if(!found_image) {
1592         target = 0;
1593         return false; // image not found...this is bad
1594     }
1595
1596     // get the target address of this function
1597     Address target_addr = 0;
1598 //    Address insn_addr = instr.iPgetAddress(); 
1599     target_addr = instr.getTargetAddress();
1600
1601     if(!target_addr) {  
1602         // this is either not a call instruction or an indirect call instr
1603         // that we can't get the target address
1604         target = 0;
1605         return false;
1606     }
1607
1608 #if defined(sparc_sun_solaris2_4)
1609     // If this instPoint is from a function that was relocated to the heap
1610     // then need to get the target address relative to this image   
1611     if(target_addr && instr.relocated_) {
1612         assert(target_addr > base_addr);
1613         target_addr -= base_addr;
1614     }
1615 #endif
1616
1617     // see if there is a function in this image at this target address
1618     // if so return it
1619     pd_Function *pdf = 0;
1620     if( (pdf = owner->findFunctionInInstAndUnInst(target_addr,this)) ) {
1621         target = pdf;
1622         instr.set_callee(pdf);
1623         return true; // target found...target is in this image
1624     }
1625
1626     // else, get the relocation information for this image
1627     const Object &obj = owner->getObject();
1628     const vector<relocationEntry> *fbt;
1629     if(!obj.get_func_binding_table_ptr(fbt)) {
1630         target = 0;
1631         return false; // target cannot be found...it is an indirect call.
1632     }
1633
1634     // find the target address in the list of relocationEntries
1635     for(u_int i=0; i < fbt->size(); i++) {
1636         if((*fbt)[i].target_addr() == target_addr) {
1637             // check to see if this function has been bound yet...if the
1638             // PLT entry for this function has been modified by the runtime
1639             // linker
1640             pd_Function *target_pdf = 0;
1641             if(hasBeenBound((*fbt)[i], target_pdf, base_addr)) {
1642                 target = target_pdf;
1643                 instr.set_callee(target_pdf);
1644                 return true;  // target has been bound
1645             } 
1646             else {
1647                 // just try to find a function with the same name as entry 
1648                 target = findOneFunctionFromAll((*fbt)[i].name());
1649                 if(target){
1650                     return true;
1651                 }
1652                 else {  
1653                     // KLUDGE: this is because we are not keeping more than
1654                     // one name for the same function if there is more
1655                     // than one.  This occurs when there are weak symbols
1656                     // that alias global symbols (ex. libm.so.1: "sin" 
1657                     // and "__sin").  In most cases the alias is the same as 
1658                     // the global symbol minus one or two leading underscores,
1659                     // so here we add one or two leading underscores to search
1660                     // for the name to handle the case where this string 
1661                     // is the name of the weak symbol...this will not fix 
1662                     // every case, since if the weak symbol and global symbol
1663                     // differ by more than leading underscores we won't find
1664                     // it...when we parse the image we should keep multiple
1665                     // names for pd_Functions
1666
1667                     string s = string("_");
1668                     s += (*fbt)[i].name();
1669                     target = findOneFunctionFromAll(s);
1670                     if(target){
1671                         return true;
1672                     }
1673                     s = string("__");
1674                     s += (*fbt)[i].name();
1675                     target = findOneFunctionFromAll(s);
1676                     if(target){
1677                         return true;
1678                     }
1679                 }
1680             }
1681             target = 0;
1682             return false;
1683         }
1684     }
1685     target = 0;
1686     return false;  
1687 }