2 * Copyright (c) 1996 Barton P. Miller
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.
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.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
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.
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.
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>
50 #include <sys/termios.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"
57 #if defined (sparc_sun_solaris2_4)
58 #include "dyninstAPI/src/inst-sparc.h"
60 #include "dyninstAPI/src/inst-x86.h"
63 #include "instPoint.h"
65 #include <sys/procfs.h>
72 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
75 extern int ioctl(int, int, ...);
76 extern long sysconf(int);
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;
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,
92 PC_REG: program counter
93 FP_REG: frame pointer (%i7 on sparc, %ebp on x86)
95 #ifdef sparc_sun_solaris2_4
96 #define RETVAL_REG (R_O0)
100 #ifdef i386_unknown_solaris2_5
101 #define RETVAL_REG (EAX)
107 extern bool isValidAddress(process *proc, Address where);
108 extern void generateBreakPoint(instruction &insn);
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
117 void OS::osTraceMe(void) {
121 sprintf(procName,"/proc/%05d", (int)getpid());
122 int fd = P_open(procName, O_RDWR, 0);
124 fprintf(stderr, "osTraceMe: open failed: %s\n", sys_errlist[errno]);
126 P__exit(-1); // must use _exit here.
129 /* set a breakpoint at the exit of exec/execve */
130 premptyset(&exitSet);
131 praddset(&exitSet, SYS_exec);
132 praddset(&exitSet, SYS_execve);
134 if (ioctl(fd, PIOCSEXIT, &exitSet) < 0) {
135 fprintf(stderr, "osTraceMe: PIOCSEXIT failed: %s\n", sys_errlist[errno]);
137 P__exit(-1); // must use _exit here.
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);
154 bool process::continueWithForwardSignal(int) {
155 if (-1 == ioctl(proc_fd, PIOCRUN, NULL)) {
156 perror("could not forward signal in PIOCRUN");
163 #ifdef BPATCH_LIBRARY
164 bool process::dumpImage(string /* imageFileName */) {return false;}
166 bool process::dumpImage() {return false;}
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.
176 static inline bool execResult(prstatus_t stat) {
177 return (stat.pr_reg[RETVAL_REG] == 0);
181 wait for inferior processes to terminate or stop.
183 #ifdef BPATCH_LIBRARY
184 int process::waitProcs(int *status, bool block) {
186 int process::waitProcs(int *status) {
188 extern vector<process*> processVec;
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
194 #ifdef BPATCH_LIBRARY
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.
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;
210 fds[u].events = POLLPRI;
214 #ifdef BPATCH_LIBRARY
216 if (block) timeout = INFTIM;
218 selected_fds = poll(fds, processVec.size(), timeout);
220 selected_fds = poll(fds, processVec.size(), 0);
222 if (selected_fds < 0) {
223 fprintf(stderr, "waitProcs: poll failed: %s\n", sys_errlist[errno]);
231 if (selected_fds > 0) {
232 while (fds[curr].revents == 0)
235 // fds[curr] has an event of interest
239 #ifdef BPATCH_LIBRARY
240 if (fds[curr].revents & POLLHUP) {
241 ret = waitpid(processVec[curr]->getPid(), status, 0);
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) {
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();
262 if (processVec[curr]->trapDueToDyninstLib()) {
263 // we need to load libdyninstRT.so.1 - naim
264 processVec[curr]->handleIfDueToDyninstLib();
267 if (!processVec[curr]->continueProc()) assert(0);
272 // exit of a system call.
273 process *p = processVec[curr];
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))
281 delete [] p->save_exitset_ptr;
282 p->save_exitset_ptr = NULL;
284 // fall through on purpose (so status, ret get set)
286 else if (!execResult(stat)) {
287 // a failed exec. continue the process
288 processVec[curr]->continueProc_();
292 *status = SIGTRAP << 8 | 0177;
293 ret = processVec[curr]->getPid();
312 #ifdef BPATCH_LIBRARY
316 return waitpid(0, status, WNOHANG);
321 static char *extract_string_ptr(int procfd, char **ptr) {
322 // we want to return *ptr.
324 if (-1 == lseek(procfd, (long)ptr, SEEK_SET))
328 if (-1 == read(procfd, &result, sizeof(result)))
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.
338 if (-1 == lseek(procfd, (long)inferiorptr, SEEK_SET))
344 if (-1 == read(procfd, &buffer, 80))
349 // was there a '\0' anywhere in chars 0 thru 79? If so then
351 for (unsigned lcv=0; lcv < 80; lcv++)
352 if (buffer[lcv] == '\0') {
353 //attach_cerr << "extract_string returning " << result << endl;
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.
364 if (-1 == ioctl(proc_fd, PIOCPSINFO, &the_psinfo))
367 if (the_psinfo.pr_zomb)
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);
377 // Get the PWD and PATH environment variables from the application.
378 char **envptr = the_psinfo.pr_envp;
380 // dereference envptr; check for NULL
381 char *env = extract_string_ptr(proc_fd, envptr);
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;
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;
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.
406 extern string pd_flavor ;
407 bool process::attach() {
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)
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);
419 fprintf(stderr, "attach: open failed: %s\n", sys_errlist[errno]);
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.
430 praddset(&sigs, SIGSTOP);
432 #ifndef i386_unknown_solaris2_5
433 praddset(&sigs, SIGTRAP);
436 #ifdef i386_unknown_solaris2_5
437 praddset(&sigs, SIGILL);
440 if (ioctl(fd, PIOCSTRACE, &sigs) < 0) {
441 fprintf(stderr, "attach: ioctl failed: %s\n", sys_errlist[errno]);
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.
453 //Tempest, do not need to inherit-on-fork
455 if(process::pdFlavor == string("cow"))
456 flags = PR_KLC | PR_BPTADJ;
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]);
467 if (!get_ps_stuff(proc_fd, this->argv0, this->pathenv, this->cwdenv))
473 #if defined(USES_LIBDYNINSTRT_SO)
474 bool process::trapAtEntryPointOfMain()
477 if (ioctl (proc_fd, PIOCGREG, ®s) != -1) {
478 // is the trap instr at main_brk_addr?
479 if(regs[R_PC] == (int)main_brk_addr){
486 bool process::trapDueToDyninstLib()
489 if (ioctl (proc_fd, PIOCGREG, ®s) != -1) {
490 // is the trap instr at dyninstlib_brk_addr?
491 if(regs[R_PC] == (int)dyninstlib_brk_addr){
498 void process::handleIfDueToDyninstLib()
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();
505 Address codeBase = (this->findOneFunction("_start"))->addr();
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
513 void process::handleTrapAtEntryPointOfMain()
515 function_base *f_main = findOneFunction("main");
517 unsigned addr = f_main->addr();
518 // restore original instruction
519 writeDataSpace((void *)addr, sizeof(instruction), (char *)savedCodeBuffer);
522 void process::insertTrapAtEntryPointOfMain()
524 function_base *f_main = findOneFunction("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;
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]
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();
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.
554 // savedCodeBuffer[BYTES_TO_SAVE] is declared in process.h
555 readDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer, true);
557 unsigned char scratchCodeBuffer[BYTES_TO_SAVE];
558 vector<AstNode*> dlopenAstArgs(2);
562 #ifdef BPATCH_LIBRARY /* dyninst API doesn't load libsocket.so.1 */
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]);
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();
580 #ifndef BPATCH_LIBRARY /* dyninst API doesn't load libsocket.so.1 */
581 dlopenAst->generateCode(this, dlopenRegSpace, (char *)scratchCodeBuffer,
583 writeDataSpace((void *)codeBase, count, (char *)scratchCodeBuffer);
584 count += sizeof(instruction);
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
590 #ifndef BPATCH_LIBRARY /* since dyninst API didn't create an ast yet */
591 removeAst(dlopenAst); // to avoid memory leaks - naim
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]);
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;
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
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
622 AstNode *check_dlopen_result;
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);
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);
638 check_dlopen_result = new AstNode(ifOp, expression, action);
639 removeAst(expression);
642 check_dlopen_result->generateCode(this, dlopenRegSpace,
643 (char *)scratchCodeBuffer, astcount, true);
644 writeDataSpace((void *)(codeBase+count), astcount,
645 (char *)scratchCodeBuffer);
647 removeAst(check_dlopen_result);
650 instruction insnTrap;
651 generateBreakPoint(insnTrap);
652 //insnTrap.raw = BREAK_POINT_INSN;
653 writeDataSpace((void *)(codeBase + count), sizeof(instruction),
655 dyninstlib_brk_addr = codeBase + count;
656 count += sizeof(instruction);
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"));
663 string msg = string("DYNINSTAPI_RT_LIB is not defined");
664 showErrorCallback(101, msg);
668 if (getenv("PARADYN_LIB") != NULL) {
669 strcpy((char*)libname,(char*)getenv("PARADYN_LIB"));
671 string msg = string("PARADYN_LIB has not been defined for ") +
672 string("process") + string(pid);
673 showErrorCallback(101, msg);
678 unsigned dyninstlib_addr = (unsigned) (codeBase + count);
680 writeDataSpace((void *)(codeBase + count), strlen(libname)+1,
682 count += strlen(libname)+1;
683 // we have now written the name of the library after the trap - naim
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
689 char socketname[256];
690 if (getenv("PARADYN_SOCKET_LIB") != NULL) {
691 strcpy((char*)socketname,(char*)getenv("PARADYN_SOCKET_LIB"));
693 strcpy((char*)socketname,(char *)"/usr/lib/libsocket.so.1");
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
701 assert(count<=BYTES_TO_SAVE);
704 #ifdef BPATCH_LIBRARY /* dyninst API doesn't load libsocket.so.1 */
705 count = 0; // reset count
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,
720 writeDataSpace((void *)codeBase, count, (char *)scratchCodeBuffer);
721 removeAst(dlopenAst);
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);
739 savedRegs = getRegisters();
740 assert((savedRegs!=NULL) && (savedRegs!=(void *)-1));
741 isLoadingDyninstLib = true;
742 if (!changePC(codeBase,savedRegs)) // this uses the info in "savedRegs"
744 logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
751 unsigned process::get_dlopen_addr() const {
753 return(dyn->get_dlopen_addr());
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.
764 if (-1 == ioctl(proc_fd, PIOCSTATUS, &theStatus)) {
765 perror("process::isRunning_()");
769 if (theStatus.pr_flags & PR_STOPPED)
775 bool process::attach_() {assert(false);}
776 bool process::stop_() {assert(false);}
779 continue a process that is stopped
781 bool process::continueProc_() {
782 ptraceOps++; ptraceOtherOps++;
786 //cerr << "welcome to continueProc_()" << endl;
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]);
800 if (ioctl(proc_fd, PIOCWSTOP, 0) == -1) {
801 fprintf(stderr, "continueProc_: PIOCWSTOP failed: %s\n", sys_errlist[errno]);
805 flags.pr_flags = PRCSIG; // clear current signal
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;
813 if (ioctl(proc_fd, PIOCRUN, &flags) == -1) {
814 fprintf(stderr, "continueProc_: PIOCRUN 2 failed: %s\n", sys_errlist[errno]);
821 #ifdef BPATCH_LIBRARY
823 terminate execution of a process
825 bool process::terminateProc_()
828 if (ioctl(proc_fd, PIOCKILL, &sig) == -1)
836 pause a process that is running
838 bool process::pause_() {
839 ptraceOps++; ptraceOtherOps++;
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: ");
849 return (ioctl_ret != -1);
853 close the file descriptor for the file associated with a process
855 bool process::detach_() {
860 #ifdef BPATCH_LIBRARY
862 detach from thr process, continuing its execution if the parameter "cont"
865 bool process::API_detach_(const bool cont)
867 // Reset the kill-on-close flag, and the run-on-last-close flag if necessary
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]);
875 // Set the run-on-last-close-flag if necessary
878 if (ioctl (proc_fd, PIOCSET, &flags) < 0) {
879 fprintf(stderr, "detach: PIOCSET failed: %s\n", sys_errlist[errno]);
887 if (ioctl(proc_fd, PIOCSTRACE, &sigs) < 0) {
888 fprintf(stderr, "detach: PIOCSTRACE failed: %s\n", sys_errlist[errno]);
892 if (ioctl(proc_fd, PIOCSHOLD, &sigs) < 0) {
893 fprintf(stderr, "detach: PIOCSHOLD failed: %s\n", sys_errlist[errno]);
900 if (ioctl(proc_fd, PIOCSFAULT, &faults) < 0) {
901 fprintf(stderr, "detach: PIOCSFAULT failed: %s\n", sys_errlist[errno]);
907 premptyset(&syscalls);
908 if (ioctl(proc_fd, PIOCSENTRY, &syscalls) < 0) {
909 fprintf(stderr, "detach: PIOCSENTRY failed: %s\n", sys_errlist[errno]);
913 if (ioctl(proc_fd, PIOCSEXIT, &syscalls) < 0) {
914 fprintf(stderr, "detach: PIOCSEXIT failed: %s\n", sys_errlist[errno]);
924 bool process::dumpCore_(const string) {
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);
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);
938 #ifdef BPATCH_SET_MUTATIONS_ACTIVE
939 bool process::readTextSpace_(void *inTraced, int amount, const void *inSelf) {
940 return readDataSpace_(inTraced, amount, inSelf);
944 bool process::writeDataSpace_(void *inTraced, int amount, const void *inSelf) {
945 ptraceOps++; ptraceBytes += amount;
947 // cerr << "process::writeDataSpace_ pid " << getPid() << " writing " << amount << " bytes at loc " << inTraced << endl;
949 if (lseek(proc_fd, (off_t)inTraced, SEEK_SET) != (off_t)inTraced)
951 return (write(proc_fd, inSelf, amount) == amount);
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);
960 return (read(proc_fd, inSelf, amount) == amount);
963 bool process::loopUntilStopped() {
968 // TODO -- only call getrusage once per round
969 static struct rusage *get_usage_data() {
974 float OS::compute_rusage_cpu() {
978 float OS::compute_rusage_sys() {
982 float OS::compute_rusage_min() {
985 float OS::compute_rusage_maj() {
989 float OS::compute_rusage_swap() {
992 float OS::compute_rusage_io_in() {
995 float OS::compute_rusage_io_out() {
998 float OS::compute_rusage_msg_send() {
1001 float OS::compute_rusage_msg_recv() {
1004 float OS::compute_rusage_sigs() {
1007 float OS::compute_rusage_vol_cs() {
1010 float OS::compute_rusage_inv_cs() {
1014 int getNumberOfCPUs()
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
1020 numberOfCPUs = (int) sysconf(_SC_NPROCESSORS_ONLN);
1022 return(numberOfCPUs);
1028 bool process::getActiveFrame(int *fp, int *pc)
1033 if (ioctl (proc_fd, PIOCGREG, ®s) != -1) {
1041 #ifdef sparc_sun_solaris2_4
1043 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool uppermost)
1052 function_base *func;
1056 func = this->findFunctionIn(pc);
1058 if (func->hasNoStackFrame()) { // formerly "isLeafFunc()"
1059 if (ioctl (proc_fd, PIOCGREG, ®s) != -1) {
1060 *rtn = regs[R_O7] + 8;
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
1076 if (readDataSpace((caddr_t) (currentFP + 56),
1077 sizeof(int)*2, (caddr_t) &addrs, true)) {
1078 // this is the previous frame pointer
1081 *rtn = addrs.rtn + 8;
1083 // if pc==0, then we are in the outermost frame and we should stop. We
1084 // do this by making fp=0.
1086 if ( (addrs.rtn == 0) || !isValidAddress(this,(Address) addrs.rtn) ) {
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().
1108 // We use the PIOCUSAGE /proc ioctl
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
1119 if (ioctl(proc_fd, PIOCUSAGE, &theUsage) == -1) {
1120 perror("could not read CPU time of inferior PIOCPSINFO");
1123 result = PDYN_mulMillion(theUsage.pr_utime.tv_sec); // sec to usec
1124 result += PDYN_div1000(theUsage.pr_utime.tv_nsec); // nsec to usec
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");
1139 void *process::getRegisters() {
1140 // Astonishingly, this routine can be shared between solaris/sparc and
1141 // solaris/x86. All hail /proc!!!
1143 // assumes the process is stopped (/proc requires it)
1144 assert(status_ == stopped);
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;
1157 prfpregset_t theFpRegs;
1158 if (ioctl(proc_fd, PIOCGFPREG, &theFpRegs) == -1) {
1159 perror("process::getRegisters PIOCGFPREG");
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;
1171 const int numbytesPart1 = sizeof(prgregset_t);
1172 const int numbytesPart2 = sizeof(prfpregset_t);
1173 assert(numbytesPart1 % 4 == 0);
1174 assert(numbytesPart2 % 4 == 0);
1176 void *buffer = new char[numbytesPart1 + numbytesPart2];
1179 memcpy(buffer, &theIntRegs, sizeof(theIntRegs));
1180 memcpy((char *)buffer + sizeof(theIntRegs), &theFpRegs, sizeof(theFpRegs));
1185 bool process::executingSystemCall() {
1187 if (ioctl(proc_fd, PIOCSTATUS, &theStatus) != -1) {
1188 if (theStatus.pr_syscall > 0) {
1189 inferiorrpc_cerr << "pr_syscall=" << theStatus.pr_syscall << endl;
1196 bool process::changePC(unsigned addr, const void *savedRegs) {
1197 assert(status_ == stopped);
1199 prgregset_t theIntRegs = *(const prgregset_t *)savedRegs; // makes a copy, on purpose
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;
1206 if (ioctl(proc_fd, PIOCSREG, &theIntRegs) == -1) {
1207 perror("process::changePC PIOCSREG failed");
1209 cerr << "It appears that the process wasn't stopped in the eyes of /proc" << endl;
1216 bool process::changePC(unsigned addr) {
1217 assert(status_ == stopped); // /proc will require this
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;
1229 theIntRegs[R_PC] = addr;
1231 theIntRegs[R_nPC] = addr + 4;
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;
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!
1250 assert(status_ == stopped); // /proc requires it
1252 prgregset_t theIntRegs = *(prgregset_t *)buffer;
1253 prfpregset_t theFpRegs = *(prfpregset_t *)((char *)buffer + sizeof(theIntRegs));
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;
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;
1276 #ifdef i386_unknown_solaris2_5
1278 bool process::readDataFromFrame(int currentFP, int *fp, int *rtn, bool )
1287 // for the x86, the frame-pointer (EBP) points to the previous frame-pointer,
1288 // and the saved return address is in EBP-4.
1291 if (readDataSpace((caddr_t) (currentFP),
1292 sizeof(int)*2, (caddr_t) &addrs, true)) {
1293 // this is the previous frame pointer
1298 // if pc==0, then we are in the outermost frame and we should stop. We
1299 // do this by making fp=0.
1301 if ( (addrs.rtn == 0) || !isValidAddress(this,(Address) addrs.rtn) ) {
1314 #ifdef i386_unknown_solaris2_5
1315 // ******** TODO **********
1316 bool process::needToAddALeafFrame(Frame , Address &) {
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){
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);
1335 sig_addr = signal_handler->getAddress(0);
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
1344 int fp = current_frame.getFramePtr();
1345 if (readDataSpace((caddr_t)(fp+40),sizeof(u_int),(caddr_t)®_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()"
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).
1366 // Remember, we can always return the empty string...no need to
1367 // go nuts writing the world's most complex algorithm.
1369 attach_cerr << "welcome to tryToFindExecutable; progpath=" << iprogpath << ", pid=" << pid << endl;
1371 const string progpath = expand_tilde_pathname(iprogpath);
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;
1380 attach_cerr << "tryToFindExecutable failed on filename " << progpath << endl;
1383 sprintf(buffer, "/proc/%05d", pid);
1384 int procfd = open(buffer, O_RDONLY, 0);
1386 attach_cerr << "tryToFindExecutable failed since open of /proc failed" << endl;
1389 attach_cerr << "tryToFindExecutable: opened /proc okay" << endl;
1391 string argv0, path, cwd;
1392 if (get_ps_stuff(procfd, argv0, path, cwd)) {
1393 // the following routine is implemented in the util lib.
1395 if (executableFromArgv0AndPathAndCwd(result, argv0, path, cwd)) {
1396 (void)close(procfd);
1401 attach_cerr << "tryToFindExecutable: giving up" << endl;
1403 (void)close(procfd);
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. */
1413 sysset_t save_exitset;
1414 if (-1 == ioctl(proc_fd, PIOCGEXIT, &save_exitset))
1417 sysset_t new_exit_set;
1418 prfillset(&new_exit_set);
1419 if (-1 == ioctl(proc_fd, PIOCSEXIT, &new_exit_set))
1422 assert(save_exitset_ptr == NULL);
1423 save_exitset_ptr = new sysset_t;
1424 memcpy(save_exitset_ptr, &save_exitset, sizeof(save_exitset));
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;
1437 return 0; // assert(false)?
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];
1445 return theIntRegs[R_O0];
1449 void print_read_error_info(const relocationEntry entry,
1450 pd_Function *&target_pdf, Address base_addr) {
1452 sprintf(errorLine, " entry : target_addr 0x%x\n",
1453 entry.target_addr());
1455 sprintf(errorLine, " rel_addr 0x%x\n", entry.rel_addr());
1457 sprintf(errorLine, " name %s\n", (entry.name()).string_of());
1460 sprintf(errorLine, " target_pdf : symTabName %s\n",
1461 (target_pdf->symTabName()).string_of());
1463 sprintf(errorLine , " prettyName %s\n",
1464 (target_pdf->symTabName()).string_of());
1466 sprintf(errorLine , " size %i\n",
1467 target_pdf->size());
1469 sprintf(errorLine , " addr 0x%x\n",
1470 target_pdf->addr());
1473 sprintf(errorLine, " base_addr 0x%x\n", base_addr);
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) {
1484 // TODO: the x86 and sparc versions should really go in seperate files
1485 #if defined(i386_unknown_solaris2_5)
1487 if (status() == exited) return false;
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
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);
1503 print_read_error_info(entry, target_pdf, base_addr);
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);
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
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",
1537 print_read_error_info(entry, target_pdf, base_addr);
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)) {
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",
1553 print_read_error_info(entry,target_pdf, base_addr);
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)) {
1561 Address new_target = (next_insn.sethi.imm22 << 10) & 0xfffffc00;
1562 new_target |= third_insn.resti.simm13;
1564 target_pdf = findpdFunctionIn(new_target);
1570 // this is a messed up entry
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).
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){
1599 if((target = (function_base *)instr.iPgetCallee())) {
1600 return true; // callee already set
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()) {
1612 base_addr = ((*shared_objects)[i])->getBaseAddress();
1619 return false; // image not found...this is bad
1622 // get the target address of this function
1623 Address target_addr = 0;
1624 // Address insn_addr = instr.iPgetAddress();
1625 target_addr = instr.getTargetAddress();
1628 // this is either not a call instruction or an indirect call instr
1629 // that we can't get the target address
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;
1643 // see if there is a function in this image at this target address
1645 pd_Function *pdf = 0;
1646 if( (pdf = owner->findFunctionInInstAndUnInst(target_addr,this)) ) {
1648 instr.set_callee(pdf);
1649 return true; // target found...target is in this image
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)) {
1657 return false; // target cannot be found...it is an indirect call.
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
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
1673 // just try to find a function with the same name as entry
1674 target = findOneFunctionFromAll((*fbt)[i].name());
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
1693 string s = string("_");
1694 s += (*fbt)[i].name();
1695 target = findOneFunctionFromAll(s);
1700 s += (*fbt)[i].name();
1701 target = findOneFunctionFromAll(s);