Remove dead code (save_the_world, #if 0).
[dyninst.git] / dyninstAPI / src / solaris.C
1 /*
2  * Copyright (c) 1996-2009 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  * By your use of Paradyn, you understand and agree that we (or any
12  * other person or entity with proprietary rights in Paradyn) are
13  * under no obligation to provide either maintenance services,
14  * update services, notices of latent defects, or correction of
15  * defects for Paradyn.
16  * 
17  * This library is free software; you can redistribute it and/or
18  * modify it under the terms of the GNU Lesser General Public
19  * License as published by the Free Software Foundation; either
20  * version 2.1 of the License, or (at your option) any later version.
21  * 
22  * This library is distributed in the hope that it will be useful,
23  * but WITHOUT ANY WARRANTY; without even the implied warranty of
24  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
25  * Lesser General Public License for more details.
26  * 
27  * You should have received a copy of the GNU Lesser General Public
28  * License along with this library; if not, write to the Free Software
29  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
30  */
31
32 // $Id: solaris.C,v 1.224 2008/06/19 22:13:43 jaw Exp $
33
34 #include "dyninstAPI/src/symtab.h"
35 #include "common/h/headers.h"
36 #include "dyninstAPI/src/process.h"
37 #include "dyninstAPI/src/binaryEdit.h"
38 #include "dyninstAPI/src/dyn_thread.h"
39 #include "common/h/stats.h"
40 #include "common/h/Types.h"
41 #include <sys/ioctl.h>
42 #include <fcntl.h>
43 #include <sys/termios.h>
44 #include <unistd.h>
45 #include <string>
46 #include "dyninstAPI/src/debug.h"
47 #include "common/h/pathName.h" // concat_pathname_components()
48 #include "common/h/debugOstream.h"
49 #include "common/h/solarisKludges.h"
50 #include "dyninstAPI/src/registerSpace.h"
51 #include "dyninstAPI/src/editSharedLibrary.h" //ccw 11 mar 2005
52 #include "mapped_module.h"
53 #include "mapped_object.h"
54 #include "dynamiclinking.h"
55 #include "dyninstAPI/h/BPatch.h"
56
57 #include "symtabAPI/src/Object.h" //TODO: Remove this
58
59 #if defined (sparc_sun_solaris2_4)
60 #include "dyninstAPI/src/inst-sparc.h"
61 #else
62 #include "dyninstAPI/src/inst-x86.h"
63 #endif
64
65 #include "signalgenerator.h"
66
67 #include "function.h"
68
69 #include "instPoint.h"
70 #include "baseTramp.h"
71 #include "miniTramp.h"
72
73 #include <procfs.h>
74 #include <stropts.h>
75 #include <link.h>
76 #include <dlfcn.h>
77 #include <strings.h> //ccw 11 mar 2005
78
79 #include "dyn_lwp.h"
80
81 #include "ast.h"
82 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
83
84 extern "C" {
85 extern long sysconf(int);
86 };
87
88 /*
89    Define the indices of some registers to be used with pr_reg.
90    These values are different on sparc and x86 platforms.
91    RETVAL_REG: the registers that holds the return value of calls ($o0 on sparc,
92                %eax on x86).
93    PC_REG: program counter
94    FP_REG: frame pointer (%i7 on sparc, %ebp on x86) 
95 */
96 #ifdef sparc_sun_solaris2_4
97 #define PARAM1_REG (R_O0)
98 #define RETVAL_REG (R_O0)
99 #define PC_REG (R_PC)
100 #define FP_REG (R_O6)
101 #endif
102 #ifdef i386_unknown_solaris2_5
103 #define RETVAL_REG (EAX)
104 #define SP_REG (UESP)
105 #define PC_REG (EIP)
106 #define FP_REG (EBP)
107 #endif
108
109
110 // already setup on this FD.
111 // disconnect from controlling terminal 
112 void OS::osDisconnect(void) {
113   //This is the POSIX-compliant way of disconnecting from the terminal 
114   setpgrp();
115 }
116
117 /*
118  * The set operations (set_entry_syscalls and set_exit_syscalls) are defined
119  * in sol_proc.C
120  */
121
122
123 // Compatibility for /proc
124 bool process::get_entry_syscalls(sysset_t *entry)
125 {
126     pstatus_t status;
127     if (!get_status(&status)) return false;
128     
129     memcpy(entry, &(status.pr_sysentry), sizeof(sysset_t));    
130     return true;
131 }
132
133 bool process::get_exit_syscalls(sysset_t *exit)
134 {
135     pstatus_t status;
136     if (!get_status(&status)) return false;
137
138     memcpy(exit, &(status.pr_sysexit), sizeof(sysset_t));
139     return true;
140 }    
141
142 #if defined (cap_save_the_world)
143 //TODO: This function should be converted to use process objects, not BPatch.
144 bool process::dldumpSharedLibrary(std::string originalLibNameFullPath, char* dirName){
145     BPatch_Vector<BPatch_snippet *> args;
146     char *newLibName = saveWorldFindNewSharedLibraryName(originalLibNameFullPath.c_str(),dirName);
147     
148     bool exists;
149     BPatch_process *bproc = BPatch::bpatch->getProcessByPid(getPid(), &exists);
150     
151     assert(exists);
152     BPatch_constExpr *oldNameArg= new BPatch_constExpr(originalLibNameFullPath.c_str());
153     BPatch_constExpr *newNameArg = new BPatch_constExpr(newLibName);
154     
155     args.push_back(oldNameArg);
156     args.push_back(newNameArg);
157     
158     BPatch_Vector<BPatch_function *> bpfv;
159     
160     if (((NULL == bproc->getImage()->findFunction("DYNINSTsaveRtSharedLibrary", bpfv) || !bpfv.size()))) {
161         cout << __FILE__ << ":" << __LINE__ << ": FATAL:  Cannot find Internal Function " << "DYNINSTsaveRtSharedLibrary" << endl;
162         if( newLibName){
163             delete [] newLibName;
164         }
165         return false;
166     }
167     
168     BPatch_function *dldump_func = bpfv[0]; 
169     if (dldump_func == NULL) {
170         if(newLibName){
171             delete [] newLibName;
172         }
173         return false;
174     }
175     
176     BPatch_funcCallExpr call_dldump(*dldump_func, args);
177     
178     /*fprintf(stderr,"CALLING dldump\n"); */
179     if (!bproc->oneTimeCodeInternal(call_dldump, NULL, NULL, NULL,true)) {
180         fprintf(stderr, "%s[%d]:  oneTimeCodeInternal failed\n", FILE__, __LINE__);
181         // dldump FAILED
182         // find the (global var) error string in the RT Lib and send it to the
183         // error reporting mechanism
184         BPatch_variableExpr *dlerror_str_var = bproc->getImage()->findVariable("gLoadLibraryErrorString");
185         assert(NULL != dlerror_str_var);
186         
187         char dlerror_str[256];
188         dlerror_str_var->readValue((void *)dlerror_str, 256);
189         cerr << dlerror_str << endl;
190         BPatch_reportError(BPatchWarning, 0, dlerror_str);
191         if(newLibName){
192             delete [] newLibName;
193         }
194         return false;
195     }
196     
197     editSharedLibrary editSL;
198     bool res = editSL.removeBSSfromSharedLibrary(newLibName);   
199     delete [] newLibName;
200     return res;
201 }
202 #endif
203
204
205 bool process::dumpImage(std::string imageFileName) 
206 {
207     int newFd;
208     string command;
209
210     string origFile = getAOut()->fileName();
211    
212     // first copy the entire image file
213     command = "cp ";
214     command += origFile;
215     command += " ";
216     command += imageFileName.c_str();
217     system(command.c_str());
218
219     // now open the copy
220     newFd = open(imageFileName.c_str(), O_RDWR, 0);
221     if (newFd < 0) {
222         // log error
223         return false;
224     }
225
226     Elf_X elf(newFd, ELF_C_READ);
227     if (!elf.isValid()) return false;
228
229     Elf_X_Shdr shstrscn = elf.get_shdr( elf.e_shstrndx() );
230     Elf_X_Data shstrdata = shstrscn.get_data();
231     const char* shnames = (const char *) shstrdata.get_string();
232
233     Address baseAddr = 0;
234     int length = 0;
235     int offset = 0;
236     for (int i = 0; i < elf.e_shnum(); ++i) {
237         Elf_X_Shdr shdr = elf.get_shdr(i);
238         const char *name = (const char *) &shnames[shdr.sh_name()];
239
240         if (!P_strcmp(name, ".text")) {
241             offset = shdr.sh_offset();
242             length = shdr.sh_size();
243             baseAddr = shdr.sh_addr();
244             break;
245         }
246     }
247
248     char *tempCode = new char[length];
249     bool ret = readTextSpace((void *) baseAddr, length, tempCode);
250     if (!ret) {
251         // log error
252
253         delete[] tempCode;
254         elf.end();
255         P_close(newFd);
256
257         return false;
258     }
259
260     lseek(newFd, offset, SEEK_SET);
261     write(newFd, tempCode, length);
262
263     // Cleanup
264     delete[] tempCode;
265     elf.end();
266     P_close(newFd);
267
268     return true;
269 }
270
271 /* Auxiliary function */
272 bool checkAllThreadsForBreakpoint(process *proc, Address break_addr)
273 {
274    pdvector<Frame> activeFrames;
275    if (!proc->getAllActiveFrames(activeFrames)) {
276       fprintf(stderr, "%s[%d]:  getAllActiveFrames failed\n", FILE__, __LINE__);
277       return false;
278    }
279    for(unsigned frame_iter = 0; frame_iter < activeFrames.size(); frame_iter++)
280    {
281       if (activeFrames[frame_iter].getPC() == break_addr) {
282          return true;
283       }
284    }
285    
286    return false;
287 }
288
289 bool process::trapAtEntryPointOfMain(dyn_lwp *, Address)
290 {
291     if (main_brk_addr == 0x0) return false;
292     return checkAllThreadsForBreakpoint(this, main_brk_addr);
293 }
294
295 bool process::handleTrapAtEntryPointOfMain(dyn_lwp *)
296 {
297     assert(main_brk_addr);
298     
299   // restore original instruction 
300     writeDataSpace((void *)main_brk_addr, sizeof(savedCodeBuffer), 
301                    (char *)savedCodeBuffer);
302     main_brk_addr = 0;
303     return true;
304 }
305
306 bool process::insertTrapAtEntryPointOfMain()
307 {
308
309     int_function *f_main = 0;
310     pdvector<int_function *> funcs;
311     
312     //first check a.out for function symbol   
313     bool res = findFuncsByPretty("main", funcs);
314     if (!res)
315     {
316         logLine( "a.out has no main function. checking for PLT entry\n" );
317         //we have not found a "main" check if we have a plt entry
318         res = findFuncsByPretty( "DYNINST_pltMain", funcs );
319  
320         if (!res) {
321             logLine( "no PLT entry for main found\n" );
322             return false;
323           }       
324     }
325     
326     if( funcs.size() > 1 ) {
327         cerr << __FILE__ << __LINE__ 
328              << ": found more than one main! using the first" << endl;
329     }
330     f_main = funcs[0];
331     assert(f_main);
332
333     Address addr = f_main->getAddress(); 
334
335     codeGen gen(instruction::size());
336     insnCodeGen::generateTrap(gen);
337
338     // save original instruction first
339     readDataSpace((void *)addr, sizeof(savedCodeBuffer), savedCodeBuffer, true);
340     
341     writeDataSpace((void *)addr, gen.used(), gen.start_ptr());
342
343     main_brk_addr = addr;
344     
345     return true;
346 }
347
348 bool process::handleTrapAtLibcStartMain(dyn_lwp *)  { assert(0); return false; }
349 bool process::instrumentLibcStartMain() { assert(0); return false; }
350 bool process::decodeStartupSysCalls(EventRecord &) { assert(0); return false; }
351 void process::setTraceSysCalls(bool) { assert(0); }
352 void process::setTraceState(traceState_t) { assert(0); }
353 bool process::getSysCallParameters(dyn_saved_regs *, long *, int) { assert(0); return false; }
354 int process::getSysCallNumber(dyn_saved_regs *) { assert(0); return 0; }
355 long process::getSysCallReturnValue(dyn_saved_regs *) { assert(0); return 0; }
356 Address process::getSysCallProgramCounter(dyn_saved_regs *) { assert(0); return 0; }
357 bool process::isMmapSysCall(int) { assert(0); return false; }
358 Offset process::getMmapLength(int, dyn_saved_regs *) { assert(0); return 0;}
359 Address process::getLibcStartMainParam(dyn_lwp *) { assert(0); return 0;}
360
361 bool AddressSpace::getDyninstRTLibName() {
362    if (dyninstRT_name.length() == 0) {
363       // Get env variable
364       if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
365          dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
366       }
367       else {
368          std::string msg = std::string("Environment variable ") +
369                         std::string("DYNINSTAPI_RT_LIB") +
370                         std::string(" has not been defined.");
371          showErrorCallback(101, msg);
372          return false;
373       }
374    }
375    
376     // Automatically choose the .a version or the .so version
377     const char *name = dyninstRT_name.c_str();
378
379     const char *split = P_strrchr(name, '/');
380     if ( !split ) split = name;
381     split = P_strchr(split, '.');
382     if ( !split || P_strlen(split) <= 1 ) {
383         // We should probably print some error here.
384         // Then, of course, the user will find out soon enough.
385         startup_printf("Invalid Dyninst RT lib name: %s\n", 
386                 dyninstRT_name.c_str());
387         return false;
388     }
389
390     const char *suffix = split;
391     if( getAOut()->isStaticExec() ) {
392         suffix = ".a";
393     }else{
394         if( P_strncmp(suffix, ".a", 2) == 0 ) {
395             // This will be incorrect if the RT library's version changes
396             suffix = ".so";
397         }
398     }
399
400     dyninstRT_name = std::string(name, split - name) +
401                      std::string(suffix);
402
403     startup_printf("Dyninst RT Library name set to '%s'\n",
404             dyninstRT_name.c_str());
405
406    // Check to see if the library given exists.
407    if (access(dyninstRT_name.c_str(), R_OK)) {
408       std::string msg = std::string("Runtime library ") + dyninstRT_name +
409                      std::string(" does not exist or cannot be accessed!");
410       showErrorCallback(101, msg);
411       return false;
412    }
413    return true;
414 }
415
416 bool process::loadDYNINSTlib() {
417     // we will write the following into a buffer and copy it into the
418     // application process's address space
419     // [....LIBRARY's NAME...|code for DLOPEN]
420     
421     // write to the application at codeOffset. This won't work if we
422     // attach to a running process.
423     //Address codeBase = this->getImage()->codeOffset();
424     // ...let's try "_start" instead
425     int_function *_startfn;
426     
427     pdvector<int_function *> funcs;
428     bool res = findFuncsByPretty("_start", funcs);
429     if (!res) {
430         // we can't instrument main - naim
431         showErrorCallback(108,"_start() unfound");
432         return false;
433     }
434
435     if( funcs.size() > 1 ) {
436         cerr << __FILE__ << __LINE__ 
437              << ": found more than one _start! using the first" << endl;
438     }
439     _startfn = funcs[0];
440
441     Address codeBase = _startfn->getAddress();
442     assert(codeBase);
443     
444     // Or should this be readText... it seems like they are identical
445     // the remaining stuff is thanks to Marcelo's ideas - this is what 
446     // he does in NT. The major change here is that we use AST's to 
447     // generate code for dlopen.
448     
449     // savedCodeBuffer[BYTES_TO_SAVE] is declared in process.h
450     readDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer, true);
451     
452     codeGen scratchCodeBuffer(BYTES_TO_SAVE);
453     scratchCodeBuffer.setAddrSpace(this);
454     scratchCodeBuffer.setAddr(codeBase);
455     scratchCodeBuffer.setRegisterSpace(registerSpace::savedRegSpace(this));
456
457     // First we write in the dyninst lib string. Vewy simple.
458     Address dyninstlib_addr = codeBase;
459     
460     scratchCodeBuffer.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
461
462     // Were we're calling into
463     Address dlopencall_addr = codeBase + scratchCodeBuffer.used();
464
465     /*
466       fprintf(stderr, "dlopen call addr at 0x%x, for codeBase of 0x%x\n",
467             dlopencall_addr, codeBase);
468     */
469
470
471     pdvector<AstNodePtr> dlopenAstArgs(2);
472     AstNodePtr dlopenAst;
473     
474     // We call directly into ld.so.1. This used to be handled in 
475     // process::findInternalSymbols, which made it very difficult
476     // to figure out what was going on.
477     Address dlopen_func_addr = dyn->get_dlopen_addr();
478     assert(dlopen_func_addr);
479
480     //fprintf(stderr, "We want to call 0x%x\n", dlopen_func_addr);
481     // See if we can get a function for it.
482
483     dlopenAstArgs[0] = AstNode::operandNode(AstNode::Constant, (void *)(dyninstlib_addr));
484     dlopenAstArgs[1] = AstNode::operandNode(AstNode::Constant, (void*)DLOPEN_MODE);
485     dlopenAst = AstNode::funcCallNode(dlopen_func_addr, dlopenAstArgs);
486
487     dlopenAst->generateCode(scratchCodeBuffer,
488                             true);
489
490     // Slap in a breakpoint
491     dyninstlib_brk_addr = codeBase + scratchCodeBuffer.used();
492     insnCodeGen::generateTrap(scratchCodeBuffer);
493     
494     writeDataSpace((void *)codeBase, scratchCodeBuffer.used(), 
495                    scratchCodeBuffer.start_ptr());
496     
497     //fprintf(stderr, "Breakpoint at 0x%x\n", dyninstlib_brk_addr);
498     
499     // save registers
500     savedRegs = new dyn_saved_regs;
501     bool status = getRepresentativeLWP()->getRegisters(savedRegs);
502     assert(status == true);
503     
504     if (!getRepresentativeLWP()->changePC(dlopencall_addr, NULL)) {
505         logLine("WARNING: changePC failed in loadDYNINSTlib\n");
506         assert(0);
507     }
508     setBootstrapState(loadingRT_bs);
509     return true;
510 }
511
512 bool process::trapDueToDyninstLib(dyn_lwp *)
513 {
514   if (dyninstlib_brk_addr == 0) return(false);
515   return checkAllThreadsForBreakpoint(this, dyninstlib_brk_addr);
516 }
517
518 bool process::loadDYNINSTlibCleanup(dyn_lwp *)
519 {
520   // rewrite original instructions in the text segment we use for 
521   // the inferiorRPC - naim
522   unsigned count = sizeof(savedCodeBuffer);
523   //Address codeBase = getImage()->codeOffset();
524
525   int_function *_startfn;
526
527     pdvector<int_function *> funcs;
528     bool res = findFuncsByPretty("_start", funcs);
529     if (!res) {
530         // we can't instrument main - naim
531         showErrorCallback(108,"_start() unfound");
532         return false;
533     }
534
535     if( funcs.size() > 1 ) {
536         cerr << __FILE__ << __LINE__ 
537              << ": found more than one main! using the first" << endl;
538     }
539     _startfn = funcs[0];
540
541     Address codeBase = _startfn->getAddress();
542     assert(codeBase);
543     if (!writeDataSpace((void *)codeBase, count, (char *)savedCodeBuffer))
544         return false;
545
546     // restore registers
547     if (!getRepresentativeLWP()->restoreRegisters(*savedRegs))
548      return false;
549     delete savedRegs;
550     savedRegs = NULL;
551     return true;
552 }
553
554 bool SignalGeneratorCommon::getExecFileDescriptor(std::string filename,
555                                     int /*pid*/,
556                                     bool /*whocares*/,
557                                     int &,
558                                     fileDescriptor &desc)
559 {
560     desc = fileDescriptor(filename.c_str(), 0, 0, false);
561     return true;
562 }
563
564 #if defined(cap_dynamic_heap)
565 static const Address lowest_addr = 0x0;
566 void process::inferiorMallocConstraints(Address near, Address &lo, Address &hi,
567                                         inferiorHeapType /* type */)
568 {
569   if (near)
570     {
571       lo = region_lo(near);
572       hi = region_hi(near);  
573     }
574 }
575 #endif
576
577 bool process::dumpCore_(const std::string coreName) 
578 {
579   char command[100];
580
581   sprintf(command, "gcore %d 2> /dev/null; mv core.%d %s", getPid(), getPid(), 
582           coreName.c_str());
583
584   detach(false);
585   system(command);
586   attach();
587
588   return false;
589 }
590
591 Frame Frame::getCallerFrame()
592 {
593   Address newPC=0;
594   Address newFP=0;
595   Address newSP=0;
596
597   //fprintf(stderr, "Frame::getCallerFrame for %p\n", this);
598
599   if (uppermost_) {
600     codeRange *range = getRange();
601     int_function *func = range->is_function();
602     if (func) {
603         struct dyn_saved_regs regs;
604         bool status;
605         if (lwp_)
606           status = lwp_->getRegisters(&regs);
607         else
608           status = getProc()->getRepresentativeLWP()->getRegisters(&regs);
609
610         assert(status == true);
611       if (func->hasNoStackFrame()) { // formerly "isLeafFunc()"
612         newPC = regs.theIntRegs[R_O7] + 8;
613         newFP = fp_; // frame pointer unchanged
614       } else {
615         newPC = regs.theIntRegs[R_O7] + 8;
616         if (!getProc()->readDataSpace((caddr_t)(fp_ + 56), sizeof(int), (caddr_t)&newFP, true))
617            return Frame();
618       }
619         return Frame(newPC, newFP, newSP, 0, this);
620     }
621   }
622   //
623   // For the sparc, register %i7 is the return address - 8 and the fp is
624   // register %i6. These registers can be located in %fp+14*5 and
625   // %fp+14*4 respectively, but to avoid two calls to readDataSpace,
626   // we bring both together (i.e. 8 bytes of memory starting at %fp+14*4
627   // or %fp+56).
628   // These values are copied to the stack when the application is paused,
629   // so we are assuming that the application is paused at this point
630   
631   struct {
632     Address fp;
633     Address rtn;
634   } addrs;
635   
636   if (getProc()->readDataSpace((caddr_t)(fp_ + 56), 2*sizeof(int),
637                                (caddr_t)&addrs, true))
638     {
639
640       newFP = addrs.fp;
641       newPC = addrs.rtn + 8;
642
643       if (isSignalFrame()) {
644          // get the value of the saved PC: this value is stored in the
645          // address specified by the value in register i2 + 44. Register i2
646          // must contain the address of some struct that contains, among
647          // other things, the saved PC value.
648          u_int reg_i2;
649          if (getProc()->readDataSpace((caddr_t)(fp_+40), sizeof(u_int),
650                               (caddr_t)&reg_i2,true)) {
651             Address saved_pc;
652             if (getProc()->readDataSpace((caddr_t) (reg_i2+44), sizeof(int),
653                                  (caddr_t) &saved_pc,true)) {
654                
655                int_function *func = getProc()->findFuncByAddr(saved_pc);
656                
657                newPC = saved_pc;
658                if (func && func->hasNoStackFrame())
659                   newFP = fp_;
660             }
661          }
662          else {
663            return Frame();
664          }
665       }
666       
667
668       if(getProc()->multithread_capable()) {
669          // MT thread adds another copy of the start function
670          // to the top of the stack... this breaks instrumentation
671          // since we think we're at a function entry.
672          if (newFP == 0) newPC = 0;
673       }
674       Frame ret = Frame(newPC, newFP, 0, 0, this);
675
676       codeRange *range = getRange();
677       // Find our way out of the minitramp, and up to the calling function
678       if (range->is_minitramp()) {
679          instPoint *p = getPoint();
680          if (p->getPointType() != functionEntry &&
681              !p->func()->hasNoStackFrame()) {
682             if (!getProc()->readDataSpace((caddr_t)(newFP + 60), sizeof(int), (caddr_t)&newPC, true))
683                return Frame();
684             if (!getProc()->readDataSpace((caddr_t)(newFP + 56), sizeof(int), (caddr_t)&newFP, true))
685                return Frame();
686             ret = Frame(newPC, newFP, 0, 0, this);
687          }
688       }
689
690       // If we're in a base tramp, skip this frame (return getCallerFrame)
691       // as we only return minitramps
692       if (range->is_multitramp()) {
693           // If we're inside instrumentation only....
694           multiTramp *multi = range->is_multitramp();
695           baseTrampInstance *bti = multi->getBaseTrampInstanceByAddr(getPC());
696           if (bti &&
697               bti->isInInstru(getPC()))
698               return ret.getCallerFrame();
699       }
700       return ret;
701     }
702    return Frame(); // zero frame
703 }
704
705 bool Frame::setPC(Address newpc) {
706   fprintf(stderr, "Implement me! Changing frame PC from %x to %x\n",
707           pc_, newpc);
708   return false;
709 }
710
711
712 void print_read_error_info(const SymtabAPI::relocationEntry entry, 
713                            int_function *&target_pdf, Address base_addr) {
714
715    sprintf(errorLine, "  entry      : target_addr 0x%lx\n",
716            entry.target_addr());
717    logLine(errorLine);
718    sprintf(errorLine, "               rel_addr 0x%lx\n", entry.rel_addr());
719    logLine(errorLine);
720    sprintf(errorLine, "               name %s\n", (entry.name()).c_str());
721    logLine(errorLine);
722    
723    if (target_pdf) {
724       sprintf(errorLine, "  target_pdf : symTabName %s\n",
725               (target_pdf->symTabName()).c_str());
726       logLine(errorLine);    
727       sprintf(errorLine , "              prettyName %s\n",
728               (target_pdf->symTabName()).c_str());
729       logLine(errorLine);
730       sprintf(errorLine , "              addr 0x%lx\n",
731               target_pdf->getAddress());
732       logLine(errorLine);
733    }
734
735    sprintf(errorLine, "  base_addr  0x%lx\n", base_addr);
736    logLine(errorLine);
737 }
738
739 // hasBeenBound: returns true if the runtime linker has bound the
740 // function symbol corresponding to the relocation entry in at the address
741 // specified by entry and base_addr.  If it has been bound, then the callee 
742 // function is returned in "target_pdf", else it returns false.
743 bool process::hasBeenBound(const SymtabAPI::relocationEntry &entry, 
744                            int_function *&target_pdf, Address base_addr) {
745
746 // TODO: the x86 and sparc versions should really go in seperate files 
747 #if defined(i386_unknown_solaris2_5)
748
749     if (status() == exited) return false;
750
751     // if the relocationEntry has not been bound yet, then the value
752     // at rel_addr is the address of the instruction immediately following
753     // the first instruction in the PLT entry (which is at the target_addr) 
754     // The PLT entries are never modified, instead they use an indirrect 
755     // jump to an address stored in the _GLOBAL_OFFSET_TABLE_.  When the 
756     // function symbol is bound by the runtime linker, it changes the address
757     // in the _GLOBAL_OFFSET_TABLE_ corresponding to the PLT entry
758
759     Address got_entry = entry.rel_addr() + base_addr;
760     Address bound_addr = 0;
761     if(!readDataSpace((const void*)got_entry, sizeof(Address), 
762                         &bound_addr, true)){
763         sprintf(errorLine, "read error in process::hasBeenBound "
764                 "addr 0x%lx, pid=%d\n (readDataSpace returns 0)",
765                 got_entry, pid);
766         logLine(errorLine);
767         print_read_error_info(entry, target_pdf, base_addr);
768         return false;
769     }
770
771     if( !( bound_addr == (entry.target_addr()+6+base_addr)) ) {
772         // the callee function has been bound by the runtime linker
773         // find the function and return it
774         target_pdf = findFuncByAddr(bound_addr);
775         if(!target_pdf){
776             return false;
777         }
778         return true;    
779     }
780     return false;
781
782 #else
783     // if the relocationEntry has not been bound yet, then the second instr 
784     // in this PLT entry branches to the fist PLT entry.  If it has been   
785     // bound, then second two instructions of the PLT entry have been changed 
786     // by the runtime linker to jump to the address of the function.  
787     // Here is an example:   
788     //     before binding                       after binding
789     //     --------------                       -------------
790     //     sethi  %hi(0x15000), %g1             sethi  %hi(0x15000), %g1
791     //     b,a  <_PROCEDURE_LINKAGE_TABLE_>     sethi  %hi(0xef5eb000), %g1
792     //     nop                                  jmp  %g1 + 0xbc ! 0xef5eb0bc
793
794     unsigned int insnBuf;
795
796     Address next_insn_addr = entry.target_addr() + base_addr + instruction::size(); 
797     if( !(readDataSpace((caddr_t)next_insn_addr, instruction::size(), 
798                         (char *)&insnBuf, true)) ) {
799         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%lx"
800                 " (readDataSpace next_insn_addr returned 0)\n",
801                 next_insn_addr);
802         logLine(errorLine);
803         print_read_error_info(entry, target_pdf, base_addr);
804     }
805     instruction next_insn(insnBuf);
806     // if this is a b,a instruction, then the function has not been bound
807     if(((*next_insn).branch.op == FMT2op)  && ((*next_insn).branch.op2 == BICCop2) 
808        && ((*next_insn).branch.anneal == 1) && ((*next_insn).branch.cond == BAcond)) {
809         return false;
810     } 
811
812     // if this is a sethi instruction, then it has been bound...get target_addr
813     Address third_addr = entry.target_addr() + base_addr + 8; 
814     if( !(readDataSpace((caddr_t)third_addr, instruction::size(),
815                        (char *)&insnBuf, true)) ) {
816         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%lx"
817                 " (readDataSpace third_addr returned 0)\n",
818                 third_addr);
819         logLine(errorLine);
820         print_read_error_info(entry,target_pdf, base_addr);
821     }
822
823     instruction third_insn(insnBuf);
824
825     // get address of bound function, and return the corr. int_function
826     if(((*next_insn).sethi.op == FMT2op) && ((*next_insn).sethi.op2 == SETHIop2)
827         && ((*third_insn).rest.op == RESTop) && ((*third_insn).rest.i == 1)
828         && ((*third_insn).rest.op3 == JMPLop3)) {
829         
830         Address new_target = ((*next_insn).sethi.imm22 << 10) & 0xfffffc00; 
831         new_target |= (*third_insn).resti.simm13;
832
833         target_pdf = findFuncByAddr(new_target);
834         if(!target_pdf){
835             return false;
836         }
837         return true;
838     }
839     // this is a messed up entry
840     return false;
841 #endif
842
843 }
844
845
846
847 // findCallee: finds the function called by the instruction corresponding
848 // to the instPoint "instr". If the function call has been bound to an
849 // address, then the callee function is returned in "target" and the 
850 // instPoint "callee" data member is set to pt to callee's int_function.  
851 // If the function has not yet been bound, then "target" is set to the 
852 // int_function associated with the name of the target function (this is 
853 // obtained by the PLT and relocation entries in the image), and the instPoint
854 // callee is not set.  If the callee function cannot be found, (ex. function
855 // pointers, or other indirect calls), it returns false.
856 // Returns false on error (ex. process doesn't contain this instPoint).
857 //
858 int_function *instPoint::findCallee() {
859
860    if(callee_) {
861        return callee_;
862    }
863
864        if (ipType_ != callSite) {
865         return NULL;
866     }
867
868     if (isDynamic()) { 
869         return NULL;
870     }
871
872     // Check if we parsed an intra-module static call
873     assert(img_p_);
874     image_func *icallee = img_p_->getCallee();
875     if (icallee) {
876         // Now we have to look up our specialized version
877         // Can't do module lookup because of DEFAULT_MODULE...
878         const pdvector<int_function *> *possibles = func()->obj()->findFuncVectorByMangled(icallee->symTabName().c_str());
879         if (!possibles) {
880             return NULL;
881         }
882         for (unsigned i = 0; i < possibles->size(); i++) {
883           if ((*possibles)[i]->ifunc() == icallee) {
884                 callee_ = (*possibles)[i];
885                 return callee_;
886             }
887         }
888         // No match... very odd
889         assert(0);
890         return NULL;
891     }
892
893     
894     // get the target address of this function
895     Address target_addr = img_p_->callTarget();
896     //    Address insn_addr = instr.pointAddr(); 
897     
898     if(!target_addr) {  
899         // this is either not a call instruction or an indirect call instr
900         // that we can't get the target address
901         return NULL;
902     }
903     
904     
905     // else, get the relocation information for this image
906     SymtabAPI::Symtab *obj = func()->obj()->parse_img()->getObject();
907     vector<SymtabAPI::relocationEntry> fbtvector;
908     if(!obj->getFuncBindingTable(fbtvector))
909         return false;   // target cannot be found...it is an indirect call.
910     pdvector<SymtabAPI::relocationEntry> *fbt = new pdvector<SymtabAPI::relocationEntry>;
911     for(unsigned index=0;index<fbtvector.size();index++)
912         fbt->push_back(fbtvector[index]);
913     
914     // find the target address in the list of relocationEntries
915     Address base_addr = func()->obj()->codeBase();
916     for(u_int i=0; i < fbt->size(); i++) {
917         if((*fbt)[i].target_addr() == target_addr) {
918             // check to see if this function has been bound yet...if the
919             // PLT entry for this function has been modified by the runtime
920             // linker
921             int_function *target_pdf = 0;
922             if(proc()->hasBeenBound((*fbt)[i], target_pdf, base_addr)) {
923                 callee_ = target_pdf;
924                 return callee_;
925             } 
926             else {
927                 // just try to find a function with the same name as entry 
928                 pdvector<int_function *> pdfv;
929                 bool found = proc()->findFuncsByMangled((*fbt)[i].name().c_str(), pdfv);
930                 if(found) {
931                     assert(pdfv.size());
932                     if(pdfv.size() > 1)
933                         cerr << __FILE__ << ":" << __LINE__ 
934                              << ": WARNING:  findAllFuncsByName found " 
935                              << pdfv.size() << " references to function " 
936                              << (*fbt)[i].name() << ".  Using the first.\n";
937                     callee_ = pdfv[0];
938                     return callee_;
939                 }
940             }
941             return NULL;
942         }
943     }
944     return NULL;
945 }
946
947 // vim:ts=5:
948
949 /**
950  * Searches for function in order, with preference given first 
951  * to libpthread, then to libc, then to the process.
952  **/
953 static void findThreadFuncs(process *p, std::string func, 
954                             pdvector<int_function *> &result)
955 {
956    bool found = false;
957    mapped_module *lpthread = p->findModule("libthread*", true);
958    if (lpthread)
959       found = lpthread->findFuncVectorByPretty(func, result);
960    if (found) {
961       return;
962    }
963    /*
964     * Do not look in libc... there are matches, but they're singlethread versions
965
966     mapped_module *lc = p->findModule("libc.so*", true);
967     if (lc)
968     found = lc->findFuncVectorByPretty(func, result);
969     if (found) {
970     fprintf(stderr, "found in libc.so\n");
971     return;
972     }
973    */
974
975    p->findFuncsByPretty(func, result);
976 }
977
978 bool process::initMT()
979 {
980     unsigned i;
981     bool res;
982     
983 #if !defined(cap_threads)
984     return true;
985 #endif
986
987     /**
988      * Instrument thread_create with calls to DYNINST_dummy_create
989      **/
990     pdvector<int_function *> thread_init_funcs;
991     findThreadFuncs(this, "init_func", thread_init_funcs);
992     if (thread_init_funcs.size() < 1) {
993         //findThreadFuncs(this, "_lwp_start", thread_init_funcs);
994         findThreadFuncs(this, "_thr_setup", thread_init_funcs);
995         if (thread_init_funcs.size() < 1) {
996           findThreadFuncs(this, "_thread_start", thread_init_funcs);
997           if (thread_init_funcs.size() < 1) {
998             fprintf(stderr, "%s[%d]: no copies of thread start function, expected 1\n",
999                     FILE__, __LINE__);
1000
1001             return false;
1002           }
1003         }
1004     }
1005
1006     //Find DYNINST_dummy_create
1007    int_function *dummy_create = findOnlyOneFunction("DYNINST_dummy_create");
1008    if (!dummy_create) {
1009        fprintf(stderr, "[%s:%d] - Couldn't find DYNINST_dummy_create",
1010                __FILE__, __LINE__);
1011        return false;
1012    }
1013    //Instrument
1014    for (i=0; i<thread_init_funcs.size(); i++)
1015    {
1016       pdvector<AstNodePtr> args;
1017       AstNodePtr call_dummy_create = AstNode::funcCallNode(dummy_create, args);
1018       const pdvector<instPoint *> &ips = thread_init_funcs[i]->funcEntries();
1019       for (unsigned j=0; j<ips.size(); j++)
1020       {
1021          miniTramp *mt;
1022          mt = ips[j]->instrument(call_dummy_create, callPreInsn, orderFirstAtPoint, false, 
1023                                  false);
1024          if (!mt)
1025          {
1026             fprintf(stderr, "[%s:%d] - Couldn't instrument thread_create\n",
1027                     __FILE__, __LINE__);
1028          }
1029          //TODO: Save the mt objects for detach
1030       }
1031    }
1032    
1033    /**
1034     * Have dyn_pthread_self call the actual pthread_self
1035     **/
1036    //Find dyn_pthread_self
1037    pdvector<int_variable *> ptself_syms;
1038    res = findVarsByAll("DYNINST_pthread_self", ptself_syms);
1039    if (!res) {
1040        fprintf(stderr, "[%s:%d] - Couldn't find any dyn_pthread_self, expected 1\n",
1041                __FILE__, __LINE__);
1042    }
1043    assert(ptself_syms.size() == 1);
1044    Address dyn_pthread_self = ptself_syms[0]->getAddress();
1045
1046
1047    //Find pthread_self
1048    pdvector<int_function *> pthread_self_funcs;
1049    findThreadFuncs(this, "thr_self", pthread_self_funcs);   
1050    if (pthread_self_funcs.size() != 1) {
1051        fprintf(stderr, "[%s:%d] - Found %d pthread_self functions, expected 1\n",
1052                __FILE__, __LINE__, pthread_self_funcs.size());
1053        for (unsigned j=0; j<pthread_self_funcs.size(); j++) {
1054            int_function *ps = pthread_self_funcs[j];
1055            fprintf(stderr, "[%s:%u] - %s in module %s at %lx\n", __FILE__, __LINE__,
1056                    ps->prettyName().c_str(), ps->mod()->fullName().c_str(), 
1057                    ps->getAddress());
1058        }
1059        return false;
1060    }   
1061    //Replace
1062    res = writeFunctionPtr(this, dyn_pthread_self, pthread_self_funcs[0]);
1063    if (!res) {
1064        fprintf(stderr, "[%s:%d] - Couldn't update dyn_pthread_self\n",
1065                __FILE__, __LINE__);
1066        return false;
1067    }
1068    return true;
1069 }
1070
1071 #include <sched.h>
1072 void dyninst_yield()
1073 {
1074    sched_yield();
1075 }
1076
1077 bool SignalHandler::handleProcessExitPlat(EventRecord & /*ev*/, bool &) 
1078 {
1079     return true;
1080 }
1081
1082 bool process::hasPassedMain() 
1083 {
1084    return true;
1085 }
1086
1087 bool BinaryEdit::getResolvedLibraryPath(const std::string &filename, std::vector<std::string> &paths) {
1088     // No actual library name resolution for now
1089     paths.push_back(filename);
1090     return true;
1091 }
1092
1093 // Temporary remote debugger interface.
1094 // I assume these will be removed when procControlAPI is complete.
1095 bool OS_isConnected(void)
1096 {
1097     return true;  // We're always connected to the child on this platform.
1098 }
1099
1100 bool OS_connect(BPatch_remoteHost &/*remote*/)
1101 {
1102     return true;  // We're always connected to the child on this platform.
1103 }
1104
1105 bool OS_getPidList(BPatch_remoteHost &/*remote*/,
1106                    BPatch_Vector<unsigned int> &/*tlist*/)
1107 {
1108     return false;  // Not implemented.
1109 }
1110
1111 bool OS_getPidInfo(BPatch_remoteHost &/*remote*/,
1112                    unsigned int /*pid*/, std::string &/*pidStr*/)
1113 {
1114     return false;  // Not implemented.
1115 }
1116
1117 bool OS_disconnect(BPatch_remoteHost &/*remote*/)
1118 {
1119     return true;
1120 }