*** empty log message ***
[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   sigset_t sigs;
396   premptyset(&sigs);
397   praddset(&sigs, SIGSTOP);
398
399 #ifndef i386_unknown_solaris2_5
400   praddset(&sigs, SIGTRAP);
401 #endif
402
403 #ifdef i386_unknown_solaris2_5
404   praddset(&sigs, SIGILL);
405 #endif
406
407   if (ioctl(fd, PIOCSTRACE, &sigs) < 0) {
408     fprintf(stderr, "attach: ioctl failed: %s\n", sys_errlist[errno]);
409     close(fd);
410     return false;
411   }
412
413   // Step 3) /proc PIOCSET:
414   // a) turn on the kill-on-last-close flag (kills inferior with SIGKILL when
415   //    the last writable /proc fd closes)
416   // b) turn on inherit-on-fork flag (tracing flags inherited when child forks).
417   // c) turn on breakpoint trap pc adjustment (x86 only).
418   // Also, any child of this process will stop at the exit of an exec call.
419
420   //Tempest, do not need to inherit-on-fork
421   long flags ;
422   if(process::pdFlavor == string("cow"))
423         flags = PR_KLC |  PR_BPTADJ;
424   else
425         flags = PR_KLC | PR_FORK | PR_BPTADJ;
426   if (ioctl (fd, PIOCSET, &flags) < 0) {
427     fprintf(stderr, "attach: PIOCSET failed: %s\n", sys_errlist[errno]);
428     close(fd);
429     return false;
430   }
431
432   proc_fd = fd;
433
434   if (!get_ps_stuff(proc_fd, this->argv0, this->pathenv, this->cwdenv))
435       return false;
436
437   return true;
438 }
439
440 #if defined(USES_LIBDYNINSTRT_SO)
441 bool process::trapAtEntryPointOfMain()
442 {
443   prgregset_t regs;
444   if (ioctl (proc_fd, PIOCGREG, &regs) != -1) {
445     // is the trap instr at main_brk_addr?
446     if(regs[R_PC] == (int)main_brk_addr){ 
447       return(true);
448     }
449   }
450   return(false);
451 }
452
453 bool process::trapDueToDyninstLib()
454 {
455   prgregset_t regs;
456   if (ioctl (proc_fd, PIOCGREG, &regs) != -1) {
457     // is the trap instr at dyninstlib_brk_addr?
458     if(regs[R_PC] == (int)dyninstlib_brk_addr){ 
459       return(true);
460     }
461   }
462   return(false);
463 }
464
465 void process::handleIfDueToDyninstLib() 
466 {
467   // rewrite original instructions in the text segment we use for 
468   // the inferiorRPC - naim
469   unsigned count = sizeof(savedCodeBuffer);
470   //Address codeBase = getImage()->codeOffset();
471
472   Address codeBase = (this->findOneFunction("_start"))->addr();
473   assert(codeBase);
474   writeDataSpace((void *)codeBase, count, (char *)savedCodeBuffer);
475   restoreRegisters(savedRegs); 
476   // this should put the PC at the right position, that is, at the entry point
477   // of main - naim
478 }
479
480 void process::handleTrapAtEntryPointOfMain()
481 {
482   function_base *f_main = findOneFunction("main");
483   assert(f_main);
484   unsigned addr = f_main->addr();
485   // restore original instruction 
486   writeDataSpace((void *)addr, sizeof(instruction), (char *)savedCodeBuffer);
487 }
488
489 void process::insertTrapAtEntryPointOfMain()
490 {
491   function_base *f_main = findOneFunction("main");
492   assert(f_main);
493   unsigned addr = f_main->addr();
494   // save original instruction first
495   readDataSpace((void *)addr, sizeof(instruction), savedCodeBuffer, true);
496   // and now, insert trap
497   instruction insnTrap;
498   generateBreakPoint(insnTrap);
499   //insnTrap.raw = BREAK_POINT_INSN;
500   writeDataSpace((void *)addr, sizeof(instruction), (char *)&insnTrap);  
501   main_brk_addr = addr;
502 }
503
504 bool process::dlopenDYNINSTlib() {
505   // we will write the following into a buffer and copy it into the
506   // application process's address space
507   // [....LIBRARY's NAME...|code for DLOPEN]
508
509   // write to the application at codeOffset. This won't work if we
510   // attach to a running process.
511   //Address codeBase = this->getImage()->codeOffset();
512   // ...let's try "_start" instead
513   Address codeBase = (this->findOneFunction("_start"))->addr();
514   assert(codeBase);
515
516   // Or should this be readText... it seems like they are identical
517   // the remaining stuff is thanks to Marcelo's ideas - this is what 
518   // he does in NT. The major change here is that we use AST's to 
519   // generate code for dlopen.
520
521   // savedCodeBuffer[BYTES_TO_SAVE] is declared in process.h
522   readDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer, true);
523
524   unsigned char scratchCodeBuffer[BYTES_TO_SAVE];
525   vector<AstNode*> dlopenAstArgs(2);
526
527   unsigned count = 0;
528
529 #ifdef BPATCH_LIBRARY   /* dyninst API doesn't load libsocket.so.1 */
530   AstNode *dlopenAst;
531 #else
532   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void*)0); 
533   // library name. We use a scratch value first. We will update this parameter
534   // later, once we determine the offset to find the string - naim
535   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE); // mode
536   AstNode *dlopenAst = new AstNode("dlopen",dlopenAstArgs);
537   removeAst(dlopenAstArgs[0]);
538   removeAst(dlopenAstArgs[1]);
539 #endif
540
541   // deadList and deadListSize are defined in inst-sparc.C - naim
542   extern int deadList[];
543   extern int deadListSize;
544   registerSpace *dlopenRegSpace = new registerSpace(deadListSize/sizeof(int), deadList, 0, NULL);
545   dlopenRegSpace->resetSpace();
546
547 #ifndef BPATCH_LIBRARY /* dyninst API doesn't load libsocket.so.1 */
548   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
549                           count, true);
550   writeDataSpace((void *)codeBase, count, (char *)scratchCodeBuffer);
551   count += sizeof(instruction);
552 #endif
553
554   // we need to make 2 calls to dlopen: one to load libsocket.so.1 and another
555   // one to load libdyninst.so.1 - naim
556
557 #ifndef BPATCH_LIBRARY /* since dyninst API didn't create an ast yet */
558   removeAst(dlopenAst); // to avoid memory leaks - naim
559 #endif
560   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void*)0);
561   // library name. We use a scratch value first. We will update this parameter
562   // later, once we determine the offset to find the string - naim
563   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE); // mode
564   dlopenAst = new AstNode("dlopen",dlopenAstArgs);
565   removeAst(dlopenAstArgs[0]);
566   removeAst(dlopenAstArgs[1]);
567
568   unsigned dyninst_count = 0;
569   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
570                           dyninst_count, true);
571   writeDataSpace((void *)codeBase, dyninst_count, (char *)scratchCodeBuffer);
572   dyninst_count += sizeof(instruction);
573   count += dyninst_count;
574
575 #ifdef ndef
576   // NOTE: this is an example of the code that could go here to check for
577   // the return value of dlopen. If dlopen returns NULL, which means failure,
578   // we won't be able to load libdyninstRT.so.1. If this happens, paradynd
579   // will notice it anyway and it will print a message to the user saying that
580   // dlopen failed for some reason. It might be better to be able to call
581   // dlerror at this point and print the corresponding error message, but we
582   // will need to add a "printOp" or something similar to the AstNode class
583   // to do this, plus we will need to find the address of dlerror first in the
584   // same way we do it for dlopen - naim 8/13/97
585
586   // we now check the return value of dlopen. If it is NULL, which means that
587   // dlopen has failed, we then go ahead and retry calling it again until it
588   // succeeds - naim
589   AstNode *check_dlopen_result;
590   AstNode *expression;
591   AstNode *action;
592   AstNode *part1, *part2;
593   part1 = new AstNode(AstNode::DataReg,(void *)RETVAL_REG);
594   part2 = new AstNode(AstNode::Constant,(void *)0);
595   expression = new AstNode(eqOp, part1, part2);
596   removeAst(part1);
597   removeAst(part2);
598   AstNode *offset;
599   // offset if the number of instructions from this point to the beginning
600   // of codeBase. If the number of instructions generated change, we also
601   // have to change this value (15 for now) - naim
602   offset = new AstNode(AstNode::Constant, (void *)(-15*sizeof(instruction))); 
603   action = new AstNode(branchOp, offset);
604   removeAst(offset);
605   check_dlopen_result = new AstNode(ifOp, expression, action); 
606   removeAst(expression);
607   removeAst(action);
608   unsigned astcount=0;
609   check_dlopen_result->generateCode(this, dlopenRegSpace, 
610                                     (char *)scratchCodeBuffer, astcount, true);
611   writeDataSpace((void *)(codeBase+count), astcount, 
612                  (char *)scratchCodeBuffer);
613   count += astcount;
614   removeAst(check_dlopen_result);
615 #endif
616
617   instruction insnTrap;
618   generateBreakPoint(insnTrap);
619   //insnTrap.raw = BREAK_POINT_INSN;
620   writeDataSpace((void *)(codeBase + count), sizeof(instruction), 
621                  (char *)&insnTrap);
622   dyninstlib_brk_addr = codeBase + count;
623   count += sizeof(instruction);
624
625   char libname[256];
626 #ifdef BPATCH_LIBRARY  /* dyninst API loads a different run-time library */
627   if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
628     strcpy((char*)libname,(char*)getenv("DYNINSTAPI_RT_LIB"));
629   } else {
630     string msg = string("DYNINSTAPI_RT_LIB is not defined");
631     showErrorCallback(101, msg);
632     return false;
633   }
634 #else
635   if (getenv("PARADYN_LIB") != NULL) {
636     strcpy((char*)libname,(char*)getenv("PARADYN_LIB"));
637   } else {
638     string msg = string("PARADYN_LIB has not been defined for ") +
639                  string("process") + string(pid);
640     showErrorCallback(101, msg);
641     return false;
642   }
643 #endif
644
645   unsigned dyninstlib_addr = (unsigned) (codeBase + count);
646
647   writeDataSpace((void *)(codeBase + count), strlen(libname)+1,
648                  (caddr_t)libname);
649   count += strlen(libname)+1;
650   // we have now written the name of the library after the trap - naim
651
652 #ifdef BPATCH_LIBRARY  /* dyninst API doesn't load libsocket.so.1 */
653   assert(count<=BYTES_TO_SAVE);
654   // The dyninst API doesn't load the socket library
655 #else
656   char socketname[256];
657   if (getenv("PARADYN_SOCKET_LIB") != NULL) {
658     strcpy((char*)socketname,(char*)getenv("PARADYN_SOCKET_LIB"));
659   } else {
660     strcpy((char*)socketname,(char *)"/usr/lib/libsocket.so.1");
661   }
662   unsigned socketlib_addr = (unsigned) (codeBase + count);
663   writeDataSpace((void *)(codeBase + count), 
664                  strlen(socketname)+1, (caddr_t)socketname);
665   count += strlen(socketname)+1;
666   // we have now written the name of the socket library after the trap - naim
667   //
668   assert(count<=BYTES_TO_SAVE);
669 #endif
670
671 #ifdef BPATCH_LIBRARY  /* dyninst API doesn't load libsocket.so.1 */
672   count = 0; // reset count
673 #else
674   // at this time, we know the offset for the library name, so we fix the
675   // call to dlopen and we just write the code again! This is probably not
676   // very elegant, but it is easy and it works - naim
677   removeAst(dlopenAst); // to avoid leaking memory
678   //dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void *)(codeBase+count+strlen(libname)+1));
679   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void *)(socketlib_addr));
680   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE);
681   dlopenAst = new AstNode("dlopen",dlopenAstArgs);
682   removeAst(dlopenAstArgs[0]);
683   removeAst(dlopenAstArgs[1]);
684   count = 0; // reset count
685   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
686                           count, true);
687   writeDataSpace((void *)codeBase, count, (char *)scratchCodeBuffer);
688   removeAst(dlopenAst);
689 #endif
690
691   // at this time, we know the offset for the library name, so we fix the
692   // call to dlopen and we just write the code again! This is probably not
693   // very elegant, but it is easy and it works - naim
694   removeAst(dlopenAst); // to avoid leaking memory
695   dlopenAstArgs[0] = new AstNode(AstNode::Constant, (void *)(dyninstlib_addr));
696   dlopenAstArgs[1] = new AstNode(AstNode::Constant, (void*)DLOPEN_MODE);
697   dlopenAst = new AstNode("dlopen",dlopenAstArgs);
698   removeAst(dlopenAstArgs[0]);
699   removeAst(dlopenAstArgs[1]);
700   dyninst_count = 0; // reset count
701   dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
702                           dyninst_count, true);
703   writeDataSpace((void *)(codeBase+count), dyninst_count, (char *)scratchCodeBuffer);
704   removeAst(dlopenAst);
705
706   savedRegs = getRegisters();
707   assert((savedRegs!=NULL) && (savedRegs!=(void *)-1));
708   isLoadingDyninstLib = true;
709   if (!changePC(codeBase,savedRegs)) // this uses the info in "savedRegs"
710   {
711     logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
712     assert(0);
713   }
714
715   return true;
716 }
717
718 unsigned process::get_dlopen_addr() const {
719   if (dyn != NULL)
720     return(dyn->get_dlopen_addr());
721   else 
722     return(0);
723 }
724 #endif
725
726 bool process::isRunning_() const {
727    // determine if a process is running by doing low-level system checks, as
728    // opposed to checking the 'status_' member vrble.  May assume that attach()
729    // has run, but can't assume anything else.
730    prstatus theStatus;
731    if (-1 == ioctl(proc_fd, PIOCSTATUS, &theStatus)) {
732       perror("process::isRunning_()");
733       assert(false);
734    }
735
736    if (theStatus.pr_flags & PR_STOPPED)
737       return false;
738    else
739       return true;
740 }
741
742 bool process::attach_() {assert(false);}
743 bool process::stop_() {assert(false);}
744
745 /* 
746    continue a process that is stopped 
747 */
748 bool process::continueProc_() {
749   ptraceOps++; ptraceOtherOps++;
750   prrun_t flags;
751   prstatus_t stat;
752
753 //cerr << "welcome to continueProc_()" << endl;
754
755   // a process that receives a stop signal stops twice. We need to run the process
756   // and wait for the second stop. (The first run simply absorbs the stop signal;
757   // the second one does the actual continue.)
758   if ((ioctl(proc_fd, PIOCSTATUS, &stat) != -1)
759       && (stat.pr_flags & PR_STOPPED)
760       && (stat.pr_why == PR_SIGNALLED)
761       && (stat.pr_what == SIGSTOP || stat.pr_what == SIGINT)) {
762     flags.pr_flags = PRSTOP;
763     if (ioctl(proc_fd, PIOCRUN, &flags) == -1) {
764       fprintf(stderr, "continueProc_: PIOCRUN failed: %s\n", sys_errlist[errno]);
765       return false;
766     }
767     if (ioctl(proc_fd, PIOCWSTOP, 0) == -1) {
768       fprintf(stderr, "continueProc_: PIOCWSTOP failed: %s\n", sys_errlist[errno]);
769       return false;
770     }
771   }
772   flags.pr_flags = PRCSIG; // clear current signal
773   if (hasNewPC) {
774     // set new program counter
775     //cerr << "continueProc_ doing new currentPC: " << (void*)currentPC_ << endl;
776     flags.pr_vaddr = (caddr_t) currentPC_;
777     flags.pr_flags |= PRSVADDR;
778     hasNewPC = false;
779   }
780   if (ioctl(proc_fd, PIOCRUN, &flags) == -1) {
781     fprintf(stderr, "continueProc_: PIOCRUN 2 failed: %s\n", sys_errlist[errno]);
782     return false;
783   }
784
785   return true;
786 }
787
788 #ifdef BPATCH_LIBRARY
789 /*
790    terminate execution of a process
791  */
792 bool process::terminateProc_()
793 {
794     int sig = SIGKILL;
795     if (ioctl(proc_fd, PIOCKILL, &sig) == -1)
796         return false;
797     else
798         return true;
799 }
800 #endif
801
802 /*
803    pause a process that is running
804 */
805 bool process::pause_() {
806   ptraceOps++; ptraceOtherOps++;
807   int ioctl_ret;
808
809   // /proc PIOCSTOP: direct all LWPs to stop, _and_ wait for them to stop.
810   ioctl_ret = ioctl(proc_fd, PIOCSTOP, 0);
811   if (ioctl_ret == -1) {
812       sprintf(errorLine, "warn : process::pause_ use ioctl to send PICOSTOP returns error : errno = %i\n", errno);
813       perror("warn : process::pause_ ioctl PICOSTOP: ");
814       logLine(errorLine);
815   }
816   return (ioctl_ret != -1);
817 }
818
819 /*
820    close the file descriptor for the file associated with a process
821 */
822 bool process::detach_() {
823   close(proc_fd);
824   return true;
825 }
826
827 #ifdef BPATCH_LIBRARY
828 /*
829    detach from thr process, continuing its execution if the parameter "cont"
830    is true.
831  */
832 bool process::API_detach_(const bool cont)
833 {
834   // Reset the kill-on-close flag, and the run-on-last-close flag if necessary
835   long flags = PR_KLC;
836   if (!cont) flags |= PR_RLC;
837   if (ioctl (proc_fd, PIOCRESET, &flags) < 0) {
838     fprintf(stderr, "detach: PIOCRESET failed: %s\n", sys_errlist[errno]);
839     close(proc_fd);
840     return false;
841   }
842   // Set the run-on-last-close-flag if necessary
843   if (cont) {
844     flags = PR_RLC;
845     if (ioctl (proc_fd, PIOCSET, &flags) < 0) {
846       fprintf(stderr, "detach: PIOCSET failed: %s\n", sys_errlist[errno]);
847       close(proc_fd);
848       return false;
849     }
850   }
851
852   sigset_t sigs;
853   premptyset(&sigs);
854   if (ioctl(proc_fd, PIOCSTRACE, &sigs) < 0) {
855     fprintf(stderr, "detach: PIOCSTRACE failed: %s\n", sys_errlist[errno]);
856     close(proc_fd);
857     return false;
858   }
859   if (ioctl(proc_fd, PIOCSHOLD, &sigs) < 0) {
860     fprintf(stderr, "detach: PIOCSHOLD failed: %s\n", sys_errlist[errno]);
861     close(proc_fd);
862     return false;
863   }
864
865   fltset_t faults;
866   premptyset(&faults);
867   if (ioctl(proc_fd, PIOCSFAULT, &faults) < 0) {
868     fprintf(stderr, "detach: PIOCSFAULT failed: %s\n", sys_errlist[errno]);
869     close(proc_fd);
870     return false;
871   }
872   
873   sysset_t syscalls;
874   premptyset(&syscalls);
875   if (ioctl(proc_fd, PIOCSENTRY, &syscalls) < 0) {
876     fprintf(stderr, "detach: PIOCSENTRY failed: %s\n", sys_errlist[errno]);
877     close(proc_fd);
878     return false;
879   }
880   if (ioctl(proc_fd, PIOCSEXIT, &syscalls) < 0) {
881     fprintf(stderr, "detach: PIOCSEXIT failed: %s\n", sys_errlist[errno]);
882     close(proc_fd);
883     return false;
884   }
885
886   close(proc_fd);
887   return true;
888 }
889 #endif
890
891 bool process::dumpCore_(const string) {
892   return false;
893 }
894
895 bool process::writeTextWord_(caddr_t inTraced, int data) {
896 //  cerr << "writeTextWord @ " << (void *)inTraced << endl; cerr.flush();
897   return writeDataSpace_(inTraced, sizeof(int), (caddr_t) &data);
898 }
899
900 bool process::writeTextSpace_(void *inTraced, int amount, const void *inSelf) {
901 //  cerr << "writeTextSpace pid=" << getPid() << ", @ " << (void *)inTraced << " len=" << amount << endl; cerr.flush();
902   return writeDataSpace_(inTraced, amount, inSelf);
903 }
904
905 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
906 bool process::readTextSpace_(void *inTraced, int amount, const void *inSelf) {
907   return readDataSpace_(inTraced, amount, inSelf);
908 }
909 #endif
910
911 bool process::writeDataSpace_(void *inTraced, int amount, const void *inSelf) {
912   ptraceOps++; ptraceBytes += amount;
913
914 //  cerr << "process::writeDataSpace_ pid " << getPid() << " writing " << amount << " bytes at loc " << inTraced << endl;
915
916   if (lseek(proc_fd, (off_t)inTraced, SEEK_SET) != (off_t)inTraced)
917     return false;
918   return (write(proc_fd, inSelf, amount) == amount);
919 }
920
921 bool process::readDataSpace_(const void *inTraced, int amount, void *inSelf) {
922   ptraceOps++; ptraceBytes += amount;
923   if((lseek(proc_fd, (off_t)inTraced, SEEK_SET)) != (off_t)inTraced) {
924     printf("error in lseek addr = 0x%x amount = %d\n",(u_int)inTraced,amount);
925     return false;
926   }
927   return (read(proc_fd, inSelf, amount) == amount);
928 }
929
930 bool process::loopUntilStopped() {
931   assert(0);
932 }
933
934 #ifdef notdef
935 // TODO -- only call getrusage once per round
936 static struct rusage *get_usage_data() {
937   return NULL;
938 }
939 #endif
940
941 float OS::compute_rusage_cpu() {
942   return 0;
943 }
944
945 float OS::compute_rusage_sys() {
946   return 0;
947 }
948
949 float OS::compute_rusage_min() {
950   return 0;
951 }
952 float OS::compute_rusage_maj() {
953   return 0;
954 }
955
956 float OS::compute_rusage_swap() {
957   return 0;
958 }
959 float OS::compute_rusage_io_in() {
960   return 0;
961 }
962 float OS::compute_rusage_io_out() {
963   return 0;
964 }
965 float OS::compute_rusage_msg_send() {
966   return 0;
967 }
968 float OS::compute_rusage_msg_recv() {
969   return 0;
970 }
971 float OS::compute_rusage_sigs() {
972   return 0;
973 }
974 float OS::compute_rusage_vol_cs() {
975   return 0;
976 }
977 float OS::compute_rusage_inv_cs() {
978   return 0;
979 }
980
981 int getNumberOfCPUs()
982 {
983   // _SC_NPROCESSORS_CONF is the number of processors configured in the
984   // system and _SC_NPROCESSORS_ONLN is the number of those processors that
985   // are online.
986   int numberOfCPUs;
987   numberOfCPUs = (int) sysconf(_SC_NPROCESSORS_ONLN);
988   if (numberOfCPUs) 
989     return(numberOfCPUs);
990   else 
991     return(1);
992 }  
993
994
995 bool process::getActiveFrame(int *fp, int *pc)
996 {
997   prgregset_t regs;
998   bool ok=false;
999
1000   if (ioctl (proc_fd, PIOCGREG, &regs) != -1) {
1001       *fp=regs[FP_REG];
1002       *pc=regs[PC_REG];
1003       ok=true;
1004   }
1005   return(ok);
1006 }
1007
1008 #ifdef sparc_sun_solaris2_4
1009
1010 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool uppermost)
1011 {
1012   bool readOK=true;
1013   struct {
1014     int fp;
1015     int rtn;
1016   } addrs;
1017
1018   prgregset_t regs;
1019   function_base *func;
1020   int pc = *rtn;
1021
1022   if (uppermost) {
1023       func = this->findFunctionIn(pc);
1024       if (func) {
1025          if (func->hasNoStackFrame()) { // formerly "isLeafFunc()"
1026               if (ioctl (proc_fd, PIOCGREG, &regs) != -1) {
1027                   *rtn = regs[R_O7] + 8;
1028                   return readOK;
1029               }    
1030          }
1031       }
1032   }
1033
1034   //
1035   // For the sparc, register %i7 is the return address - 8 and the fp is
1036   // register %i6. These registers can be located in currentFP+14*5 and
1037   // currentFP+14*4 respectively, but to avoid two calls to readDataSpace,
1038   // we bring both together (i.e. 8 bytes of memory starting at currentFP+14*4
1039   // or currentFP+56).
1040   // These values are copied to the stack when the application is paused,
1041   // so we are assuming that the application is paused at this point
1042
1043   if (readDataSpace((caddr_t) (currentFP + 56),
1044                     sizeof(int)*2, (caddr_t) &addrs, true)) {
1045     // this is the previous frame pointer
1046     *fp = addrs.fp;
1047     // return address
1048     *rtn = addrs.rtn + 8;
1049
1050     // if pc==0, then we are in the outermost frame and we should stop. We
1051     // do this by making fp=0.
1052
1053     if ( (addrs.rtn == 0) || !isValidAddress(this,(Address) addrs.rtn) ) {
1054       readOK=false;
1055     }
1056   }
1057   else {
1058     readOK=false;
1059   }
1060
1061
1062   return(readOK);
1063 }
1064
1065 #endif
1066
1067 #ifdef SHM_SAMPLING
1068 time64 process::getInferiorProcessCPUtime() {
1069    // returns user+sys time from the u or proc area of the inferior process, which in
1070    // turn is presumably obtained by mmapping it (sunos) or by using a /proc ioctl
1071    // to obtain it (solaris).  It must not stop the inferior process in order
1072    // to obtain the result, nor can it assue that the inferior has been stopped.
1073    // The result MUST be "in sync" with rtinst's DYNINSTgetCPUtime().
1074
1075    // We use the PIOCUSAGE /proc ioctl
1076
1077    // Other /proc ioctls that should work too: PIOCPSINFO
1078    // and the lower-level PIOCGETPR and PIOCGETU which return copies of the proc
1079    // and u areas, respectively.
1080    // PIOCSTATUS does _not_ work because its results are not in sync
1081    // with DYNINSTgetCPUtime
1082
1083    time64 result;
1084    prpsinfo_t theUsage;
1085
1086    if (ioctl(proc_fd, PIOCPSINFO, &theUsage) == -1) {
1087       perror("could not read CPU time of inferior PIOCPSINFO");
1088       return 0;
1089    }
1090    result = PDYN_mulMillion(theUsage.pr_time.tv_sec); // sec to usec
1091    result += PDYN_div1000(theUsage.pr_time.tv_nsec);  // nsec to usec
1092
1093    if (result<previous) {
1094      // time shouldn't go backwards, but we have seen this happening
1095      // before, so we better check it just in case - naim 5/30/97
1096      logLine("********* time going backwards in paradynd **********\n");
1097      result=previous;
1098    } else {
1099      previous=result;
1100    }
1101
1102    return result;
1103 }
1104 #endif
1105
1106 void *process::getRegisters() {
1107    // Astonishingly, this routine can be shared between solaris/sparc and
1108    // solaris/x86.  All hail /proc!!!
1109
1110    // assumes the process is stopped (/proc requires it)
1111    assert(status_ == stopped);
1112
1113    prgregset_t theIntRegs;
1114    if (ioctl(proc_fd, PIOCGREG, &theIntRegs) == -1) {
1115       perror("process::getRegisters PIOCGREG");
1116       if (errno == EBUSY) {
1117          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1118          assert(false);
1119       }
1120
1121       return NULL;
1122    }
1123
1124    prfpregset_t theFpRegs;
1125    if (ioctl(proc_fd, PIOCGFPREG, &theFpRegs) == -1) {
1126       perror("process::getRegisters PIOCGFPREG");
1127       if (errno == EBUSY)
1128          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1129       else if (errno == EINVAL)
1130          // what to do in this case?  Probably shouldn't even do a print, right?
1131          // And it certainly shouldn't be an error, right?
1132          // But I wonder if any sparcs out there really don't have floating point.
1133          cerr << "It appears that this machine doesn't have floating-point instructions" << endl;
1134
1135       return NULL;
1136    }
1137
1138    const int numbytesPart1 = sizeof(prgregset_t);
1139    const int numbytesPart2 = sizeof(prfpregset_t);
1140    assert(numbytesPart1 % 4 == 0);
1141    assert(numbytesPart2 % 4 == 0);
1142
1143    void *buffer = new char[numbytesPart1 + numbytesPart2];
1144    assert(buffer);
1145
1146    memcpy(buffer, &theIntRegs, sizeof(theIntRegs));
1147    memcpy((char *)buffer + sizeof(theIntRegs), &theFpRegs, sizeof(theFpRegs));
1148
1149    return buffer;
1150 }
1151
1152 bool process::executingSystemCall() {
1153    prstatus theStatus;
1154    if (ioctl(proc_fd, PIOCSTATUS, &theStatus) != -1) {
1155      if (theStatus.pr_syscall > 0) {
1156        inferiorrpc_cerr << "pr_syscall=" << theStatus.pr_syscall << endl;
1157        return(true);
1158      }
1159    } else assert(0);
1160    return(false);
1161 }
1162
1163 bool process::changePC(unsigned addr, const void *savedRegs) {
1164    assert(status_ == stopped);
1165
1166    prgregset_t theIntRegs = *(const prgregset_t *)savedRegs; // makes a copy, on purpose
1167
1168    theIntRegs[R_PC] = addr; // PC (sparc), EIP (x86)
1169 #ifdef R_nPC  // true for sparc, not for x86
1170    theIntRegs[R_nPC] = addr + 4;
1171 #endif
1172
1173    if (ioctl(proc_fd, PIOCSREG, &theIntRegs) == -1) {
1174       perror("process::changePC PIOCSREG failed");
1175       if (errno == EBUSY)
1176          cerr << "It appears that the process wasn't stopped in the eyes of /proc" << endl;
1177       return false;
1178    }
1179
1180    return true;
1181 }
1182
1183 bool process::changePC(unsigned addr) {
1184    assert(status_ == stopped); // /proc will require this
1185
1186    prgregset_t theIntRegs;
1187    if (-1 == ioctl(proc_fd, PIOCGREG, &theIntRegs)) {
1188       perror("process::changePC PIOCGREG");
1189       if (errno == EBUSY) {
1190          cerr << "It appears that the process wasn't stopped in the eyes of /proc" << endl;
1191          assert(false);
1192       }
1193       return false;
1194    }
1195
1196    theIntRegs[R_PC] = addr;
1197 #ifdef R_nPC
1198    theIntRegs[R_nPC] = addr + 4;
1199 #endif
1200
1201    if (-1 == ioctl(proc_fd, PIOCSREG, &theIntRegs)) {
1202       perror("process::changePC PIOCSREG");
1203       if (errno == EBUSY) {
1204          cerr << "It appears that the process wasn't stopped in the eyes of /proc" << endl;
1205          assert(false);
1206       }
1207       return false;
1208    }
1209
1210    return true;
1211 }
1212
1213 bool process::restoreRegisters(void *buffer) {
1214    // The fact that this routine can be shared between solaris/sparc and
1215    // solaris/x86 is just really, really cool.  /proc rules!
1216
1217    assert(status_ == stopped); // /proc requires it
1218
1219    prgregset_t theIntRegs = *(prgregset_t *)buffer;
1220    prfpregset_t theFpRegs = *(prfpregset_t *)((char *)buffer + sizeof(theIntRegs));
1221
1222    if (ioctl(proc_fd, PIOCSREG, &theIntRegs) == -1) {
1223       perror("process::restoreRegisters PIOCSREG failed");
1224       if (errno == EBUSY) {
1225          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1226          assert(false);
1227       }
1228       return false;
1229    }
1230
1231    if (ioctl(proc_fd, PIOCSFPREG, &theFpRegs) == -1) {
1232       perror("process::restoreRegisters PIOCSFPREG failed");
1233       if (errno == EBUSY) {
1234          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1235          assert(false);
1236       }
1237       return false;
1238    }
1239
1240    return true;
1241 }
1242
1243 #ifdef i386_unknown_solaris2_5
1244
1245 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool )
1246 {
1247   bool readOK=true;
1248   struct {
1249     int fp;
1250     int rtn;
1251   } addrs;
1252
1253   //
1254   // for the x86, the frame-pointer (EBP) points to the previous frame-pointer,
1255   // and the saved return address is in EBP-4.
1256   //
1257
1258   if (readDataSpace((caddr_t) (currentFP),
1259                     sizeof(int)*2, (caddr_t) &addrs, true)) {
1260     // this is the previous frame pointer
1261     *fp = addrs.fp;
1262     // return address
1263     *rtn = addrs.rtn;
1264
1265     // if pc==0, then we are in the outermost frame and we should stop. We
1266     // do this by making fp=0.
1267
1268     if ( (addrs.rtn == 0) || !isValidAddress(this,(Address) addrs.rtn) ) {
1269       readOK=false;
1270     }
1271   }
1272   else {
1273     readOK=false;
1274   }
1275
1276   return(readOK);
1277 }
1278
1279 #endif
1280
1281 #ifdef i386_unknown_solaris2_5
1282 // ******** TODO **********
1283 bool process::needToAddALeafFrame(Frame , Address &) {
1284   return false;
1285 }
1286
1287 #else
1288
1289 // needToAddALeafFrame: returns true if the between the current frame 
1290 // and the next frame there is a leaf function (this occurs when the 
1291 // current frame is the signal handler and the function that was executing
1292 // when the sighandler was called is a leaf function)
1293 bool process::needToAddALeafFrame(Frame current_frame, Address &leaf_pc){
1294
1295    // check to see if the current frame is the signal handler 
1296    Address frame_pc = current_frame.getPC();
1297    Address sig_addr = 0;
1298    const image *sig_image = (signal_handler->file())->exec();
1299    if(getBaseAddress(sig_image, sig_addr)){
1300        sig_addr += signal_handler->getAddress(0);
1301    } else {
1302        sig_addr = signal_handler->getAddress(0);
1303    }
1304    u_int sig_size = signal_handler->size();
1305    if(signal_handler&&(frame_pc >= sig_addr)&&(frame_pc < (sig_addr+sig_size))){
1306        // get the value of the saved PC: this value is stored in the address
1307        // specified by the value in register i2 + 44. Register i2 must contain
1308        // the address of some struct that contains, among other things, the 
1309        // saved PC value.  
1310        u_int reg_i2;
1311        int fp = current_frame.getFramePtr();
1312        if (readDataSpace((caddr_t)(fp+40),sizeof(u_int),(caddr_t)&reg_i2,true)){
1313           if (readDataSpace((caddr_t) (reg_i2+44), sizeof(int),
1314                             (caddr_t) &leaf_pc,true)){
1315               // if the function is a leaf function return true
1316               function_base *func = findFunctionIn(leaf_pc);
1317               if(func && func->hasNoStackFrame()) { // formerly "isLeafFunc()"
1318                   return(true);
1319               }
1320           }
1321       }
1322    }
1323    return false;
1324 }
1325 #endif
1326
1327 string process::tryToFindExecutable(const string &iprogpath, int pid) {
1328    // returns empty string on failure.
1329    // Otherwise, returns a full-path-name for the file.  Tries every
1330    // trick to determine the full-path-name, even though "progpath" may be
1331    // unspecified (empty string).
1332    
1333    // Remember, we can always return the empty string...no need to
1334    // go nuts writing the world's most complex algorithm.
1335
1336    attach_cerr << "welcome to tryToFindExecutable; progpath=" << iprogpath << ", pid=" << pid << endl;
1337
1338    const string progpath = expand_tilde_pathname(iprogpath);
1339
1340    // Trivial case: if "progpath" is specified and the file exists then nothing needed
1341    if (exists_executable(progpath)) {
1342       attach_cerr << "tryToFindExecutable succeeded immediately, returning "
1343                   << progpath << endl;
1344       return progpath;
1345    }
1346
1347    attach_cerr << "tryToFindExecutable failed on filename " << progpath << endl;
1348
1349    char buffer[128];
1350    sprintf(buffer, "/proc/%05d", pid);
1351    int procfd = open(buffer, O_RDONLY, 0);
1352    if (procfd == -1) {
1353       attach_cerr << "tryToFindExecutable failed since open of /proc failed" << endl;
1354       return "";
1355    }
1356    attach_cerr << "tryToFindExecutable: opened /proc okay" << endl;
1357
1358    string argv0, path, cwd;
1359    if (get_ps_stuff(procfd, argv0, path, cwd)) {
1360        // the following routine is implemented in the util lib.
1361        string result;
1362        if (executableFromArgv0AndPathAndCwd(result, argv0, path, cwd)) {
1363           (void)close(procfd);
1364           return result;
1365        }
1366    }
1367
1368    attach_cerr << "tryToFindExecutable: giving up" << endl;
1369
1370    (void)close(procfd);
1371    return "";
1372 }
1373
1374 bool process::set_breakpoint_for_syscall_completion() {
1375    /* Can assume: (1) process is paused and (2) in a system call.
1376       We want to set a TRAP for the syscall exit, and do the
1377       inferiorRPC at that time.  We'll use /proc PIOCSEXIT.
1378       Returns true iff breakpoint was successfully set. */
1379
1380    sysset_t save_exitset;
1381    if (-1 == ioctl(proc_fd, PIOCGEXIT, &save_exitset))
1382       return false;
1383
1384    sysset_t new_exit_set;
1385    prfillset(&new_exit_set);
1386    if (-1 == ioctl(proc_fd, PIOCSEXIT, &new_exit_set))
1387       return false;
1388
1389    assert(save_exitset_ptr == NULL);
1390    save_exitset_ptr = new sysset_t;
1391    memcpy(save_exitset_ptr, &save_exitset, sizeof(save_exitset));
1392
1393    return true;
1394 }
1395
1396 unsigned process::read_inferiorRPC_result_register(reg) {
1397    prgregset_t theIntRegs;
1398    if (-1 == ioctl(proc_fd, PIOCGREG, &theIntRegs)) {
1399       perror("process::read_inferiorRPC_result_register PIOCGREG");
1400       if (errno == EBUSY) {
1401          cerr << "It appears that the process was not stopped in the eyes of /proc" << endl;
1402          assert(false);
1403       }
1404       return 0; // assert(false)?
1405    }
1406
1407    // on x86, the result is always stashed in %EAX; on sparc, it's always %o0.  In
1408    // neither case do we need the argument of this fn.
1409 #ifdef i386_unknown_solaris2_5
1410    return theIntRegs[EAX];
1411 #else
1412    return theIntRegs[R_O0];
1413 #endif
1414 }
1415
1416 void print_read_error_info(const relocationEntry entry, 
1417       pd_Function *&target_pdf, Address base_addr) {
1418
1419     sprintf(errorLine, "  entry      : target_addr 0x%x\n", \
1420             entry.target_addr());
1421     logLine(errorLine);
1422     sprintf(errorLine, "               rel_addr 0x%x\n", entry.rel_addr());
1423     logLine(errorLine);
1424     sprintf(errorLine, "               name %s\n", (entry.name()).string_of());
1425     logLine(errorLine);
1426
1427     sprintf(errorLine, "  target_pdf : symTabName %s\n", \
1428             (target_pdf->symTabName()).string_of());
1429     logLine(errorLine);    
1430     sprintf(errorLine , "              prettyName %s\n", \
1431             (target_pdf->symTabName()).string_of());
1432     logLine(errorLine);
1433     sprintf(errorLine , "              size %i\n", \
1434             target_pdf->size());
1435     logLine(errorLine);
1436     sprintf(errorLine , "              addr 0x%x\n", \
1437             target_pdf->addr());
1438     logLine(errorLine);
1439
1440     sprintf(errorLine, "  base_addr  0x%x\n", base_addr);
1441     logLine(errorLine);
1442 }
1443
1444 // hasBeenBound: returns true if the runtime linker has bound the
1445 // function symbol corresponding to the relocation entry in at the address
1446 // specified by entry and base_addr.  If it has been bound, then the callee 
1447 // function is returned in "target_pdf", else it returns false.
1448 bool process::hasBeenBound(const relocationEntry entry, 
1449                            pd_Function *&target_pdf, Address base_addr) {
1450
1451 // TODO: the x86 and sparc versions should really go in seperate files 
1452 #if defined(i386_unknown_solaris2_5)
1453
1454     if (status() == exited) return false;
1455
1456     // if the relocationEntry has not been bound yet, then the value
1457     // at rel_addr is the address of the instruction immediately following
1458     // the first instruction in the PLT entry (which is at the target_addr) 
1459     // The PLT entries are never modified, instead they use an indirrect 
1460     // jump to an address stored in the _GLOBAL_OFFSET_TABLE_.  When the 
1461     // function symbol is bound by the runtime linker, it changes the address
1462     // in the _GLOBAL_OFFSET_TABLE_ corresponding to the PLT entry
1463
1464     Address got_entry = entry.rel_addr() + base_addr;
1465     Address bound_addr = 0;
1466     if(!readDataSpace((const void*)got_entry, sizeof(Address), 
1467                         &bound_addr, true)){
1468         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%x, pid=%d\n (readDataSpace returns 0)",got_entry,pid);
1469         logLine(errorLine);
1470         print_read_error_info(entry, target_pdf, base_addr);
1471         return false;
1472     }
1473
1474     if( !( bound_addr == (entry.target_addr()+6+base_addr)) ) {
1475         // the callee function has been bound by the runtime linker
1476         // find the function and return it
1477         target_pdf = findpdFunctionIn(bound_addr);
1478         if(!target_pdf){
1479             return false;
1480         }
1481         return true;    
1482     }
1483     return false;
1484
1485 #else
1486     // if the relocationEntry has not been bound yet, then the second instr 
1487     // in this PLT entry branches to the fist PLT entry.  If it has been   
1488     // bound, then second two instructions of the PLT entry have been changed 
1489     // by the runtime linker to jump to the address of the function.  
1490     // Here is an example:   
1491     //     before binding                       after binding
1492     //     --------------                       -------------
1493     //     sethi  %hi(0x15000), %g1             sethi  %hi(0x15000), %g1
1494     //     b,a  <_PROCEDURE_LINKAGE_TABLE_>     sethi  %hi(0xef5eb000), %g1
1495     //     nop                                  jmp  %g1 + 0xbc ! 0xef5eb0bc
1496
1497     instruction next_insn;
1498     Address next_insn_addr = entry.target_addr() + base_addr + 4; 
1499     if( !(readDataSpace((caddr_t)next_insn_addr, sizeof(next_insn), 
1500                        (char *)&next_insn, true)) ) {
1501         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%x (readDataSpace next_isin_addr returns 0)\n",
1502                 next_insn_addr);
1503         logLine(errorLine);
1504         print_read_error_info(entry, target_pdf, base_addr);
1505     }
1506     // if this is a b,a instruction, then the function has not been bound
1507     if((next_insn.branch.op == FMT2op)  && (next_insn.branch.op2 == BICCop2) 
1508        && (next_insn.branch.anneal == 1) && (next_insn.branch.cond == BAcond)) {
1509         return false;
1510     } 
1511
1512     // if this is a sethi instruction, then it has been bound...get target_addr
1513     instruction third_insn;
1514     Address third_addr = entry.target_addr() + base_addr + 8; 
1515     if( !(readDataSpace((caddr_t)third_addr, sizeof(third_insn), 
1516                        (char *)&third_insn, true)) ) {
1517         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%x (readDataSpace third_addr returns 0)\n",
1518                 third_addr);
1519         logLine(errorLine);
1520         print_read_error_info(entry,target_pdf, base_addr);
1521     }
1522
1523     // get address of bound function, and return the corr. pd_Function
1524     if((next_insn.sethi.op == FMT2op) && (next_insn.sethi.op2 == SETHIop2)
1525         && (third_insn.rest.op == RESTop) && (third_insn.rest.i == 1)
1526         && (third_insn.rest.op3 == JMPLop3)) {
1527         
1528         Address new_target = (next_insn.sethi.imm22 << 10) & 0xfffffc00; 
1529         new_target |= third_insn.resti.simm13;
1530
1531         target_pdf = findpdFunctionIn(new_target);
1532         if(!target_pdf){
1533             return false;
1534         }
1535         return true;
1536     }
1537     // this is a messed up entry
1538     return false;
1539 #endif
1540
1541 }
1542
1543
1544
1545 // findCallee: finds the function called by the instruction corresponding
1546 // to the instPoint "instr". If the function call has been bound to an
1547 // address, then the callee function is returned in "target" and the 
1548 // instPoint "callee" data member is set to pt to callee's function_base.  
1549 // If the function has not yet been bound, then "target" is set to the 
1550 // function_base associated with the name of the target function (this is 
1551 // obtained by the PLT and relocation entries in the image), and the instPoint
1552 // callee is not set.  If the callee function cannot be found, (ex. function
1553 // pointers, or other indirect calls), it returns false.
1554 // Returns false on error (ex. process doesn't contain this instPoint).
1555 //
1556 // The assumption here is that for all processes sharing the image containing
1557 // this instPoint they are going to bind the call target to the same function. 
1558 // For shared objects this is always true, however this may not be true for
1559 // dynamic executables.  Two a.outs can be identical except for how they are
1560 // linked, so a call to fuction foo in one version of the a.out may be bound
1561 // to function foo in libfoo.so.1, and in the other version it may be bound to 
1562 // function foo in libfoo.so.2.  We are currently not handling this case, since
1563 // it is unlikely to happen in practice.
1564 bool process::findCallee(instPoint &instr, function_base *&target){
1565     
1566     if((target = (function_base *)instr.iPgetCallee())) {
1567         return true; // callee already set
1568     }
1569
1570     // find the corresponding image in this process  
1571     const image *owner = instr.iPgetOwner();
1572     bool found_image = false;
1573     Address base_addr = 0;
1574     if(symbols == owner) {  found_image = true; } 
1575     else if(shared_objects){
1576         for(u_int i=0; i < shared_objects->size(); i++){
1577             if(owner == ((*shared_objects)[i])->getImage()) {
1578                 found_image = true;
1579                 base_addr = ((*shared_objects)[i])->getBaseAddress();
1580                 break;
1581             }
1582         }
1583     } 
1584     if(!found_image) {
1585         target = 0;
1586         return false; // image not found...this is bad
1587     }
1588
1589     // get the target address of this function
1590     Address target_addr = 0;
1591 //    Address insn_addr = instr.iPgetAddress(); 
1592     target_addr = instr.getTargetAddress();
1593
1594     if(!target_addr) {  
1595         // this is either not a call instruction or an indirect call instr
1596         // that we can't get the target address
1597         target = 0;
1598         return false;
1599     }
1600
1601 #if defined(sparc_sun_solaris2_4)
1602     // If this instPoint is from a function that was relocated to the heap
1603     // then need to get the target address relative to this image   
1604     if(target_addr && instr.relocated_) {
1605         assert(target_addr > base_addr);
1606         target_addr -= base_addr;
1607     }
1608 #endif
1609
1610     // see if there is a function in this image at this target address
1611     // if so return it
1612     pd_Function *pdf = 0;
1613     if( (pdf = owner->findFunctionInInstAndUnInst(target_addr,this)) ) {
1614         target = pdf;
1615         instr.set_callee(pdf);
1616         return true; // target found...target is in this image
1617     }
1618
1619     // else, get the relocation information for this image
1620     const Object &obj = owner->getObject();
1621     const vector<relocationEntry> *fbt;
1622     if(!obj.get_func_binding_table_ptr(fbt)) {
1623         target = 0;
1624         return false; // target cannot be found...it is an indirect call.
1625     }
1626
1627     // find the target address in the list of relocationEntries
1628     for(u_int i=0; i < fbt->size(); i++) {
1629         if((*fbt)[i].target_addr() == target_addr) {
1630             // check to see if this function has been bound yet...if the
1631             // PLT entry for this function has been modified by the runtime
1632             // linker
1633             pd_Function *target_pdf = 0;
1634             if(hasBeenBound((*fbt)[i], target_pdf, base_addr)) {
1635                 target = target_pdf;
1636                 instr.set_callee(target_pdf);
1637                 return true;  // target has been bound
1638             } 
1639             else {
1640                 // just try to find a function with the same name as entry 
1641                 target = findOneFunctionFromAll((*fbt)[i].name());
1642                 if(target){
1643                     return true;
1644                 }
1645                 else {  
1646                     // KLUDGE: this is because we are not keeping more than
1647                     // one name for the same function if there is more
1648                     // than one.  This occurs when there are weak symbols
1649                     // that alias global symbols (ex. libm.so.1: "sin" 
1650                     // and "__sin").  In most cases the alias is the same as 
1651                     // the global symbol minus one or two leading underscores,
1652                     // so here we add one or two leading underscores to search
1653                     // for the name to handle the case where this string 
1654                     // is the name of the weak symbol...this will not fix 
1655                     // every case, since if the weak symbol and global symbol
1656                     // differ by more than leading underscores we won't find
1657                     // it...when we parse the image we should keep multiple
1658                     // names for pd_Functions
1659
1660                     string s = string("_");
1661                     s += (*fbt)[i].name();
1662                     target = findOneFunctionFromAll(s);
1663                     if(target){
1664                         return true;
1665                     }
1666                     s = string("__");
1667                     s += (*fbt)[i].name();
1668                     target = findOneFunctionFromAll(s);
1669                     if(target){
1670                         return true;
1671                     }
1672                 }
1673             }
1674             target = 0;
1675             return false;
1676         }
1677     }
1678     target = 0;
1679     return false;  
1680 }