BPatch_binaryEdit::staticExecutableLoaded was poorly named. Changing
[dyninst.git] / dyninstAPI / src / linux-x86.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: linux-x86.C,v 1.142 2008/08/01 17:55:12 roundy Exp $
33
34 #include <fstream>
35 #include <string>
36
37 #include "dyninstAPI/src/process.h"
38
39 #include <sys/ptrace.h>
40 #include <sys/ioctl.h>
41 #include <fcntl.h>
42 #include <dlfcn.h>
43 #include <sys/user.h>
44 #include <sys/time.h>
45 #include <sys/resource.h>
46 #include <math.h> // for floor()
47 #include <unistd.h> // for sysconf()
48 #include <elf.h>
49 #include <libelf.h>
50
51 #include "dyninstAPI/src/miniTramp.h"
52 #include "dyninstAPI/src/baseTramp.h"
53 #include "dyninstAPI/src/symtab.h"
54 #include "dyninstAPI/src/instPoint.h"
55 #include "common/h/headers.h"
56 #include "dyninstAPI/src/os.h"
57 #include "common/h/stats.h"
58 #include "common/h/Types.h"
59 #include "dyninstAPI/src/debug.h"
60 #include "dyninstAPI/src/util.h" // getCurrWallTime
61 #include "common/h/pathName.h"
62 #include "dyninstAPI/src/inst-x86.h"
63 #include "dyninstAPI/src/emit-x86.h"
64 #include "dyninstAPI/src/dyn_thread.h"
65 //#include "dyninstAPI/src/InstrucIter.h"
66
67 #include "dyninstAPI/src/mapped_object.h" 
68 #include "dyninstAPI/src/signalgenerator.h" 
69
70 #include "dyninstAPI/src/dyn_lwp.h"
71 #include "dyninstAPI/src/linux.h"
72
73 #include "dyninstAPI/src/registerSpace.h"
74
75 #include <sstream>
76
77 #if defined (cap_save_the_world)
78 #include "dyninstAPI/src/addLibraryLinux.h"
79 #include "dyninstAPI/src/writeBackElf.h"
80 #endif
81 #include "dyninstAPI/src/debuggerinterface.h"
82
83 #include "dyninstAPI/src/ast.h"
84 #include "dyninstAPI/src/dynamiclinking.h"
85 #include "dyninstAPI/src/binaryEdit.h"
86
87 #include "instructionAPI/h/InstructionDecoder.h"
88 #include "instructionAPI/h/Instruction.h"
89
90 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
91
92 const char *DL_OPEN_FUNC_USER = NULL;
93 const char DL_OPEN_FUNC_EXPORTED[] = "dlopen";
94 const char DL_OPEN_FUNC_NAME[] = "do_dlopen";
95 const char DL_OPEN_FUNC_INTERNAL[] = "_dl_open";
96
97 const char libc_version_symname[] = "__libc_version";
98
99
100 #if defined(PTRACEDEBUG) && !defined(PTRACEDEBUG_ALWAYS)
101 static bool debug_ptrace = false;
102 #endif
103
104 #define NUM_REGS (17 /*+ NUM_FREGS*/)
105 #define NUM_FREGS 8
106 #define FP0_REGNUM NUM_REGS
107 #define FP7_REGNUM (FP0_REGNUM+7)
108 #define INTREGSIZE (sizeof(long))
109 #define FPREGSIZE 10
110 #define MAX_REGISTER_RAW_SIZE 10
111
112 #define REGISTER_RAW_SIZE(N) (((N) < FP0_REGNUM) ? INTREGSIZE : FPREGSIZE)
113 #define REGS_SIZE ( NUM_REGS * REGISTER_RAW_SIZE(0) + NUM_FREGS * REGISTER_RAW_SIZE(FP0_REGNUM) )
114 #define REGS_INTS ( REGS_SIZE / INTREGSIZE )
115
116 const int GENREGS_STRUCT_SIZE = sizeof( user_regs_struct );
117 #ifdef _SYS_USER_H 
118 const int FPREGS_STRUCT_SIZE = sizeof( user_fpregs_struct );
119 #else
120 const int FPREGS_STRUCT_SIZE = sizeof( user_i387_struct );
121 #endif
122
123 #define P_offsetof(s, m) (Address) &(((s *) NULL)->m)
124
125 /* ********************************************************************** */
126
127 bool dyn_lwp::getRegisters_(struct dyn_saved_regs *regs, bool includeFP) 
128 {
129    // Cycle through all registers, reading each from the
130    // process user space with ptrace(PTRACE_PEEKUSER ...
131    int error;
132    bool errorFlag = false;
133    assert(get_lwp_id() != 0);
134    int ptrace_errno = 0;
135    error = DBI_ptrace(PTRACE_GETREGS, get_lwp_id(), 0, (long)&(regs->gprs), 
136          &ptrace_errno, proc_->getAddressWidth(),  
137          __FILE__, __LINE__ );
138    if( error ) {
139       perror("dyn_lwp::getRegisters PTRACE_GETREGS" );
140       errorFlag = true;
141       return false;
142    }
143
144    if (includeFP)
145    {
146       error = DBI_ptrace(PTRACE_GETFPREGS, get_lwp_id(), 0,
147             (long)&(regs->fprs), &ptrace_errno,
148             proc_->getAddressWidth(),  __FILE__, __LINE__);
149
150       if( error ) {
151          perror("dyn_lwp::getRegisters PTRACE_GETFPREGS" );
152          return false;
153       }
154    }
155    return true;
156 }
157
158 void dyn_lwp::dumpRegisters()
159 {
160    dyn_saved_regs regs;
161    if (!getRegisters(&regs)) {
162       fprintf(stderr, "%s[%d]:  registers unavailable\n", FILE__, __LINE__);
163       return;
164    }
165
166 #if defined(arch_x86)
167    fprintf(stderr, "eip:   %lx\n", regs.gprs.eip);
168    fprintf(stderr, "eax:   %lx\n", regs.gprs.eax);
169    fprintf(stderr, "ebx:   %lx\n", regs.gprs.ebx);
170    fprintf(stderr, "ecx:   %lx\n", regs.gprs.ecx);
171    fprintf(stderr, "esp:   %lx\n", regs.gprs.esp);
172    fprintf(stderr, "xcs:   %lx\n", regs.gprs.xcs);
173 #endif
174 #if defined(arch_x86_64)
175    fprintf(stderr, "eip:   %lx\n", regs.gprs.rip);
176    fprintf(stderr, "eax:   %lx\n", regs.gprs.rax);
177    fprintf(stderr, "ebx:   %lx\n", regs.gprs.rbx);
178    fprintf(stderr, "ecx:   %lx\n", regs.gprs.rcx);
179    fprintf(stderr, "esp:   %lx\n", regs.gprs.rsp);
180    fprintf(stderr, "xcs:   %lx\n", regs.gprs.cs);
181 #endif
182    //  plenty more register if we want to print em....
183 }
184
185 bool dyn_lwp::changePC(Address loc,
186       struct dyn_saved_regs */*ignored registers*/)
187 {
188    Address regaddr = P_offsetof(struct user_regs_struct, PTRACE_REG_IP);
189    assert(get_lwp_id() != 0);
190    int ptrace_errno = 0;
191
192    // Check to see if the incoming address is valid...
193    #if defined(arch_x86_64)
194    if ((proc_->getAddressWidth() == 4) &&
195        (sizeof(Address) == 8)) {
196      assert(!(loc & 0xffffffff00000000));
197    }
198    #endif
199    if (0 != DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(), regaddr, loc, 
200             &ptrace_errno, proc_->getAddressWidth(),  
201             __FILE__, __LINE__ )) {
202       fprintf(stderr, "dyn_lwp::changePC - PTRACE_POKEUSER failure for %u",
203             get_lwp_id());
204       return false;
205    }
206    
207    return true;
208 }
209
210 bool dyn_lwp::clearOPC() 
211 {
212    Address regaddr = P_offsetof(struct user_regs_struct, PTRACE_REG_ORIG_AX);
213    assert(get_lwp_id() != 0);
214    int ptrace_errno = 0;
215    if (0 != DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(), regaddr, -1UL, &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__)) {
216       perror( "dyn_lwp::changePC - PTRACE_POKEUSER" );
217       return false;
218    }
219    return true;
220 }
221
222 #define REG_STR(x)      REG_STR_(x)
223 #define REG_STR_(x)     #x
224 void printRegs( void *save ) 
225 {
226    user_regs_struct *regs = (user_regs_struct*)save;
227    cerr
228       << REG_STR( PTRACE_REG_AX ) ": " << (void*)regs->PTRACE_REG_AX
229       << REG_STR( PTRACE_REG_BX ) ": " << (void*)regs->PTRACE_REG_BX
230       << REG_STR( PTRACE_REG_CX ) ": " << (void*)regs->PTRACE_REG_CX
231       << REG_STR( PTRACE_REG_DX ) ": " << (void*)regs->PTRACE_REG_DX << endl
232       << REG_STR( PTRACE_REG_DI ) ": " << (void*)regs->PTRACE_REG_DI
233       << REG_STR( PTRACE_REG_SI ) ": " << (void*)regs->PTRACE_REG_SI << endl
234       << REG_STR( PTRACE_REG_CS ) ": " << (void*)regs->PTRACE_REG_CS
235       << REG_STR( PTRACE_REG_DS ) ": " << (void*)regs->PTRACE_REG_DS
236       << REG_STR( PTRACE_REG_ES ) ": " << (void*)regs->PTRACE_REG_ES
237       << REG_STR( PTRACE_REG_FS ) ": " << (void*)regs->PTRACE_REG_FS
238       << REG_STR( PTRACE_REG_GS ) ": " << (void*)regs->PTRACE_REG_GS
239       << REG_STR( PTRACE_REG_SS ) ": " << (void*)regs->PTRACE_REG_SS << endl
240       << REG_STR( PTRACE_REG_IP ) ": " << (void*)regs->PTRACE_REG_IP
241       << REG_STR( PTRACE_REG_SP ) ": " << (void*)regs->PTRACE_REG_SP
242       << REG_STR( PTRACE_REG_BP ) ": " << (void*)regs->PTRACE_REG_BP << endl
243       << REG_STR( PTRACE_REG_ORIG_AX ) ": " << (void*)regs->PTRACE_REG_ORIG_AX
244       << REG_STR( PTRACE_REG_FLAGS ) ": " << (void*)regs->PTRACE_REG_FLAGS << endl;
245 }
246
247
248 bool dyn_lwp::restoreRegisters_(const struct dyn_saved_regs &regs, bool includeFP) {
249    // Cycle through all registers, writing each from the
250    // buffer with ptrace(PTRACE_POKEUSER ...
251
252    bool retVal = true;
253    int ptrace_errno = 0;
254
255
256    assert(get_lwp_id() != 0);
257    if( DBI_ptrace( PTRACE_SETREGS, get_lwp_id(), 0,(long)&(regs.gprs), 
258             &ptrace_errno, proc_->getAddressWidth(),  
259             __FILE__, __LINE__ ) )
260    {
261       perror("dyn_lwp::restoreRegisters PTRACE_SETREGS" );
262       retVal = false;
263    }
264
265    if (includeFP) {
266       if( DBI_ptrace( PTRACE_SETFPREGS, get_lwp_id(), 0, (long)&(regs.fprs), 
267                &ptrace_errno, proc_->getAddressWidth(),  
268                __FILE__, __LINE__))
269       {
270          perror("dyn_lwp::restoreRegisters PTRACE_SETFPREGS" );
271          retVal = false;
272       }
273    }
274    return retVal;
275 }
276
277 // getActiveFrame(): populate Frame object using toplevel frame
278 Frame dyn_lwp::getActiveFrame()
279 {
280    if(status() == running) {
281       fprintf(stderr, "%s[%d][%s]:  FIXME\n", __FILE__, __LINE__, 
282             getThreadStr(getExecThreadID()));
283       cerr << "    performance problem in call to dyn_lwp::getActiveFrame\n"
284          << "       successive pauses and continues with ptrace calls\n";
285    }
286
287    Address pc, fp, sp;
288
289    int ptrace_errno = 0;
290    fp = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(), P_offsetof(struct user_regs_struct, PTRACE_REG_BP), 0, &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__);
291    if (ptrace_errno) return Frame();
292
293    pc = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(), P_offsetof(struct user_regs_struct, PTRACE_REG_IP), 0, &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__);
294    if (ptrace_errno) return Frame();
295
296    sp = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(), P_offsetof(struct user_regs_struct, PTRACE_REG_SP), 0, &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__);
297    if (ptrace_errno) return Frame();
298
299    dbi_printf("%s[%d]:  GET ACTIVE FRAME (pc = %p, sp = %p, fp = %p\n", 
300          FILE__, __LINE__, pc, sp, fp);
301
302    return Frame(pc, fp, sp, proc_->getPid(), proc_, NULL, this, true);
303 }
304
305 bool process::loadDYNINSTlibCleanup(dyn_lwp *trappingLWP)
306 {
307    // rewrite original instructions in the text segment we use for 
308    // the inferiorRPC - naim
309    unsigned count = sizeof(savedCodeBuffer);
310
311    Address codeBase = findFunctionToHijack(this);
312    assert(codeBase);
313
314    writeDataSpace((void *)codeBase, count, (char *)savedCodeBuffer);
315
316    // restore registers
317    assert(savedRegs != NULL);
318    trappingLWP->restoreRegisters(*savedRegs);
319
320    delete savedRegs;
321    savedRegs = NULL;
322    return true;
323 }
324
325 bool process::handleTrapAtEntryPointOfMain(dyn_lwp *trappingLWP)
326 {
327    assert(main_brk_addr);
328    assert(trappingLWP);
329    // restore original instruction 
330    // Use this for the size -- make sure that we're using the same
331    // insn in both places. Or give savedCodeBuffer a size twin.
332
333    if (!writeDataSpace((void *)main_brk_addr, sizeof(savedCodeBuffer), (char *)savedCodeBuffer))
334       return false;
335
336    if (! trappingLWP->changePC(main_brk_addr,NULL))
337    {
338       logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
339       assert(0);
340    }
341
342    main_brk_addr = 0;
343    return true;
344 }
345
346 bool process::insertTrapAtEntryPointOfMain()
347 {
348
349    int_function *f_main = 0;
350    pdvector<int_function *> funcs;
351    //first check a.out for function symbol   
352    bool res = findFuncsByPretty("main", funcs);
353    if (!res)
354    {
355       logLine( "a.out has no main function. checking for PLT entry\n" );
356       //we have not found a "main" check if we have a plt entry
357       res = findFuncsByPretty( "DYNINST_pltMain", funcs );
358
359       if (!res) {
360          logLine( "no PLT entry for main found\n" );
361          return false;
362       }       
363    }
364
365    if( funcs.size() > 1 ) {
366       cerr << __FILE__ << __LINE__ 
367          << ": found more than one main! using the first" << endl;
368    }
369    f_main = funcs[0];
370    assert(f_main);
371    Address addr = f_main->getAddress();
372
373    // and now, insert trap
374    // For some reason, using a trap breaks but using an illegal works. Anyone 
375    // have any idea?
376    // It looks like the trap PC is actual PC + 1...
377    // This is ugly, but we'll have the "check if this was entry of main" function
378    // check main_brk_addr or main_brk_addr + 1...
379    startup_printf("%s[%d]: Saving %d bytes from entry of main of %d...\n", 
380          FILE__, __LINE__, sizeof(savedCodeBuffer), getPid());
381
382    // save original instruction first
383    if (!readDataSpace((void *)addr, sizeof(savedCodeBuffer), savedCodeBuffer, true)) {
384       fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
385       fprintf(stderr, "%s[%d][%s]:  failing insertTrapAtEntryPointOfMain\n",
386             __FILE__, __LINE__, getThreadStr(getExecThreadID()));
387       fprintf(stderr, "Failed to read at address 0x%lx\n", addr);
388       return false;
389    }
390
391    codeGen gen(1);
392    instruction::generateTrap(gen);
393
394    if (!writeDataSpace((void *)addr, gen.used(), gen.start_ptr())) {
395       fprintf(stderr, "%s[%d][%s]:  failing insertTrapAtEntryPointOfMain\n",
396             __FILE__, __LINE__, getThreadStr(getExecThreadID()));
397       return false;
398    }
399
400    main_brk_addr = addr;
401
402    signal_printf("Added trap at entry of main, address 0x%x\n", main_brk_addr);
403    return true;
404 }
405
406 #if defined(arch_x86_64)
407
408 bool process::getSysCallParameters(dyn_saved_regs *regs, long *params, int numparams) 
409 {
410    if (getAddressWidth() == 4) { // 32 bit mutatee
411    } else { // 64 bit mutatee, have to use ifdef, otherwise it won't
412       // compile on a 32 bit machine
413       if (numparams > 0) {
414          params[0] = regs->gprs.rdi;
415       }
416       if (numparams > 1) {
417          params[1] = regs->gprs.rsi;
418       }
419       if (numparams > 2) {
420          params[2] = regs->gprs.rdx;
421       }
422       if (numparams > 3) {
423          params[3] = regs->gprs.r8;
424       }
425       if (numparams > 4) {
426          params[4] = regs->gprs.r9;
427       }
428       if (numparams > 5) {
429          params[5] = regs->gprs.r10;
430       }
431       for (int i=6; i < numparams; i++) {
432          if (!readDataSpace((void*)regs->gprs.rsp, getAddressWidth(), 
433                   (void*)(params + i * getAddressWidth()), true)) {
434             return false;
435          }
436       }
437    }
438    return true;
439 }
440
441 int process::getSysCallNumber(dyn_saved_regs *regs) {
442    return regs->gprs.orig_rax;
443 }
444
445 long process::getSysCallReturnValue(dyn_saved_regs *regs) {
446    return regs->gprs.rax;
447 }
448
449 Address process::getSysCallProgramCounter(dyn_saved_regs *regs) {
450    return regs->gprs.rip;
451 }
452
453 bool process::isMmapSysCall(int callnum) {
454    if (getAddressWidth() == 4) {
455       startup_printf("CALLNUM=%d\n",callnum);
456    }
457    return callnum == SYS_mmap;
458 }
459
460 Offset process::getMmapLength(int, dyn_saved_regs *regs) {
461    return (Offset) regs->gprs.rsi;
462 }
463
464 Address process::getLibcStartMainParam(dyn_lwp *trappingLWP) {
465    Address mainaddr = 0;
466    dyn_saved_regs regs;
467    trappingLWP->getRegisters(&regs);
468    if (getAddressWidth() == 4) { // 32 bit mutatee
469       if (!readDataSpace((void*)(regs.gprs.rsp + getAddressWidth()),
470                getAddressWidth(), (void*)&mainaddr,true)) {
471          fprintf(stderr,"[%s][%d]: failed readDataSpace\n", __FILE__,__LINE__); 
472       }
473    } else { // 64 bit mutatee
474       mainaddr = regs.gprs.rdi;
475    }
476    return mainaddr;
477 }
478 // 64 bit architecture
479 #else 
480 // 32 bit architecture
481 bool process::getSysCallParameters(dyn_saved_regs *regs, 
482       long *params, int numparams) {
483    if (numparams > 0) {
484       params[0] = regs->gprs.ebx;
485    }
486    if (numparams > 1) {
487       params[1] = regs->gprs.ecx;
488    }
489    if (numparams > 2) {
490       params[2] = regs->gprs.edx;
491    }
492    if (numparams > 3) {
493       params[3] = regs->gprs.esi;
494    }
495    if (numparams > 4) {
496       params[4] = regs->gprs.edi;
497    }
498    if (numparams > 5) {
499       params[5] = regs->gprs.ebp;
500    }
501    for (int i=6; i < numparams; i++) {
502       if (!readDataSpace((void*)regs->gprs.esp, getAddressWidth(), 
503                (void*)(params + i * getAddressWidth()), true)) {
504          return false;
505       }
506    }
507    return true;
508 }
509
510 int process::getSysCallNumber(dyn_saved_regs *regs) 
511 {
512    return regs->gprs.orig_eax;
513 }
514
515 long process::getSysCallReturnValue(dyn_saved_regs *regs) 
516 {
517    return regs->gprs.eax;
518 }
519
520 Address process::getSysCallProgramCounter(dyn_saved_regs *regs) 
521 {
522    return regs->gprs.eip;
523 }
524
525 bool process::isMmapSysCall(int callnum) {
526    return (callnum == SYS_mmap || callnum == SYS_mmap2);
527 }
528
529 Offset process::getMmapLength(int callnum, dyn_saved_regs *regs) 
530 {
531    if (callnum == SYS_mmap) {
532       Offset length;
533       readDataSpace((void*)(regs->gprs.ebx + getAddressWidth()),
534             getAddressWidth(), (void*)&length, true);
535       return length;
536    }
537    else {
538       return (Offset) regs->gprs.ecx;
539    }
540 }
541
542 Address process::getLibcStartMainParam(dyn_lwp *trappingLWP) 
543 {
544    dyn_saved_regs regs;
545    trappingLWP->getRegisters(&regs);
546    Address mainaddr;
547    if (!readDataSpace((void*)(regs.gprs.esp + getAddressWidth()),
548             getAddressWidth(), (void*)&mainaddr,true)) {
549       fprintf(stderr,"[%s][%d]: failed readDataSpace\n", __FILE__,__LINE__); 
550    }
551    return mainaddr;
552
553
554 #endif
555
556 void process::setTraceSysCalls(bool traceSys) 
557 {
558    traceSysCalls_ = traceSys;
559 }
560
561 void process::setTraceState(traceState_t state) 
562 {
563    traceState_ = state;
564 }
565
566 /* For cases in which we are unable to locate the mutatee's main function
567  * via our normal findMain heuristics, we resort to tracing system calls
568  * looking for libc to be loaded.  Here we decode the different system
569  * that we see during process startup. 
570  */
571 bool process::decodeStartupSysCalls(EventRecord &ev) 
572 {
573    // set up parameters & variables, which is platform dependent
574    const int NUMPARAMS = 6;
575    dyn_saved_regs regs;
576    ev.lwp->getRegisters(&regs);
577    long params[NUMPARAMS];
578    int callnum = getSysCallNumber(&regs);
579    long retval = getSysCallReturnValue(&regs);
580    Address programCounter = getSysCallProgramCounter(&regs);
581    getSysCallParameters(&regs, params, NUMPARAMS);
582
583    int traceerr = 0;
584    ev.type = evtNullEvent;
585    int addrWidth=getAddressWidth();
586
587    startup_printf("%s[%d]: decodeStartupSysCalls got tracestate=%d callnum=%d PC=0x%lx\n", 
588          FILE__, __LINE__, getTraceState(), callnum, programCounter);
589
590    // mmap syscall (there are multiple mmap syscalls on some platforms)
591    // store the start and end addresses of the region so that we can later
592    // determine which of the regions contains main
593    if (isMmapSysCall(callnum)) {
594       if (retval == -ENOSYS) { // grab the mmap region end address
595          mappedRegionEnd.push_back(getMmapLength(callnum, &regs));
596       } else { // the return value of mmap is the region's start address
597          mappedRegionStart.push_back(retval);
598          // turn the OFFSET we put into mappedRegionEnd into an absolute Address
599          mappedRegionEnd[mappedRegionEnd.size()-1] 
600             = mappedRegionEnd[mappedRegionEnd.size()-1] + retval;
601          startup_printf("%s[%d]: traced mmap syscall for region[0x%x 0x%x]\n",
602                __FILE__,__LINE__,
603                (int)mappedRegionStart[mappedRegionStart.size()-1],
604                (int)mappedRegionEnd[mappedRegionEnd.size()-1]);
605       }
606    }
607    // munmap: we also keep track of memory regions that are removed
608    else if (callnum==SYS_munmap && retval == -ENOSYS) { 
609       Address regionStart = params[0];
610       munmappedRegions.push_back(regionStart);
611       startup_printf("%s[%d]: traced munmap syscall for region at 0x%x\n",
612             __FILE__,__LINE__, (int)regionStart);
613    }
614
615    // switch on state, this is an automaton
616    switch (getTraceState()) { 
617       case libcOpenCall_ts: // wait for call to open libc.so
618          if(callnum == SYS_open) { // open syscall
619             char *oneword = (char*) malloc(addrWidth);
620             char *pathbuffer = (char*) malloc(256);
621             char *ptr = pathbuffer;
622             int lastchar = addrWidth;
623             Address stringAddr = params[0];
624             // recover the opened path from the call's arguments
625             do {
626                if (!readDataSpace((void*)stringAddr, addrWidth,
627                         (void*)oneword,true)) {
628                   fprintf(stderr,"%s[%d]: failed readDataSpace\n",FILE__,__LINE__ );
629                   return false;
630                }
631                strncpy(ptr, oneword, addrWidth);
632                stringAddr += addrWidth; 
633                ptr += addrWidth;
634                for (int idx=0; idx < addrWidth; idx++) {
635                   if (oneword[idx] == '\0') {
636                      lastchar = idx;
637                   }
638                }
639             }while (ptr - pathbuffer < 256 && lastchar == addrWidth);
640             pathbuffer[255] = '\0';
641             // if the path matches libc.so, transition state
642             if (strstr(pathbuffer, "libc.so")) {
643                setTraceState(libcOpenRet_ts);
644             }
645             free(pathbuffer);
646             free(oneword);
647          } // end if syscall to open
648          break;
649       case libcOpenRet_ts: // Save file-handle returned by open
650          // syscall on libc
651          if(callnum == SYS_open) { // call to open
652             if (retval >= 0) {
653                libcHandle_ = retval; 
654                setTraceState(libcClose_ts);
655             }
656             else {// open syscall was unsuccessful, revert to previous state
657                setTraceState(libcOpenCall_ts);
658             }
659          }
660          break;
661       case libcClose_ts:  //find close syscall matching libc open 
662          if (callnum == SYS_close && retval == -ENOSYS) {
663             int fd = params[0];
664             if (traceerr != 0) { 
665                fprintf(stderr,"[%s][%d]: ptrace err here\n", __FILE__,__LINE__); 
666             }
667             if (fd == libcHandle_) { // found close
668                setTraceState(instrumentLibc_ts); 
669                setBootstrapState(libcLoaded_bs);
670                ev.type = evtLibcLoaded;
671             }
672          }
673          break;
674       case instrumentLibc_ts: // results in handling of trap in startmain 
675          if (abs((long)getlibcstartmain_brk_addr() -(long)programCounter) <= 1) {
676             setTraceState(done_ts);
677             setTraceSysCalls(false);
678             ev.type = evtLibcTrap;
679          }
680          else {
681             return false;
682          }
683          break;
684       default:
685          fprintf(stderr,"[%s][%d] Internal error, should not reach this point\n",
686                __FILE__,__LINE__);
687          return false;
688    }// end switch statement
689    return true;
690 }// end decodeStartupSysCalls
691
692 /* Find libc and add it as a shared object
693  * Search for __libc_start_main
694  * Save old code at beginning of __libc_start_main
695  * Insert trap
696  * Signal thread to continue
697  */
698 bool process::instrumentLibcStartMain() 
699 {
700     unsigned int maps_size =0;
701     map_entries *maps = getLinuxMaps(getPid(), maps_size);
702     unsigned int libcIdx=0;
703     while (libcIdx < maps_size &&
704            ! (strstr(maps[libcIdx].path,"/libc")
705               && strstr(maps[libcIdx].path,".so"))) {
706        libcIdx++;
707     }
708     assert(libcIdx != maps_size);
709     //KEVINTODO: address code and data are not always 0,0: need to fix this
710     fileDescriptor libcFD = fileDescriptor(maps[libcIdx].path,0,0,true);
711     mapped_object *libc = mapped_object::createMappedObject(libcFD, this);
712     addASharedObject(libc);
713
714     // find __libc_startmain
715     const pdvector<int_function*> *funcs;
716     funcs = libc->findFuncVectorByPretty("__libc_start_main");
717     if(funcs->size() == 0 || (*funcs)[0] == NULL) {
718         logLine( "Couldn't find __libc_start_main\n");
719         return false;
720     } else if (funcs->size() > 1) {
721        startup_printf("[%s:%u] - Found %d functions called __libc_start_main, weird\n",
722                       FILE__, __LINE__, funcs->size());
723     }
724     if (!(*funcs)[0]->isInstrumentable()) {
725         logLine( "__libc_start_main is not instrumentable\n");
726         return false;
727     }
728     Address addr = (*funcs)[0]->getAddress();
729     startup_printf("%s[%d]: Instrumenting libc.so:__libc_start_main() at 0x%x\n", 
730                    FILE__, __LINE__, (int)addr);
731
732     // save original code at beginning of function
733     if (!readDataSpace((void *)addr, sizeof(savedCodeBuffer),savedCodeBuffer,true)) {
734         fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
735         fprintf(stderr, "%s[%d][%s]:  failing instrumentLibcStartMain\n",
736             __FILE__, __LINE__, getThreadStr(getExecThreadID()));
737       fprintf(stderr, "Failed to read at address 0x%lx\n", addr);
738       return false;
739    }
740    startup_printf("%s[%d]: Saved %d bytes from entry of __libc_start_main\n", 
741          FILE__, __LINE__, sizeof(savedCodeBuffer));
742    // insert trap
743    codeGen gen(1);
744    instruction::generateTrap(gen);
745    if (!writeDataSpace((void *)addr, gen.used(), gen.start_ptr())) {
746       fprintf(stderr, "%s[%d][%s]:  failing instrumentLibcStartMain\n",
747             __FILE__, __LINE__, getThreadStr(getExecThreadID()));
748       return false;
749    }
750    libcstartmain_brk_addr = addr;
751    continueProc(); // signal process to continue
752    return true;
753 }// end instrumentLibcStartMain
754
755
756 /* Read parameters to startmain including the address of main.
757  * See if there's an existing mapped object that contains the address of
758  *   main, which we'll call a_out, and set to be a.out for the process
759  * Restore original instruction in the libc library
760  * Call insertTrapAtMain
761  */
762 bool process::handleTrapAtLibcStartMain(dyn_lwp *trappingLWP)
763 {
764     assert(libcstartmain_brk_addr);
765     assert(trappingLWP);
766
767     // Read the parameters from the call to libcStartMain
768     Address mainaddr = getLibcStartMainParam(trappingLWP);
769     mapped_object *a_out = findObject(mainaddr);
770
771     char namebuf[64];
772     Address regionStart = 0;
773     Address regionEnd = 0;
774     // there might not be an object that corresponds to the a_out
775     if (a_out == NULL) {
776         // determine confines of region that encloses main, search from
777         // end to get most recent mmap of an enclosing region
778         int idx =  (int)mappedRegionStart.size()-1;
779         while (idx >= 0  && 
780                !(mappedRegionStart[idx] <= mainaddr 
781                  && mainaddr <= mappedRegionEnd[idx])) {
782             idx--;
783         }
784         if (idx < 0) {
785             fprintf(stderr,"%s[%d] No valid memory region seems to contain "
786                     "the address of main=0x%x\n",__FILE__,__LINE__, 
787                     (int)mainaddr);
788             return false;
789         }
790         regionStart = mappedRegionStart[idx];
791         regionEnd = mappedRegionEnd[idx];
792         startup_printf("main(0x%x) is in region [0x%X 0x%X]\n", 
793                        (int)mainaddr, (int)regionStart, (int)regionEnd);
794
795         // found the right region, copy its contents to a temp file
796         void *regionBuf = malloc(regionEnd - regionStart);
797         if (!readDataSpace((void*)regionStart, regionEnd-regionStart, 
798                           regionBuf, false)) {
799             fprintf(stderr, "%s[%d]: Failed to read from region [%X %X]\n",
800                        __FILE__, __LINE__,(int)regionStart, 
801                        (int)regionEnd);
802         }
803         // Make sure bytes 12-15 of magic header are set to 0 (for x86-64 bit)
804         ((int*)regionBuf)[3] = 0;
805         // We have no section information, so don't try to point to it
806         ((int*)regionBuf)[10] = 0;
807
808         snprintf(namebuf, 64, "/tmp/MemRegion_%X_%X", 
809                  (int)regionStart, (int)regionEnd);
810         namebuf[63]='\0';
811         FILE *regionFD = fopen(namebuf, "w");
812         assert(regionFD != NULL);
813         fwrite(regionBuf, 1, regionEnd-regionStart, regionFD);
814         fclose(regionFD);
815         free(regionBuf);
816         startup_printf("%s[%d]: Read region [%X %X] into temp file %s\n",
817                        __FILE__, __LINE__,(int)regionStart, 
818                        (int)regionEnd, namebuf);
819
820         //KEVINTODO: address code and data are not always 0,0: need to fix this
821         // create a fileDescriptor and a new mapped_object for the region
822         // create it as though it were a shared object
823         fileDescriptor fdesc = fileDescriptor(namebuf, 0, 0, true);
824         a_out = mapped_object::createMappedObject(fdesc, this);
825
826         // There is no function for adding an a.out, so we'll call
827         // addASharedObject, and switch the old a.out to be this one.
828         // a.out is always the first object in the mapped_objects
829         // vector, our new mapped_object should be at or near the end.
830         addASharedObject(a_out);
831         idx = mapped_objects.size() -1;
832         while (mapped_objects[idx] != a_out && idx >= 0) {
833             idx--;
834         }
835         assert(idx >= 0);
836         mapped_objects[idx] = mapped_objects[0];
837         mapped_objects[0] = a_out;
838         ((fileDescriptor)(a_out->getFileDesc())).setIsShared(false);
839     }
840     else {// (a_out != NULL)
841         regionStart = a_out->getFileDesc().loadAddr();
842         regionEnd = regionStart + a_out->imageSize();
843     }
844
845     // if gap parsing is on, check for a function at mainaddr, rename
846     // it to "main" and set main_function to its int_function
847     int_function* mainfunc = NULL;
848     if (a_out->parse_img()->parseGaps()) {
849         a_out->analyze();
850         snprintf(namebuf,64,"gap_%lx", (long)mainaddr);
851         int_function* mainfunc = findOnlyOneFunction(namebuf,a_out->fileName());
852         if (mainfunc) {
853             mainfunc->addSymTabName("main", true);
854             mainfunc->addPrettyName("main", true);
855             main_function = mainfunc;
856             startup_printf("found main via gap parsing at %x in mapped_obj [%x %x]\n",
857                            (int)main_function->getAddress(),
858                            (int)a_out->getFileDesc().loadAddr(),
859                            (int)(a_out->getFileDesc().loadAddr() + a_out->imageSize()));
860         }
861     }
862     // parse the binary with "main" as a function location
863     if (!mainfunc) {
864         startup_printf("Parsing main at 0x%x in mapped object [%x %x]"
865                        " which is its location according to __libc_start_main \n",
866                 (int)mainaddr,
867                 (int)a_out->getFileDesc().loadAddr(),
868                 (int)(a_out->getFileDesc().loadAddr() + a_out->imageSize()));
869         // add function stub and parsed object
870         a_out->parse_img()->addFunctionStub(mainaddr, "main");
871         a_out->analyze(); 
872     }
873
874    // Restore __libc_start_main to its original state
875    if (!writeDataSpace((void *)libcstartmain_brk_addr, 
876             sizeof(savedCodeBuffer), 
877             (char *)savedCodeBuffer)) {
878       fprintf(stderr, "%s[%d]: Failed to restore code in libcstartmain at 0x%X\n",
879             __FILE__, __LINE__,(int)libcstartmain_brk_addr);
880       return false;
881    }
882    if (! trappingLWP->changePC(libcstartmain_brk_addr,NULL)) {
883       logLine("WARNING: in handleTrapAtLibcStartMain: "
884             "changePC failed in handleTrapAtLibcStartmain\n");
885       assert(0);
886    }
887    libcstartmain_brk_addr = 0;
888    // now let insertTrapAtEntryPointOfMain insert the trap at main
889    return insertTrapAtEntryPointOfMain();
890 }// handleTrapAtLibcStartmain
891
892
893 extern bool isFramePush(instruction &i);
894
895 /**
896  * Signal handler return points can be found in the vsyscall page.
897  * this function reads the symbol information that describes these
898  * points out of the vsyscall page.
899  **/
900 #define VSYS_SIGRETURN_NAME "_sigreturn"
901 static void getVSyscallSignalSyms(char *buffer, unsigned dso_size, process *p)
902 {
903    Elf_Scn *sec;
904    Elf32_Shdr *shdr;
905    Elf32_Ehdr *ehdr;
906    Elf32_Sym *syms;
907    unsigned i;
908    size_t dynstr = 0, shstr;
909    
910    Elf *elf = elf_memory(buffer, dso_size);
911    if (elf == NULL)
912       goto err_handler;
913    ehdr = elf32_getehdr(elf);
914    if (ehdr == NULL)
915       goto err_handler;
916    
917    //Get string section indexes
918    shstr = ehdr->e_shstrndx;
919    for (i = 0; i < ehdr->e_shnum; i++)
920    {
921       shdr = elf32_getshdr(elf_getscn(elf, i));
922       if (shdr != NULL && shdr->sh_type == SHT_STRTAB &&        
923           strcmp(elf_strptr(elf, shstr, shdr->sh_name), ".dynstr") == 0)
924       {
925          dynstr = i;
926          break;
927       }
928    }
929    
930    //For each section..
931    for (sec = elf_nextscn(elf, NULL); sec != NULL; sec = elf_nextscn(elf, sec))
932    {
933       shdr = elf32_getshdr(sec);
934       if (shdr == NULL) goto err_handler;
935       if (!p->getVsyscallText() && (shdr->sh_flags & SHF_EXECINSTR)) {
936          p->setVsyscallText(shdr->sh_addr);
937       }
938       if (shdr->sh_type == SHT_DYNSYM)
939       {
940          syms = (Elf32_Sym *) elf_getdata(sec, NULL)->d_buf;
941          //For each symbol ..
942          for (i = 0; i < (shdr->sh_size / sizeof(Elf32_Sym)); i++)
943          {
944             if ((syms[i].st_info & 0xf) == STT_FUNC)
945             {
946                //Check if this is a function symbol
947                char *name = elf_strptr(elf, dynstr, syms[i].st_name);
948                if (strstr(name, VSYS_SIGRETURN_NAME) != NULL)
949                {            
950                   // Aggravating... FC3 has these as offsets from the entry
951                   // of the vsyscall page. Others have these as absolutes.
952                   // We hates them, my precioussss....
953                   Address signal_addr = syms[i].st_value;
954                   if (signal_addr < p->getVsyscallEnd() - p->getVsyscallStart()) {
955                      p->addSignalHandler(syms[i].st_value + 
956                                          p->getVsyscallStart(), 4);
957                   }
958                   else if (signal_addr < p->getVsyscallStart() ||
959                            signal_addr >= p->getVsyscallEnd()) {
960                      //FC-9 moved the vsyscall page, but didn't update its debug
961                      // info or symbols from some hardcoded values.  Fix up the
962                      // bad signal values.
963                      p->addSignalHandler(syms[i].st_value - 0xffffe000 +
964                                          p->getVsyscallStart(), 4);
965                   }
966                   else 
967                      p->addSignalHandler(syms[i].st_value, 4);
968                } 
969             }
970          }
971       }
972    }
973    
974    elf_end(elf);
975    return;
976
977 err_handler:
978    if (elf != NULL)
979       elf_end(elf);
980 }
981
982 static volatile int segfaulted = 0;
983 static void catchSigSegV(int) {
984    segfaulted = 1;
985 }
986
987 static char *execVsyscallFetch(process *p, char *buffer) {
988    //We can't read the Vsyscall page out of the process addr
989    // space do to a kernel bug.  However, the versions of the
990    // kernel with this bug don't move the vsyscall page between
991    // processes, so let's read it out of the mutator's.
992    //Latter versions of the kernel do move the page between
993    // processes, which makes our read attempt seg fault.  Let's
994    // install a handler to be safe.
995    volatile char *start;
996    unsigned size;
997    sighandler_t old_segv;
998
999    segfaulted = 0;
1000    start = (char *) p->getVsyscallStart();
1001    size = p->getVsyscallEnd() - p->getVsyscallStart();
1002
1003    //Install SegSegV handler.
1004    old_segv = signal(SIGSEGV, catchSigSegV);
1005
1006    //Copy buffer
1007    for (unsigned i=0; i<size; i++) {
1008       buffer[i] = start[i];
1009       if (segfaulted) 
1010          break;
1011    }
1012
1013    //Restore handler.
1014    signal(SIGSEGV, old_segv);
1015    if (segfaulted)
1016       return NULL;
1017    return buffer;
1018 }
1019
1020 static bool isVsyscallData(char *buffer, int dso_size) {
1021    //Start with an elf header?
1022    if (dso_size < 4)
1023       return false;
1024    return (buffer[0] == 0x7f && buffer[1] == 'E' && buffer[2] == 'L' &&
1025            buffer[3] == 'F');
1026    
1027 }
1028
1029
1030 void calcVSyscallFrame(process *p)
1031 {
1032   unsigned dso_size;
1033   char *buffer;
1034
1035   /**
1036    * If we've already calculated and cached the DSO information then 
1037    * just return.
1038    **/
1039   if (p->getVsyscallObject())
1040      return;
1041   
1042
1043   if (p->getAddressWidth() == 8) {
1044      // FIXME: HACK to disable vsyscall page for AMD64, for now.
1045      //  Reading the VSyscall data on ginger seems to trigger a
1046      //  kernel panic.
1047      p->setVsyscallRange(0x1000, 0x0);
1048      return;
1049   }
1050
1051   /**
1052    * Read the location of the vsyscall page from /proc/.
1053    **/
1054   p->readAuxvInfo();
1055   if (p->getVsyscallStatus() != vsys_found) {
1056      p->setVsyscallRange(0x0, 0x0);
1057      return;
1058   }
1059   
1060   /**
1061    * Read the vsyscall page out of process memory.
1062    **/
1063   dso_size = p->getVsyscallEnd() - p->getVsyscallStart();
1064   buffer = (char *) calloc(1, dso_size);
1065   assert(buffer);
1066   if (!p->readDataSpace((caddr_t)p->getVsyscallStart(), dso_size, buffer,false))     
1067   {
1068      int major, minor, sub;
1069      get_linux_version(major, minor, sub);
1070      if (major == 2 && minor == 6 && sub <= 2 && sub >= 0) {
1071         //Linux 2.6.0 - Linux 2.6.2 has a  bug where ptrace 
1072         // can't read from the DSO.  The process can read the memory, 
1073         // it's just ptrace that's acting stubborn.
1074         if (!execVsyscallFetch(p, buffer))
1075         {
1076            p->setVsyscallStatus(vsys_notfound);
1077            return;
1078         }
1079      }
1080   }
1081
1082   if (!isVsyscallData(buffer, dso_size)) {
1083      p->setVsyscallRange(0x0, 0x0);
1084      p->setVsyscallStatus(vsys_notfound);
1085      return;     
1086   }
1087   getVSyscallSignalSyms(buffer, dso_size, p);
1088
1089   Symtab *obj;
1090   bool result = Symtab::openFile(obj, buffer, dso_size);
1091   if (result)
1092      p->setVsyscallObject(obj);
1093   return;
1094 }
1095
1096 bool Frame::setPC(Address newpc) {
1097    if (!pcAddr_)
1098    {
1099        //fprintf(stderr, "[%s:%u] - Frame::setPC aborted", __FILE__, __LINE__);
1100       return false;
1101    }
1102
1103    //fprintf(stderr, "[%s:%u] - Frame::setPC setting %x to %x",
1104    //__FILE__, __LINE__, pcAddr_, newpc);
1105    getProc()->writeDataSpace((void*)pcAddr_, sizeof(Address), &newpc);
1106    pc_ = newpc;
1107    range_ = NULL;
1108
1109    return false;
1110 }
1111
1112 // Laziness here: this func is used by the iRPC code
1113 // to get result registers. Don't use it other than that. 
1114
1115 Address dyn_lwp::readRegister(Register /*reg*/) {
1116    // On x86, the result is always stashed in %EAX
1117    if(status() == running) {
1118       cerr << "    performance problem in call to dyn_lwp::readRegister\n"
1119            << "       successive pauses and continues with ptrace calls\n";
1120    }
1121
1122    int ptrace_errno = 0;
1123    Address ret = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(), P_offsetof(struct user_regs_struct, PTRACE_REG_AX), 0,
1124                         &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__);
1125    return ret;
1126 }
1127
1128
1129 void print_read_error_info(const relocationEntry entry, 
1130       int_function *&target_pdf, Address base_addr) {
1131
1132     sprintf(errorLine, "  entry      : target_addr 0x%x\n",
1133             (unsigned)entry.target_addr());
1134     logLine(errorLine);
1135     sprintf(errorLine, "               rel_addr 0x%x\n", (unsigned)entry.rel_addr());
1136     logLine(errorLine);
1137     sprintf(errorLine, "               name %s\n", (entry.name()).c_str());
1138     logLine(errorLine);
1139
1140     if (target_pdf) {
1141       sprintf(errorLine, "  target_pdf : symTabName %s\n",
1142               (target_pdf->symTabName()).c_str());
1143       logLine(errorLine);    
1144       sprintf(errorLine , "              prettyName %s\n",
1145               (target_pdf->symTabName()).c_str());
1146       logLine(errorLine);
1147       /*
1148       // Size bad. <smack>
1149       sprintf(errorLine , "              size %i\n",
1150       target_pdf->getSize());
1151       logLine(errorLine);
1152       */
1153       sprintf(errorLine , "              addr 0x%x\n",
1154               (unsigned)target_pdf->getAddress());
1155       logLine(errorLine);
1156     }
1157     sprintf(errorLine, "  base_addr  0x%x\n", (unsigned)base_addr);
1158     logLine(errorLine);
1159 }
1160
1161 // hasBeenBound: returns true if the runtime linker has bound the
1162 // function symbol corresponding to the relocation entry in at the address
1163 // specified by entry and base_addr.  If it has been bound, then the callee 
1164 // function is returned in "target_pdf", else it returns false.
1165 bool process::hasBeenBound(const relocationEntry &entry, 
1166                            int_function *&target_pdf, Address base_addr) {
1167
1168     if (status() == exited) return false;
1169
1170     // if the relocationEntry has not been bound yet, then the value
1171     // at rel_addr is the address of the instruction immediately following
1172     // the first instruction in the PLT entry (which is at the target_addr) 
1173     // The PLT entries are never modified, instead they use an indirrect 
1174     // jump to an address stored in the _GLOBAL_OFFSET_TABLE_.  When the 
1175     // function symbol is bound by the runtime linker, it changes the address
1176     // in the _GLOBAL_OFFSET_TABLE_ corresponding to the PLT entry
1177
1178     Address got_entry = entry.rel_addr() + base_addr;
1179     Address bound_addr = 0;
1180     if(!readDataSpace((const void*)got_entry, sizeof(Address), 
1181                         &bound_addr, true)){
1182         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%x, pid=%d\n (readDataSpace returns 0)",(unsigned)got_entry,getPid());
1183         logLine(errorLine);
1184         print_read_error_info(entry, target_pdf, base_addr);
1185         return false;
1186     }
1187
1188     if( !( bound_addr == (entry.target_addr()+6+base_addr)) ) {
1189         // the callee function has been bound by the runtime linker
1190         // find the function and return it
1191         target_pdf = findFuncByAddr(bound_addr);
1192         if(!target_pdf){
1193             return false;
1194         }
1195         return true;    
1196     }
1197     return false;
1198 }
1199
1200 bool AddressSpace::getDyninstRTLibName() {
1201    startup_printf("dyninstRT_name: %s\n", dyninstRT_name.c_str());
1202     if (dyninstRT_name.length() == 0) {
1203         // Get env variable
1204         if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
1205             dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
1206         }
1207         else {
1208            std::string msg;
1209            process *proc;
1210            if ((proc = dynamic_cast<process *>(this)) != NULL) {
1211               msg = std::string("Environment variable ") +
1212                  std::string("DYNINSTAPI_RT_LIB") +
1213                  std::string(" has not been defined for process ") +
1214                  utos(proc->getPid());
1215            }
1216            else {
1217               msg = std::string("Environment variable ") +
1218                  std::string("DYNINSTAPI_RT_LIB") +
1219                  std::string(" has not been defined");
1220            }           
1221            showErrorCallback(101, msg);
1222            return false;
1223         }
1224     }
1225
1226     // Automatically choose 32-bit library if necessary.
1227     const char *modifier = "_m32";
1228     const char *name = dyninstRT_name.c_str();
1229
1230     const char *split = P_strrchr(name, '/');
1231     if ( !split ) split = name;
1232     split = P_strchr(split, '.');
1233     if ( !split || P_strlen(split) <= 1 ) {
1234         // We should probably print some error here.
1235         // Then, of course, the user will find out soon enough.
1236         startup_printf("Invalid Dyninst RT lib name: %s\n", 
1237                 dyninstRT_name.c_str());
1238         return false;
1239     }
1240
1241     if ( getAddressWidth() == sizeof(void *) || P_strstr(name, modifier) ) {
1242         modifier = "";
1243     }
1244
1245     const char *suffix = split;
1246     if( getAOut()->isStaticExec() ) {
1247         suffix = ".a";
1248     }else{
1249         if( P_strncmp(suffix, ".a", 2) == 0 ) {
1250             // This will be incorrect if the RT library's version changes
1251             suffix = ".so.1";
1252         }
1253     }
1254
1255     dyninstRT_name = std::string(name, split - name) +
1256                      std::string(modifier) +
1257                      std::string(suffix);
1258
1259     startup_printf("Dyninst RT Library name set to '%s'\n",
1260             dyninstRT_name.c_str());
1261
1262     // Check to see if the library given exists.
1263     if (access(dyninstRT_name.c_str(), R_OK)) {
1264         std::string msg = std::string("Runtime library ") + dyninstRT_name
1265         + std::string(" does not exist or cannot be accessed!");
1266         showErrorCallback(101, msg);
1267         return false;
1268     }
1269
1270     return true;
1271 }
1272
1273 bool process::loadDYNINSTlib()
1274 {
1275     pdvector<int_function *> dlopen_funcs;
1276
1277         //  allow user to override default dlopen func names 
1278         //  with env. var
1279
1280         DL_OPEN_FUNC_USER = getenv("DYNINST_DLOPEN_FUNC");
1281
1282         if (DL_OPEN_FUNC_USER)
1283         {
1284                 if (findFuncsByAll(DL_OPEN_FUNC_USER, dlopen_funcs)) 
1285                 {
1286                         bool ok =  loadDYNINSTlib_exported(DL_OPEN_FUNC_USER);
1287
1288                         if (ok) 
1289                                 return true;
1290
1291                         //  else fall through and try the default dlopen names
1292                 } 
1293         }
1294
1295     if (findFuncsByAll(DL_OPEN_FUNC_EXPORTED, dlopen_funcs)) 
1296         {
1297                 return loadDYNINSTlib_exported(DL_OPEN_FUNC_EXPORTED);
1298     } 
1299     else 
1300         {
1301                 return loadDYNINSTlib_hidden();
1302     }
1303 }
1304
1305 // Defined in inst-x86.C...
1306 void emitPushImm(unsigned int imm, unsigned char *&insn); 
1307
1308 bool process::loadDYNINSTlib_hidden() {
1309 #if false && defined(PTRACEDEBUG)
1310   debug_ptrace = true;
1311 #endif
1312   startup_printf("**** LIBC21 dlopen for RT lib\n");
1313   // do_dlopen takes a struct argument. This is as follows:
1314   // const char *libname;
1315   // int mode;
1316   // void *result;
1317   // void *caller_addr
1318   // Now, we have to put this somewhere writable. The idea is to
1319   // put it on the stack....
1320
1321   Address codeBase = findFunctionToHijack(this);
1322
1323   if(!codeBase)
1324   {
1325       startup_cerr << "Couldn't find a point to insert dlopen call" << endl;
1326       return false;
1327   }
1328
1329   startup_printf("(%d) writing in dlopen call at addr %p\n", getPid(), (void *)codeBase);
1330
1331   codeGen scratchCodeBuffer(BYTES_TO_SAVE);
1332
1333   // we need to make a call to dlopen to open our runtime library
1334
1335   // Variables what we're filling in
1336   Address dyninstlib_str_addr = 0;
1337   Address dlopen_call_addr = 0;
1338   Address mprotect_call_addr = 0;
1339
1340   pdvector<int_function *> dlopen_funcs;
1341   if (!findFuncsByAll(DL_OPEN_FUNC_NAME, dlopen_funcs))
1342   {
1343     pdvector<int_function *> dlopen_int_funcs;                                    
1344     // If we can't find the do_dlopen function (because this library
1345     // is stripped, for example), try searching for the internal
1346     // _dl_open function and find the do_dlopen function by examining
1347     // the functions that call it. This depends on the do_dlopen
1348     // function having been parsed (though its name is not known)
1349     // through speculative parsing.
1350     if(!findFuncsByAll(DL_OPEN_FUNC_INTERNAL, dlopen_int_funcs))
1351     {    
1352       startup_printf("Failed to find _dl_open\n");
1353     } 
1354     else
1355     { 
1356       if(dlopen_int_funcs.size() > 1)
1357         {
1358             startup_printf("%s[%d] warning: found %d matches for %s\n",
1359                            __FILE__,__LINE__,dlopen_int_funcs.size(),
1360                            DL_OPEN_FUNC_INTERNAL);
1361         }
1362         dlopen_int_funcs[0]->getStaticCallers(dlopen_funcs);
1363         if(dlopen_funcs.size() > 1)
1364         {
1365             startup_printf("%s[%d] warning: found %d do_dlopen candidates\n",
1366                            __FILE__,__LINE__,dlopen_funcs.size());
1367         }
1368   
1369         if(dlopen_funcs.size() > 0)
1370         {
1371             // give it a name
1372             dlopen_funcs[0]->addSymTabName("do_dlopen",true);
1373         }
1374     }
1375   }
1376
1377     if(dlopen_funcs.size() == 0)
1378     {
1379       startup_cerr << "Couldn't find method to load dynamic library" << endl;
1380       return false;
1381     } 
1382
1383   Address dlopen_addr = dlopen_funcs[0]->getAddress();
1384
1385   assert(dyninstRT_name.length() < BYTES_TO_SAVE);
1386   // We now fill in the scratch code buffer with appropriate data
1387   startup_cerr << "Dyninst RT lib name: " << dyninstRT_name << endl;
1388
1389   dyninstlib_str_addr = codeBase + scratchCodeBuffer.used();
1390   scratchCodeBuffer.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
1391
1392   startup_printf("(%d) dyninst str addr at 0x%x\n", getPid(), dyninstlib_str_addr);
1393
1394   startup_printf("(%d) after copy, %d used\n", getPid(), scratchCodeBuffer.used());
1395
1396
1397 #if defined(bug_syscall_changepc_rewind)
1398   // Reported by SGI, during attach to a process in a system call:
1399
1400   // Insert eight NOP instructions before the actual call to dlopen(). Loading
1401   // the runtime library when the mutatee was in a system call will sometimes
1402   // cause the process to (on IA32 anyway) execute the instruction four bytes
1403   // PREVIOUS to the PC we actually set here. No idea why. Prepending the
1404   // actual dlopen() call with eight NOP instructions insures this doesn't
1405   // really matter. Eight was selected rather than four because I don't know
1406   // if x86-64 does the same thing (and jumps eight bytes instead of four).
1407
1408   // We will put in <addr width> rather than always 8; this will be 4 on x86 and
1409   // 32-bit AMD64, and 8 on 64-bit AMD64.
1410
1411   scratchCodeBuffer.fill(getAddressWidth(), codeGen::cgNOP);
1412
1413   // And since we apparently execute at (addr - <width>), shift dlopen_call_addr
1414   // up past the NOPs.
1415 #endif
1416
1417   // Sync with whatever we've put in so far.
1418   dlopen_call_addr = codeBase + scratchCodeBuffer.used();
1419
1420
1421   // Since we are punching our way down to an internal function, we
1422   // may run into problems due to stack execute protection. Basically,
1423   // glibc knows that it needs to be able to execute on the stack in
1424   // in order to load libraries with dl_open(). It has code in
1425   // _dl_map_object_from_fd (the workhorse of dynamic library loading)
1426   // that unprotects a global, exported variable (__stack_prot), sets
1427   // the execute flag, and reprotects it. This only happens, however,
1428   // when the higher-level dl_open() functions (which we skip) are called,
1429   // as they append an undocumented flag to the library open mode. Otherwise,
1430   // assignment to the variable happens without protection, which will
1431   // cause a fault.
1432   //
1433   // Instead of chasing the value of the undocumented flag, we will
1434   // unprotect the __stack_prot variable ourselves (if we can find it).
1435
1436   if(!( mprotect_call_addr = tryUnprotectStack(scratchCodeBuffer,codeBase) )) {
1437     startup_printf("Failed to disable stack protection.\n");
1438   }
1439
1440 #if defined(cap_32_64)
1441   if (getAddressWidth() == 4) {
1442 #endif
1443
1444       // Push caller
1445       emitPushImm(dlopen_addr, scratchCodeBuffer);
1446       
1447       // Push hole for result
1448       emitPushImm(0, scratchCodeBuffer);
1449       
1450       // Push mode
1451       emitPushImm(DLOPEN_MODE, scratchCodeBuffer);
1452       
1453       // Push string addr
1454       emitPushImm(dyninstlib_str_addr, scratchCodeBuffer);
1455       
1456       // Push the addr of the struct: esp
1457       emitSimpleInsn(PUSHESP, scratchCodeBuffer);
1458       
1459       startup_printf("(%d): emitting call from 0x%x to 0x%x\n",
1460                      getPid(), codeBase + scratchCodeBuffer.used(), dlopen_addr);
1461       instruction::generateCall(scratchCodeBuffer, scratchCodeBuffer.used() + codeBase, dlopen_addr);
1462       
1463
1464 #if defined(cap_32_64)
1465   } else {
1466
1467       // Push caller
1468       emitMovImmToReg64(REGNUM_RAX, dlopen_addr, true, scratchCodeBuffer);
1469       emitSimpleInsn(0x50, scratchCodeBuffer); // push %rax
1470
1471       // Push hole for result
1472       emitSimpleInsn(0x50, scratchCodeBuffer); // push %rax
1473
1474       // Push padding and mode
1475       emitMovImmToReg64(REGNUM_EAX, DLOPEN_MODE, false, scratchCodeBuffer); // 32-bit mov: clears high dword
1476       emitSimpleInsn(0x50, scratchCodeBuffer); // push %rax
1477
1478       // Push string addr
1479       emitMovImmToReg64(REGNUM_RAX, dyninstlib_str_addr, true, scratchCodeBuffer);
1480       emitSimpleInsn(0x50, scratchCodeBuffer); // push %rax
1481       
1482       // Set up the argument: the current stack pointer
1483       emitMovRegToReg64(REGNUM_RDI, REGNUM_RSP, true, scratchCodeBuffer);
1484       
1485       // The call (must be done through a register in order to reach)
1486       emitMovImmToReg64(REGNUM_RAX, dlopen_addr, true, scratchCodeBuffer);
1487       emitSimpleInsn(0xff, scratchCodeBuffer); // group 5
1488       emitSimpleInsn(0xd0, scratchCodeBuffer); // mod = 11, ext_op = 2 (call Ev), r/m = 0 (RAX)
1489   }
1490 #endif
1491
1492   // And the break point
1493   dyninstlib_brk_addr = codeBase + scratchCodeBuffer.used();
1494   instruction::generateTrap(scratchCodeBuffer);
1495
1496   if(mprotect_call_addr != 0) {
1497     startup_printf("(%d) mprotect call addr at 0x%lx\n", getPid(), mprotect_call_addr);
1498   }
1499   startup_printf("(%d) dyninst lib string addr at 0x%x\n", getPid(), dyninstlib_str_addr);
1500   startup_printf("(%d) dyninst lib call addr at 0x%x\n", getPid(), dlopen_call_addr);
1501   startup_printf("(%d) break address is at %p\n", getPid(), (void *) dyninstlib_brk_addr);
1502   startup_printf("(%d) writing %d bytes\n", getPid(), scratchCodeBuffer.used());
1503
1504   // savedCodeBuffer[BYTES_TO_SAVE] is declared in process.h
1505   // We can tighten this up if we record how much we saved
1506
1507   if (!readDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer, true))
1508          fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
1509
1510   startup_printf("(%d) Writing from %p to %p\n", getPid(), (char *)scratchCodeBuffer.start_ptr(), (char *)codeBase);
1511   writeDataSpace((void *)(codeBase), scratchCodeBuffer.used(), scratchCodeBuffer.start_ptr());
1512
1513   // save registers
1514   dyn_lwp *lwp_to_use = NULL;
1515   if(process::IndependentLwpControl() && getRepresentativeLWP() ==NULL)
1516      lwp_to_use = getInitialThread()->get_lwp();
1517   else
1518      lwp_to_use = getRepresentativeLWP();
1519
1520   savedRegs = new dyn_saved_regs;
1521   bool status = lwp_to_use->getRegisters(savedRegs);
1522
1523   assert((status!=false) && (savedRegs!=(void *)-1));
1524
1525   lwp_to_use = NULL;
1526
1527   if(process::IndependentLwpControl() && getRepresentativeLWP() ==NULL)
1528      lwp_to_use = getInitialThread()->get_lwp();
1529   else
1530      lwp_to_use = getRepresentativeLWP();
1531
1532     Address destPC;
1533     if(mprotect_call_addr != 0)
1534         destPC = mprotect_call_addr;
1535     else
1536         destPC = dlopen_call_addr;
1537
1538   startup_printf("Changing PC to 0x%x\n", destPC);
1539   startup_printf("String at 0x%x\n", dyninstlib_str_addr);
1540
1541   if (! lwp_to_use->changePC(destPC,NULL))
1542     {
1543       logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
1544       assert(0);
1545     }
1546
1547
1548 #if false && defined(PTRACEDEBUG)
1549   debug_ptrace = false;
1550 #endif
1551
1552
1553   setBootstrapState(loadingRT_bs);
1554   return true;
1555 }
1556
1557 bool process::loadDYNINSTlib_exported(const char *dlopen_name)
1558 {
1559         // dlopen takes two arguments:
1560         // const char *libname;
1561         // int mode;
1562         // We put the library name on the stack, push the args, and
1563         // emit the call
1564
1565         Address codeBase = findFunctionToHijack(this);
1566         if (!codeBase) 
1567         {
1568                 startup_cerr << "Couldn't find a point to insert dlopen call" << endl;
1569                 return false;
1570         }
1571
1572         Address dyninstlib_str_addr = 0;
1573         Address dlopen_call_addr = 0;
1574
1575         pdvector<int_function *> dlopen_funcs;
1576
1577         if (!findFuncsByAll(dlopen_name ? dlopen_name : DL_OPEN_FUNC_EXPORTED, dlopen_funcs)) 
1578         {
1579                 startup_cerr << "Couldn't find method to load dynamic library" << endl;
1580                 return false;
1581         } 
1582
1583         assert(dlopen_funcs.size() != 0);
1584         
1585         if (dlopen_funcs.size() > 1) 
1586         {
1587                 logLine("WARNING: More than one dlopen found, using the first\n");
1588         }
1589
1590         Address dlopen_addr = dlopen_funcs[0]->getAddress();
1591
1592         // We now fill in the scratch code buffer with appropriate data
1593         codeGen scratchCodeBuffer(BYTES_TO_SAVE);
1594         assert(dyninstRT_name.length() < BYTES_TO_SAVE);
1595
1596         // The library name goes first
1597         dyninstlib_str_addr = codeBase;
1598         scratchCodeBuffer.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
1599
1600 #if defined(bug_syscall_changepc_rewind)
1601         //Fill in with NOPs, see loadDYNINSTlib_hidden
1602         scratchCodeBuffer.fill(getAddressWidth(), codeGen::cgNOP);
1603 #endif
1604
1605         // Now the real code
1606         dlopen_call_addr = codeBase + scratchCodeBuffer.used();
1607
1608         bool mode64bit = (getAddressWidth() == sizeof(uint64_t));
1609
1610         if (!mode64bit) 
1611         {
1612                 // Push mode
1613                 emitPushImm(DLOPEN_MODE, scratchCodeBuffer);
1614
1615                 // Push string addr
1616                 emitPushImm(dyninstlib_str_addr, scratchCodeBuffer);
1617
1618                 instruction::generateCall(scratchCodeBuffer,
1619                                 scratchCodeBuffer.used() + codeBase,
1620                                 dlopen_addr);
1621
1622                 // And the break point
1623                 dyninstlib_brk_addr = codeBase + scratchCodeBuffer.used();
1624                 instruction::generateTrap(scratchCodeBuffer);
1625         }
1626         else 
1627         {
1628                 // Set mode
1629                 emitMovImmToReg64(REGNUM_RSI, DLOPEN_MODE, false, scratchCodeBuffer);
1630                 // Set string addr
1631                 emitMovImmToReg64(REGNUM_RDI, dyninstlib_str_addr, true,
1632                                 scratchCodeBuffer);
1633                 // The call (must be done through a register in order to reach)
1634                 emitMovImmToReg64(REGNUM_RAX, dlopen_addr, true, scratchCodeBuffer);
1635                 emitSimpleInsn(0xff, scratchCodeBuffer);
1636                 emitSimpleInsn(0xd0, scratchCodeBuffer);
1637
1638                 // And the break point
1639                 dyninstlib_brk_addr = codeBase + scratchCodeBuffer.used();
1640                 instruction::generateTrap(scratchCodeBuffer);
1641         }
1642
1643         if (!readDataSpace((void *)codeBase,
1644                                 sizeof(savedCodeBuffer), savedCodeBuffer, true)) 
1645         {
1646                 fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
1647                 return false;
1648         }
1649
1650         if (!writeDataSpace((void *)(codeBase), scratchCodeBuffer.used(),
1651                                 scratchCodeBuffer.start_ptr())) 
1652         {
1653                 fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
1654                 return false;
1655         }
1656
1657         // save registers
1658         dyn_lwp *lwp_to_use = NULL;
1659
1660         if (process::IndependentLwpControl() && getRepresentativeLWP() == NULL)
1661         {
1662                 lwp_to_use = getInitialThread()->get_lwp();
1663         }
1664         else
1665         {
1666                 lwp_to_use = getRepresentativeLWP();
1667         }
1668
1669         savedRegs = new dyn_saved_regs;
1670         bool status = lwp_to_use->getRegisters(savedRegs);
1671
1672         assert((status != false) && (savedRegs != (void *)-1));
1673
1674         if (!lwp_to_use->changePC(dlopen_call_addr,NULL))  
1675         {
1676                 logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
1677                 return false;
1678         }
1679
1680         setBootstrapState(loadingRT_bs);
1681         return true;
1682 }
1683
1684 Address process::tryUnprotectStack(codeGen &buf, Address codeBase) 
1685 {
1686         // find variable __stack_prot
1687
1688         // mprotect READ/WRITE __stack_prot
1689         pdvector<int_variable *> vars; 
1690         pdvector<int_function *> funcs;
1691
1692         Address var_addr;
1693         Address func_addr;
1694         Address ret_addr;
1695         int size;
1696         int pagesize;
1697     Address page_start;
1698     bool ret;
1699     
1700     ret = findVarsByAll("__stack_prot", vars);
1701
1702     if(!ret || vars.size() == 0) {
1703         return 0;
1704     } else if(vars.size() > 1) {
1705         startup_printf("Warning: found more than one __stack_prot variable\n");
1706     }
1707
1708     pagesize = getpagesize();
1709
1710     var_addr = vars[0]->getAddress();
1711     page_start = var_addr & ~(pagesize -1);
1712     size = var_addr - page_start +sizeof(int);
1713
1714     ret = findFuncsByAll("mprotect",funcs);
1715
1716     if(!ret || funcs.size() == 0) {
1717         startup_printf("Couldn't find mprotect\n");
1718         return 0;
1719     }
1720
1721     int_function * mprot = funcs[0];
1722     func_addr = mprot->getAddress();
1723     ret_addr = codeBase + buf.used();
1724
1725 #if defined(arch_x86_64)
1726   if (getAddressWidth() == 4) {
1727 #endif
1728       // Push caller
1729       emitPushImm(func_addr, buf);
1730       
1731       // Push mode (READ|WRITE|EXECUTE)
1732       emitPushImm(7, buf);
1733       
1734       // Push variable size
1735       emitPushImm(size, buf);
1736       
1737       // Push variable location
1738       emitPushImm(page_start, buf);
1739      
1740       startup_printf("(%d): emitting call for mprotect from 0x%x to 0x%x\n",
1741                      getPid(), codeBase + buf.used(), func_addr);
1742       instruction::generateCall(buf, buf.used() + codeBase, func_addr);
1743 #if defined(arch_x86_64)
1744   } else {
1745       // Push caller
1746       //emitMovImmToReg64(REGNUM_RAX, func_addr, true, buf);
1747       //emitSimpleInsn(0x50, buf); // push %rax       
1748
1749       // Push mode (READ|WRITE|EXECUTE)
1750       emitMovImmToReg64(REGNUM_RDX, 7, true, buf); //32-bit mov
1751    
1752       // Push variable size
1753       emitMovImmToReg64(REGNUM_RSI, size, true, buf); //32-bit mov
1754
1755       // Push variable location 
1756       emitMovImmToReg64(REGNUM_RDI, page_start, true, buf);
1757
1758       // The call (must be done through a register in order to reach)
1759       emitMovImmToReg64(REGNUM_RAX, func_addr, true, buf);
1760       emitSimpleInsn(0xff, buf); // group 5
1761       emitSimpleInsn(0xd0, buf); // mod=11, ext_op=2 (call Ev), r/m=0 (RAX)
1762   }
1763 #endif
1764     
1765     return ret_addr;
1766 }
1767
1768 int EmitterIA32::emitCallParams(codeGen &gen, 
1769                               const pdvector<AstNodePtr> &operands,
1770                               int_function */*target*/, 
1771                               pdvector<Register> &/*extra_saves*/, 
1772                               bool noCost)
1773 {
1774     pdvector <Register> srcs;
1775     unsigned frame_size = 0;
1776     unsigned u;
1777     for (u = 0; u < operands.size(); u++) {
1778         Address unused = ADDR_NULL;
1779         Register reg = REG_NULL;
1780         if (!operands[u]->generateCode_phase2(gen,
1781                                               noCost,
1782                                               unused,
1783                                               reg)) assert(0); // ARGH....
1784         assert (reg != REG_NULL); // Give me a real return path!
1785         srcs.push_back(reg);
1786     }
1787     
1788     // push arguments in reverse order, last argument first
1789     // must use int instead of unsigned to avoid nasty underflow problem:
1790     for (int i=srcs.size() - 1; i >= 0; i--) {
1791        RealRegister r = gen.rs()->loadVirtual(srcs[i], gen);
1792        ::emitPush(r, gen);
1793        frame_size += 4;
1794        if (operands[i]->decRefCount())
1795           gen.rs()->freeRegister(srcs[i]);
1796     }
1797     return frame_size;
1798 }
1799
1800 bool EmitterIA32::emitCallCleanup(codeGen &gen,
1801                                 int_function * /*target*/, 
1802                                 int frame_size, 
1803                                 pdvector<Register> &/*extra_saves*/)
1804 {
1805    if (frame_size)
1806       emitOpRegImm(0, RealRegister(REGNUM_ESP), frame_size, gen); // add esp, frame_size
1807    gen.rs()->incStack(-1 * frame_size);
1808    return true;
1809 }
1810
1811 Frame process::preStackWalkInit(Frame startFrame) 
1812 {
1813   /* Do a special check for the vsyscall page.  Silently drop
1814      the page if it exists. */
1815   calcVSyscallFrame( this );
1816   
1817   Address next_pc = startFrame.getPC();
1818   if ((next_pc >= getVsyscallStart() && next_pc < getVsyscallEnd()) ||
1819       /* RH9 Hack */ (next_pc >= 0xffffe000 && next_pc < 0xfffff000)) {
1820      return startFrame.getCallerFrame();
1821   }
1822   return startFrame;
1823 }
1824
1825 #if defined(arch_x86_64)
1826 void print_regs(dyn_lwp *lwp)
1827 {
1828    struct dyn_saved_regs regs;
1829    bool result = lwp->getRegisters(&regs, false);
1830
1831    if (result)
1832       fprintf(stderr, "rax = %lx\n", regs.gprs.rax);
1833 }
1834 #endif
1835
1836 static const std::string LIBC_CTOR_HANDLER("__do_global_ctors_aux");
1837 static const std::string LIBC_DTOR_HANDLER("__do_global_dtors_aux");
1838 static const std::string DYNINST_CTOR_HANDLER("DYNINSTglobal_ctors_handler");
1839 static const std::string DYNINST_CTOR_LIST("DYNINSTctors_addr");
1840 static const std::string DYNINST_DTOR_HANDLER("DYNINSTglobal_dtors_handler");
1841 static const std::string DYNINST_DTOR_LIST("DYNINSTdtors_addr");
1842 static const std::string SYMTAB_CTOR_LIST_REL("__SYMTABAPI_CTOR_LIST__");
1843 static const std::string SYMTAB_DTOR_LIST_REL("__SYMTABAPI_DTOR_LIST__");
1844
1845 static bool replaceHandler(int_function *origHandler, int_function *newHandler, 
1846         int_symbol *newList, const std::string &listRelName)
1847 {
1848     // Add instrumentation to replace the function
1849     const pdvector<instPoint *> &entries = origHandler->funcEntries();
1850     AstNodePtr funcJump = AstNode::funcReplacementNode(const_cast<int_function *>(newHandler));
1851     for(unsigned j = 0; j < entries.size(); ++j) {
1852         miniTramp *mini = entries[j]->instrument(funcJump,
1853                 callPreInsn, orderFirstAtPoint, true, false);
1854         if( !mini ) {
1855             return false;
1856         }
1857     }
1858
1859     /* create the special relocation for the new list -- search the RT library for
1860      * the symbol
1861      */
1862     Symbol *newListSym = const_cast<Symbol *>(newList->sym());
1863     
1864     std::vector<Region *> allRegions;
1865     if( !newListSym->getSymtab()->getAllRegions(allRegions) ) {
1866         return false;
1867     }
1868
1869     bool success = false;
1870     std::vector<Region *>::iterator reg_it;
1871     for(reg_it = allRegions.begin(); reg_it != allRegions.end(); ++reg_it) {
1872         std::vector<relocationEntry> &region_rels = (*reg_it)->getRelocations();
1873         vector<relocationEntry>::iterator rel_it;
1874         for( rel_it = region_rels.begin(); rel_it != region_rels.end(); ++rel_it) {
1875             if( rel_it->getDynSym() == newListSym ) {
1876                 relocationEntry *rel = &(*rel_it);
1877                 rel->setName(listRelName);
1878                 success = true;
1879             }
1880         }
1881     }
1882
1883     return success;
1884 }
1885
1886 bool BinaryEdit::doStaticBinarySpecialCases() {
1887     Symtab *origBinary = mobj->parse_img()->getObject();
1888
1889     /* Special Case 1: Handling global constructor and destructor Regions
1890      *
1891      * Replace global ctors function with special ctors function,
1892      * and create a special relocation for the ctors list used by the special
1893      * ctors function
1894      *
1895      * Replace global dtors function with special dtors function,
1896      * and create a special relocation for the dtors list used by the special
1897      * dtors function
1898      */
1899     if( !mobj->parse_img()->findGlobalConstructorFunc() ) {
1900         return false;
1901     }
1902
1903     if( !mobj->parse_img()->findGlobalDestructorFunc() ) {
1904         return false;
1905     }
1906
1907     // First, find all the necessary symbol info.
1908     int_function *globalCtorHandler = findOnlyOneFunction(LIBC_CTOR_HANDLER);
1909     if( !globalCtorHandler ) {
1910         logLine("failed to find libc constructor handler\n");
1911         return false;
1912     }
1913
1914     int_function *dyninstCtorHandler = findOnlyOneFunction(DYNINST_CTOR_HANDLER);
1915     if( !dyninstCtorHandler ) {
1916         logLine("failed to find Dyninst constructor handler\n");
1917         return false;
1918     }
1919
1920     int_function *globalDtorHandler = findOnlyOneFunction(LIBC_DTOR_HANDLER);
1921     if( !globalDtorHandler ) {
1922         logLine("failed to find libc destructor handler\n");
1923         return false;
1924     }
1925
1926     int_function *dyninstDtorHandler = findOnlyOneFunction(DYNINST_DTOR_HANDLER);
1927     if( !dyninstDtorHandler ) {
1928         logLine("failed to find Dyninst destructor handler\n");
1929         return false;
1930     }
1931
1932     int_symbol ctorsListInt;
1933     int_symbol dtorsListInt;
1934     bool ctorFound = false, dtorFound = false; 
1935     std::vector<BinaryEdit *>::iterator rtlib_it;
1936     for(rtlib_it = rtlib.begin(); rtlib_it != rtlib.end(); ++rtlib_it) {
1937         if( (*rtlib_it)->getSymbolInfo(DYNINST_CTOR_LIST, ctorsListInt) ) {
1938             ctorFound = true;
1939             if( dtorFound ) break;
1940         }
1941
1942         if( (*rtlib_it)->getSymbolInfo(DYNINST_DTOR_LIST, dtorsListInt) ) {
1943             dtorFound = true;
1944             if( ctorFound ) break;
1945         }
1946     }
1947
1948     if( !ctorFound ) {
1949          logLine("failed to find ctors list symbol\n");
1950          return false;
1951     }
1952
1953     if( !dtorFound ) {
1954         logLine("failed to find dtors list symbol\n");
1955         return false;
1956     }
1957
1958     /*
1959      * Replace the libc ctor and dtor handlers with our special handlers
1960      */
1961     if( !replaceHandler(globalCtorHandler, dyninstCtorHandler,
1962                 &ctorsListInt, SYMTAB_CTOR_LIST_REL) ) {
1963         logLine("Failed to replace libc ctor handler with special handler");
1964         return false;
1965     }else{
1966         inst_printf("%s[%d]: replaced ctor function %s with %s\n",
1967                 FILE__, __LINE__, LIBC_CTOR_HANDLER.c_str(),
1968                 DYNINST_CTOR_HANDLER.c_str());
1969     }
1970
1971     if( !replaceHandler(globalDtorHandler, dyninstDtorHandler,
1972                 &dtorsListInt, SYMTAB_DTOR_LIST_REL) ) {
1973         logLine("Failed to replace libc dtor handler with special handler");
1974         return false;
1975     }else{
1976         inst_printf("%s[%d]: replaced dtor function %s with %s\n",
1977                 FILE__, __LINE__, LIBC_DTOR_HANDLER.c_str(),
1978                 DYNINST_DTOR_HANDLER.c_str());
1979     }
1980
1981     /*
1982      * Special Case 2: Issue a warning if attempting to link pthreads into a binary
1983      * that originally did not support it or into a binary that is stripped. This
1984      * scenario is not supported with the initial release of the binary rewriter for
1985      * static binaries.
1986      *
1987      * The other side of the coin, if working with a binary that does have pthreads
1988      * support, it is a good idea to load pthreads.
1989      */
1990     bool isMTCapable = isMultiThreadCapable();
1991     bool foundPthreads = false;
1992
1993     vector<Archive *> libs;
1994     vector<Archive *>::iterator libIter;
1995     if( origBinary->getLinkingResources(libs) ) {
1996         for(libIter = libs.begin(); libIter != libs.end(); ++libIter) {
1997             if( (*libIter)->name().find("libpthread") != std::string::npos ) {
1998                 foundPthreads = true;
1999                 break;
2000             }
2001         }
2002     }
2003
2004     if( foundPthreads && (!isMTCapable || origBinary->isStripped()) ) {
2005         fprintf(stderr,
2006             "\nWARNING: the pthreads library has been loaded and\n"
2007             "the original binary is not multithread-capable or\n"
2008             "it is stripped. Currently, the combination of these two\n"
2009             "scenarios is unsupported and unexpected behavior may occur.\n");
2010     }else if( !foundPthreads && isMTCapable ) {
2011         fprintf(stderr,
2012             "\nWARNING: the pthreads library has not been loaded and\n"
2013             "the original binary is multithread-capable. Unexpected\n"
2014             "behavior may occur because some pthreads routines are\n"
2015             "unavailable in the original binary\n");
2016     }
2017
2018     /* 
2019      * Special Case 3:
2020      * The RT library has some dependencies -- Symtab always needs to know
2021      * about these dependencies. So if the dependencies haven't already been
2022      * loaded, load them.
2023      */
2024     bool loadLibc = true;
2025
2026     for(libIter = libs.begin(); libIter != libs.end(); ++libIter) {
2027         if( (*libIter)->name().find("libc.a") != std::string::npos ) {
2028             loadLibc = false;
2029         }
2030     }
2031
2032     if( loadLibc ) {
2033         std::map<std::string, BinaryEdit *> res = openResolvedLibraryName("libc.a");
2034         std::map<std::string, BinaryEdit *>::iterator bedit_it;
2035         for(bedit_it = res.begin(); bedit_it != res.end(); ++bedit_it) {
2036             if( bedit_it->second == NULL ) {
2037                 logLine("Failed to load DyninstAPI_RT library dependency (libc.a)");
2038                 return false;
2039             }
2040         }
2041     }
2042
2043     return true;
2044 }
2045
2046 bool image::findGlobalConstructorFunc() {
2047     using namespace Dyninst::InstructionAPI;
2048
2049     vector<Function *> funcs;
2050     if( linkedFile->findFunctionsByName(funcs, LIBC_CTOR_HANDLER) ) {
2051         return true;
2052     }
2053
2054     /* If the symbol isn't found, try looking for it in a call instruction in
2055      * the .init section
2056      *
2057      * The instruction sequence is:
2058      * ...
2059      * some instructions
2060      * ...
2061      * call call_gmon_start
2062      * call frame_dummy
2063      * call __do_global_ctors_aux
2064      */
2065     Region *initRegion = NULL;
2066     if( !linkedFile->findRegion(initRegion, ".init") ) {
2067         if( linkedFile->findFunctionsByName(funcs, "_init") ) {
2068             initRegion = funcs[0]->getRegion();
2069         }else{
2070             logLine("failed to locate .init Region or _init function\n");
2071             return false;
2072         }
2073     }
2074
2075     if( initRegion == NULL ) {
2076         logLine("failed to locate .init Region or _init function\n");
2077         return false;
2078     }
2079
2080     /* 
2081      * If the function associated with the .init Region doesn't exist, it needs to
2082      * be created
2083      */
2084     if( !findFuncByEntry(initRegion->getRegionAddr()) ) {
2085         image_func *initStub = addFunctionStub(initRegion->getRegionAddr(), "_init");
2086         if( initStub == NULL ) {
2087             logLine("unable to create function for .init \n");
2088             return false;
2089         }else{
2090             initStub->parse();
2091             inst_printf("%s[%d]: set _init function address to 0x%lx\n", FILE__, __LINE__,
2092                 initRegion->getRegionAddr());
2093         }
2094     }
2095
2096     // Search for last of 3 calls
2097     Address ctorAddress = 0;
2098     unsigned bytesSeen = 0;
2099     unsigned numCalls = 0;
2100     const unsigned char *p = reinterpret_cast<const unsigned char *>(initRegion->getPtrToRawData());
2101
2102     dyn_detail::boost::shared_ptr<InstructionDecoder> decoder =
2103             makeDecoder(getArch(), p, initRegion->getRegionSize());
2104     decoder->setMode(getAddressWidth() == 8);
2105
2106     Instruction::Ptr curInsn = decoder->decode();
2107     while(numCalls < 3 && curInsn && curInsn->isValid() &&
2108           bytesSeen < initRegion->getRegionSize()) 
2109     {
2110         InsnCategory category = curInsn->getCategory();
2111         if( category == c_CallInsn ) {
2112             numCalls++;
2113         }
2114         if( numCalls < 3 ) {
2115             bytesSeen += curInsn->size();
2116             curInsn = decoder->decode();
2117         }
2118     }
2119
2120     if( numCalls != 3 ) {
2121         logLine("heuristic for finding global constructor function failed\n");
2122         return false;
2123     }
2124
2125     Address callAddress = initRegion->getRegionAddr() + bytesSeen;
2126
2127     RegisterAST thePC = RegisterAST(Dyninst::MachRegister::getPC(getArch()));
2128
2129     Expression::Ptr callTarget = curInsn->getControlFlowTarget();
2130     if( !callTarget.get() ) {
2131         logLine("failed to find global constructor function\n");
2132         return false;
2133     }
2134     callTarget->bind(&thePC, Result(s64, callAddress));
2135     //callTarget->bind(&rip, Result(s64, callAddress));
2136
2137     Result actualTarget = callTarget->eval();
2138     if( actualTarget.defined ) {
2139         ctorAddress = actualTarget.convert<Address>();
2140     }else{
2141         logLine("failed to find global constructor function\n");
2142         return false;
2143     }
2144
2145     if( !ctorAddress || !isValidAddress(ctorAddress) ) {
2146         logLine("invalid address for global constructor function\n");
2147         return false;
2148     }
2149
2150     if( addFunctionStub(ctorAddress, LIBC_CTOR_HANDLER.c_str()) == NULL ) {
2151         logLine("unable to create representation for global constructor function\n");
2152         return false;
2153     }else{
2154         inst_printf("%s[%d]: set global constructor address to 0x%lx\n", FILE__, __LINE__,
2155                 ctorAddress);
2156     }
2157
2158     return true;
2159 }
2160
2161 bool image::findGlobalDestructorFunc() {
2162     using namespace Dyninst::InstructionAPI;
2163
2164     vector<Function *> funcs;
2165     if( linkedFile->findFunctionsByName(funcs, LIBC_DTOR_HANDLER) ) {
2166         return true;
2167     }
2168
2169     /*
2170      * If the symbol isn't found, try looking for it in a call in the
2171      * .fini section. It is the last call in .fini.
2172      *
2173      * The pattern is:
2174      *
2175      * _fini:
2176      *
2177      * ... some code ...
2178      *
2179      * call LIBC_DTOR_HANDLER
2180      *
2181      * ... prologue ...
2182      */
2183     Region *finiRegion = NULL;
2184     if( !linkedFile->findRegion(finiRegion, ".fini") ) {
2185         if( linkedFile->findFunctionsByName(funcs, "_fini") ) {
2186             finiRegion = funcs[0]->getRegion();
2187         }else{
2188             logLine("failed to locate .fini Region or _fini function\n");
2189             return false;
2190         }
2191     }
2192
2193     if( finiRegion == NULL ) {
2194         logLine("failed to locate .fini Region or _fini function\n");
2195         return false;
2196     }
2197
2198     /* 
2199      * If the function associated with the .fini Region doesn't exist, it needs to
2200      * be created
2201      */
2202     if( !findFuncByEntry(finiRegion->getRegionAddr()) ) {
2203         image_func *finiStub = addFunctionStub(finiRegion->getRegionAddr(), "_fini");
2204         if( finiStub == NULL ) {
2205             logLine("unable to create function for .fini \n");
2206             return false;
2207         }else{
2208             finiStub->parse();
2209             inst_printf("%s[%d]: set _fini function address to 0x%lx\n", FILE__, __LINE__,
2210                 finiRegion->getRegionAddr());
2211         }
2212     }
2213
2214     // Search for last call in the function
2215     Address dtorAddress = 0;
2216     unsigned bytesSeen = 0;
2217     const unsigned char *p = reinterpret_cast<const unsigned char *>(finiRegion->getPtrToRawData());
2218
2219     dyn_detail::boost::shared_ptr<InstructionDecoder> decoder =
2220             makeDecoder(getArch(), p, finiRegion->getRegionSize());
2221     decoder->setMode(getAddressWidth() == 8);
2222
2223     Instruction::Ptr lastCall;
2224     Instruction::Ptr curInsn = decoder->decode();
2225
2226     while(curInsn && curInsn->isValid() &&
2227           bytesSeen < finiRegion->getRegionSize()) 
2228     {
2229         InsnCategory category = curInsn->getCategory();
2230         if( category == c_CallInsn ) {
2231             lastCall = curInsn;
2232         }
2233             bytesSeen += curInsn->size();
2234             curInsn = decoder->decode();
2235     }
2236
2237     if( !lastCall.get() || !lastCall->isValid() ) {
2238         logLine("heuristic for finding global destructor function failed\n");
2239         return false;
2240     }
2241
2242     Address callAddress = finiRegion->getRegionAddr() + bytesSeen;
2243
2244     RegisterAST thePC = RegisterAST(Dyninst::MachRegister::getPC(getArch()));
2245
2246     Expression::Ptr callTarget = lastCall->getControlFlowTarget();
2247     if( !callTarget.get() ) {
2248         logLine("failed to find global destructor function\n");
2249         return false;
2250     }
2251     callTarget->bind(&thePC, Result(s64, callAddress));
2252     //callTarget->bind(&rip, Result(s64, callAddress));
2253
2254     Result actualTarget = callTarget->eval();
2255     if( actualTarget.defined ) {
2256         dtorAddress = actualTarget.convert<Address>();
2257     }else{
2258         logLine("failed to find global destructor function\n");
2259         return false;
2260     }
2261
2262     if( !dtorAddress || !isValidAddress(dtorAddress) ) {
2263         logLine("invalid address for global destructor function\n");
2264         return false;
2265     }
2266
2267     if( addFunctionStub(dtorAddress, LIBC_DTOR_HANDLER.c_str()) == NULL ) {
2268         logLine("unable to create representation for global destructor function\n");
2269         return false;
2270     }else{
2271         inst_printf("%s[%d]: set global destructor address to 0x%lx\n", FILE__, __LINE__,
2272                 dtorAddress);
2273     }
2274
2275     return true;
2276 }