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