Fix for bug in loading RT library during attach on Linux x86/x86_64.
[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/function.h"
55 #include "dyninstAPI/src/instPoint.h"
56 #include "common/h/headers.h"
57 #include "dyninstAPI/src/os.h"
58 #include "common/h/stats.h"
59 #include "common/h/Types.h"
60 #include "dyninstAPI/src/debug.h"
61 #include "dyninstAPI/src/util.h" // getCurrWallTime
62 #include "common/h/pathName.h"
63 #include "dyninstAPI/src/inst-x86.h"
64 #include "dyninstAPI/src/emit-x86.h"
65 #include "dyninstAPI/src/dyn_thread.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 using namespace Dyninst;
91 using namespace Dyninst::SymtabAPI;
92
93 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
94
95 const char *DL_OPEN_FUNC_USER = NULL;
96 const char DL_OPEN_FUNC_EXPORTED[] = "dlopen";
97 const char DL_OPEN_FUNC_NAME[] = "do_dlopen";
98 const char DL_OPEN_FUNC_INTERNAL[] = "_dl_open";
99
100 const char libc_version_symname[] = "__libc_version";
101
102
103 #if defined(PTRACEDEBUG) && !defined(PTRACEDEBUG_ALWAYS)
104 static bool debug_ptrace = false;
105 #endif
106
107 #define NUM_REGS (17 /*+ NUM_FREGS*/)
108 #define NUM_FREGS 8
109 #define FP0_REGNUM NUM_REGS
110 #define FP7_REGNUM (FP0_REGNUM+7)
111 #define INTREGSIZE (sizeof(long))
112 #define FPREGSIZE 10
113 #define MAX_REGISTER_RAW_SIZE 10
114
115 #define REGISTER_RAW_SIZE(N) (((N) < FP0_REGNUM) ? INTREGSIZE : FPREGSIZE)
116 #define REGS_SIZE ( NUM_REGS * REGISTER_RAW_SIZE(0) + NUM_FREGS * REGISTER_RAW_SIZE(FP0_REGNUM) )
117 #define REGS_INTS ( REGS_SIZE / INTREGSIZE )
118
119 const int GENREGS_STRUCT_SIZE = sizeof( user_regs_struct );
120 #ifdef _SYS_USER_H 
121 const int FPREGS_STRUCT_SIZE = sizeof( user_fpregs_struct );
122 #else
123 const int FPREGS_STRUCT_SIZE = sizeof( user_i387_struct );
124 #endif
125
126 #define P_offsetof(s, m) (Address) &(((s *) NULL)->m)
127
128 /* ********************************************************************** */
129
130 bool dyn_lwp::getRegisters_(struct dyn_saved_regs *regs, bool includeFP) 
131 {
132    // Cycle through all registers, reading each from the
133    // process user space with ptrace(PTRACE_PEEKUSER ...
134    int error;
135    bool errorFlag = false;
136    assert(get_lwp_id() != 0);
137    int ptrace_errno = 0;
138    error = DBI_ptrace(PTRACE_GETREGS, get_lwp_id(), 0, (long)&(regs->gprs), 
139          &ptrace_errno, proc_->getAddressWidth(),  
140          __FILE__, __LINE__ );
141    if( error ) {
142       perror("dyn_lwp::getRegisters PTRACE_GETREGS" );
143       errorFlag = true;
144       return false;
145    }
146
147    if (includeFP)
148    {
149       error = DBI_ptrace(PTRACE_GETFPREGS, get_lwp_id(), 0,
150             (long)&(regs->fprs), &ptrace_errno,
151             proc_->getAddressWidth(),  __FILE__, __LINE__);
152
153       if( error ) {
154          perror("dyn_lwp::getRegisters PTRACE_GETFPREGS" );
155          return false;
156       }
157    }
158    return true;
159 }
160
161 void dyn_lwp::dumpRegisters()
162 {
163    dyn_saved_regs regs;
164    if (!getRegisters(&regs)) {
165       fprintf(stderr, "%s[%d]:  registers unavailable\n", FILE__, __LINE__);
166       return;
167    }
168
169 #if defined(arch_x86)
170    fprintf(stderr, "eip:   %lx\n", regs.gprs.eip);
171    fprintf(stderr, "eax:   %lx\n", regs.gprs.eax);
172    fprintf(stderr, "ebx:   %lx\n", regs.gprs.ebx);
173    fprintf(stderr, "ecx:   %lx\n", regs.gprs.ecx);
174    fprintf(stderr, "esp:   %lx\n", regs.gprs.esp);
175    fprintf(stderr, "xcs:   %lx\n", regs.gprs.xcs);
176 #endif
177 #if defined(arch_x86_64)
178    fprintf(stderr, "eip:   %lx\n", regs.gprs.rip);
179    fprintf(stderr, "eax:   %lx\n", regs.gprs.rax);
180    fprintf(stderr, "ebx:   %lx\n", regs.gprs.rbx);
181    fprintf(stderr, "ecx:   %lx\n", regs.gprs.rcx);
182    fprintf(stderr, "esp:   %lx\n", regs.gprs.rsp);
183    fprintf(stderr, "xcs:   %lx\n", regs.gprs.cs);
184 #endif
185    //  plenty more register if we want to print em....
186 }
187
188 bool dyn_lwp::changePC(Address loc,
189       struct dyn_saved_regs */*ignored registers*/)
190 {
191
192    Address regaddr = P_offsetof(struct user_regs_struct, PTRACE_REG_IP);
193    assert(get_lwp_id() != 0);
194    int ptrace_errno = 0;
195
196    // Check to see if the incoming address is valid...
197    #if defined(arch_x86_64)
198    if ((proc_->getAddressWidth() == 4) &&
199        (sizeof(Address) == 8)) {
200      assert(!(loc & 0xffffffff00000000));
201    }
202    #endif
203    if (0 != DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(), regaddr, loc, 
204             &ptrace_errno, proc_->getAddressWidth(),  
205             __FILE__, __LINE__ )) {
206       fprintf(stderr, "dyn_lwp::changePC - PTRACE_POKEUSER failure for %u",
207             get_lwp_id());
208       return false;
209    }
210    
211    return true;
212 }
213
214 bool dyn_lwp::clearOPC() 
215 {
216    Address regaddr = P_offsetof(struct user_regs_struct, PTRACE_REG_ORIG_AX);
217    assert(get_lwp_id() != 0);
218    int ptrace_errno = 0;
219    if (0 != DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(), regaddr, -1UL, &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__)) {
220       perror( "dyn_lwp::changePC - PTRACE_POKEUSER" );
221       return false;
222    }
223    return true;
224 }
225
226 #define REG_STR(x)      REG_STR_(x)
227 #define REG_STR_(x)     #x
228 void printRegs( void *save ) 
229 {
230    user_regs_struct *regs = (user_regs_struct*)save;
231    cerr
232       << REG_STR( PTRACE_REG_AX ) ": " << (void*)regs->PTRACE_REG_AX
233       << REG_STR( PTRACE_REG_BX ) ": " << (void*)regs->PTRACE_REG_BX
234       << REG_STR( PTRACE_REG_CX ) ": " << (void*)regs->PTRACE_REG_CX
235       << REG_STR( PTRACE_REG_DX ) ": " << (void*)regs->PTRACE_REG_DX << endl
236       << REG_STR( PTRACE_REG_DI ) ": " << (void*)regs->PTRACE_REG_DI
237       << REG_STR( PTRACE_REG_SI ) ": " << (void*)regs->PTRACE_REG_SI << endl
238       << REG_STR( PTRACE_REG_CS ) ": " << (void*)regs->PTRACE_REG_CS
239       << REG_STR( PTRACE_REG_DS ) ": " << (void*)regs->PTRACE_REG_DS
240       << REG_STR( PTRACE_REG_ES ) ": " << (void*)regs->PTRACE_REG_ES
241       << REG_STR( PTRACE_REG_FS ) ": " << (void*)regs->PTRACE_REG_FS
242       << REG_STR( PTRACE_REG_GS ) ": " << (void*)regs->PTRACE_REG_GS
243       << REG_STR( PTRACE_REG_SS ) ": " << (void*)regs->PTRACE_REG_SS << endl
244       << REG_STR( PTRACE_REG_IP ) ": " << (void*)regs->PTRACE_REG_IP
245       << REG_STR( PTRACE_REG_SP ) ": " << (void*)regs->PTRACE_REG_SP
246       << REG_STR( PTRACE_REG_BP ) ": " << (void*)regs->PTRACE_REG_BP << endl
247       << REG_STR( PTRACE_REG_ORIG_AX ) ": " << (void*)regs->PTRACE_REG_ORIG_AX
248       << REG_STR( PTRACE_REG_FLAGS ) ": " << (void*)regs->PTRACE_REG_FLAGS << endl;
249 }
250
251
252 bool dyn_lwp::restoreRegisters_(const struct dyn_saved_regs &regs, bool includeFP) {
253    // Cycle through all registers, writing each from the
254    // buffer with ptrace(PTRACE_POKEUSER ...
255
256    bool retVal = true;
257    int ptrace_errno = 0;
258
259
260    assert(get_lwp_id() != 0);
261    if( DBI_ptrace( PTRACE_SETREGS, get_lwp_id(), 0,(long)&(regs.gprs), 
262             &ptrace_errno, proc_->getAddressWidth(),  
263             __FILE__, __LINE__ ) )
264    {
265       perror("dyn_lwp::restoreRegisters PTRACE_SETREGS" );
266       retVal = false;
267    }
268
269    if (includeFP) {
270       if( DBI_ptrace( PTRACE_SETFPREGS, get_lwp_id(), 0, (long)&(regs.fprs), 
271                &ptrace_errno, proc_->getAddressWidth(),  
272                __FILE__, __LINE__))
273       {
274          perror("dyn_lwp::restoreRegisters PTRACE_SETFPREGS" );
275          retVal = false;
276       }
277    }
278    return retVal;
279 }
280
281 // getActiveFrame(): populate Frame object using toplevel frame
282 Frame dyn_lwp::getActiveFrame()
283 {
284    if(status() == running) {
285       fprintf(stderr, "%s[%d][%s]:  FIXME\n", __FILE__, __LINE__, 
286             getThreadStr(getExecThreadID()));
287       cerr << "    performance problem in call to dyn_lwp::getActiveFrame\n"
288          << "       successive pauses and continues with ptrace calls\n";
289    }
290
291    Address pc, fp, sp;
292
293    int ptrace_errno = 0;
294    fp = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(), P_offsetof(struct user_regs_struct, PTRACE_REG_BP), 0, &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__);
295    if (ptrace_errno) return Frame();
296
297    pc = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(), P_offsetof(struct user_regs_struct, PTRACE_REG_IP), 0, &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__);
298    if (ptrace_errno) return Frame();
299
300    sp = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(), P_offsetof(struct user_regs_struct, PTRACE_REG_SP), 0, &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__);
301    if (ptrace_errno) return Frame();
302
303    dbi_printf("%s[%d]:  GET ACTIVE FRAME (pc = %p, sp = %p, fp = %p\n", 
304          FILE__, __LINE__, pc, sp, fp);
305
306    return Frame(pc, fp, sp, proc_->getPid(), proc_, NULL, this, true);
307 }
308
309 bool process::loadDYNINSTlibCleanup(dyn_lwp *trappingLWP)
310 {
311    // rewrite original instructions in the text segment we use for 
312    // the inferiorRPC - naim
313    unsigned count = sizeof(savedCodeBuffer);
314
315    Address codeBase = findFunctionToHijack(this);
316    assert(codeBase);
317
318    writeDataSpace((void *)codeBase, count, (char *)savedCodeBuffer);
319
320    // restore registers
321    assert(savedRegs != NULL);
322    trappingLWP->restoreRegisters(*savedRegs);
323
324    delete savedRegs;
325    savedRegs = NULL;
326    return true;
327 }
328
329 bool process::handleTrapAtEntryPointOfMain(dyn_lwp *trappingLWP)
330 {
331    assert(main_brk_addr);
332    assert(trappingLWP);
333    // restore original instruction 
334    // Use this for the size -- make sure that we're using the same
335    // insn in both places. Or give savedCodeBuffer a size twin.
336
337    if (!writeDataSpace((void *)main_brk_addr, sizeof(savedCodeBuffer), (char *)savedCodeBuffer))
338       return false;
339
340    if (! trappingLWP->changePC(main_brk_addr,NULL))
341    {
342       logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
343       assert(0);
344    }
345
346    main_brk_addr = 0;
347    return true;
348 }
349
350 bool process::insertTrapAtEntryPointOfMain()
351 {
352
353    int_function *f_main = 0;
354    pdvector<int_function *> funcs;
355    //first check a.out for function symbol   
356    bool res = findFuncsByPretty("main", funcs);
357    if (!res)
358    {
359       logLine( "a.out has no main function. checking for PLT entry\n" );
360       //we have not found a "main" check if we have a plt entry
361       res = findFuncsByPretty( "DYNINST_pltMain", funcs );
362
363       if (!res) {
364          logLine( "no PLT entry for main found\n" );
365          return false;
366       }       
367    }
368
369    if( funcs.size() > 1 ) {
370       cerr << __FILE__ << __LINE__ 
371          << ": found more than one main! using the first" << endl;
372    }
373    f_main = funcs[0];
374    assert(f_main);
375    Address addr = f_main->getAddress();
376
377    // and now, insert trap
378    // For some reason, using a trap breaks but using an illegal works. Anyone 
379    // have any idea?
380    // It looks like the trap PC is actual PC + 1...
381    // This is ugly, but we'll have the "check if this was entry of main" function
382    // check main_brk_addr or main_brk_addr + 1...
383    startup_printf("%s[%d]: Saving %d bytes from entry of main of %d...\n", 
384          FILE__, __LINE__, sizeof(savedCodeBuffer), getPid());
385
386    // save original instruction first
387    if (!readDataSpace((void *)addr, sizeof(savedCodeBuffer), savedCodeBuffer, true)) {
388       fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
389       fprintf(stderr, "%s[%d][%s]:  failing insertTrapAtEntryPointOfMain\n",
390             __FILE__, __LINE__, getThreadStr(getExecThreadID()));
391       fprintf(stderr, "Failed to read at address 0x%lx\n", addr);
392       return false;
393    }
394
395    codeGen gen(1);
396    insnCodeGen::generateTrap(gen);
397
398    if (!writeDataSpace((void *)addr, gen.used(), gen.start_ptr())) {
399       fprintf(stderr, "%s[%d][%s]:  failing insertTrapAtEntryPointOfMain\n",
400             __FILE__, __LINE__, getThreadStr(getExecThreadID()));
401       return false;
402    }
403
404    main_brk_addr = addr;
405
406    signal_printf("Added trap at entry of main, address 0x%x\n", main_brk_addr);
407    return true;
408 }
409
410 #if defined(arch_x86_64)
411
412 bool process::getSysCallParameters(dyn_saved_regs *regs, long *params, int numparams) 
413 {
414    if (getAddressWidth() == 4) { // 32 bit mutatee
415    } else { // 64 bit mutatee, have to use ifdef, otherwise it won't
416       // compile on a 32 bit machine
417       if (numparams > 0) {
418          params[0] = regs->gprs.rdi;
419       }
420       if (numparams > 1) {
421          params[1] = regs->gprs.rsi;
422       }
423       if (numparams > 2) {
424          params[2] = regs->gprs.rdx;
425       }
426       if (numparams > 3) {
427          params[3] = regs->gprs.r8;
428       }
429       if (numparams > 4) {
430          params[4] = regs->gprs.r9;
431       }
432       if (numparams > 5) {
433          params[5] = regs->gprs.r10;
434       }
435       for (int i=6; i < numparams; i++) {
436          if (!readDataSpace((void*)regs->gprs.rsp, getAddressWidth(), 
437                   (void*)(params + i * getAddressWidth()), true)) {
438             return false;
439          }
440       }
441    }
442    return true;
443 }
444
445 int process::getSysCallNumber(dyn_saved_regs *regs) {
446    return regs->gprs.orig_rax;
447 }
448
449 long process::getSysCallReturnValue(dyn_saved_regs *regs) {
450    return regs->gprs.rax;
451 }
452
453 Address process::getSysCallProgramCounter(dyn_saved_regs *regs) {
454    return regs->gprs.rip;
455 }
456
457 bool process::isMmapSysCall(int callnum) {
458    if (getAddressWidth() == 4) {
459       startup_printf("CALLNUM=%d\n",callnum);
460    }
461    return callnum == SYS_mmap;
462 }
463
464 Offset process::getMmapLength(int, dyn_saved_regs *regs) {
465    return (Offset) regs->gprs.rsi;
466 }
467
468 Address process::getLibcStartMainParam(dyn_lwp *trappingLWP) {
469    Address mainaddr = 0;
470    dyn_saved_regs regs;
471    trappingLWP->getRegisters(&regs);
472    if (getAddressWidth() == 4) { // 32 bit mutatee
473       if (!readDataSpace((void*)(regs.gprs.rsp + getAddressWidth()),
474                getAddressWidth(), (void*)&mainaddr,true)) {
475          fprintf(stderr,"[%s][%d]: failed readDataSpace\n", __FILE__,__LINE__); 
476       }
477    } else { // 64 bit mutatee
478       mainaddr = regs.gprs.rdi;
479    }
480    return mainaddr;
481 }
482 // 64 bit architecture
483 #else 
484 // 32 bit architecture
485 bool process::getSysCallParameters(dyn_saved_regs *regs, 
486       long *params, int numparams) {
487    if (numparams > 0) {
488       params[0] = regs->gprs.ebx;
489    }
490    if (numparams > 1) {
491       params[1] = regs->gprs.ecx;
492    }
493    if (numparams > 2) {
494       params[2] = regs->gprs.edx;
495    }
496    if (numparams > 3) {
497       params[3] = regs->gprs.esi;
498    }
499    if (numparams > 4) {
500       params[4] = regs->gprs.edi;
501    }
502    if (numparams > 5) {
503       params[5] = regs->gprs.ebp;
504    }
505    for (int i=6; i < numparams; i++) {
506       if (!readDataSpace((void*)regs->gprs.esp, getAddressWidth(), 
507                (void*)(params + i * getAddressWidth()), true)) {
508          return false;
509       }
510    }
511    return true;
512 }
513
514 int process::getSysCallNumber(dyn_saved_regs *regs) 
515 {
516    return regs->gprs.orig_eax;
517 }
518
519 long process::getSysCallReturnValue(dyn_saved_regs *regs) 
520 {
521    return regs->gprs.eax;
522 }
523
524 Address process::getSysCallProgramCounter(dyn_saved_regs *regs) 
525 {
526    return regs->gprs.eip;
527 }
528
529 bool process::isMmapSysCall(int callnum) {
530    return (callnum == SYS_mmap || callnum == SYS_mmap2);
531 }
532
533 Offset process::getMmapLength(int callnum, dyn_saved_regs *regs) 
534 {
535    if (callnum == SYS_mmap) {
536       Offset length;
537       readDataSpace((void*)(regs->gprs.ebx + getAddressWidth()),
538             getAddressWidth(), (void*)&length, true);
539       return length;
540    }
541    else {
542       return (Offset) regs->gprs.ecx;
543    }
544 }
545
546 Address process::getLibcStartMainParam(dyn_lwp *trappingLWP) 
547 {
548    dyn_saved_regs regs;
549    trappingLWP->getRegisters(&regs);
550    Address mainaddr;
551    if (!readDataSpace((void*)(regs.gprs.esp + getAddressWidth()),
552             getAddressWidth(), (void*)&mainaddr,true)) {
553       fprintf(stderr,"[%s][%d]: failed readDataSpace\n", __FILE__,__LINE__); 
554    }
555    return mainaddr;
556
557
558 #endif
559
560 void process::setTraceSysCalls(bool traceSys) 
561 {
562    traceSysCalls_ = traceSys;
563 }
564
565 void process::setTraceState(traceState_t state) 
566 {
567    traceState_ = state;
568 }
569
570 /* For cases in which we are unable to locate the mutatee's main function
571  * via our normal findMain heuristics, we resort to tracing system calls
572  * looking for libc to be loaded.  Here we decode the different system
573  * that we see during process startup. 
574  */
575 bool process::decodeStartupSysCalls(EventRecord &ev) 
576 {
577    // set up parameters & variables, which is platform dependent
578    const int NUMPARAMS = 6;
579    dyn_saved_regs regs;
580    ev.lwp->getRegisters(&regs);
581    long params[NUMPARAMS];
582    int callnum = getSysCallNumber(&regs);
583    long retval = getSysCallReturnValue(&regs);
584    Address programCounter = getSysCallProgramCounter(&regs);
585    getSysCallParameters(&regs, params, NUMPARAMS);
586
587    int traceerr = 0;
588    ev.type = evtNullEvent;
589    int addrWidth=getAddressWidth();
590
591    startup_printf("%s[%d]: decodeStartupSysCalls got tracestate=%d callnum=%d PC=0x%lx\n", 
592          FILE__, __LINE__, getTraceState(), callnum, programCounter);
593
594    // mmap syscall (there are multiple mmap syscalls on some platforms)
595    // store the start and end addresses of the region so that we can later
596    // determine which of the regions contains main
597    if (isMmapSysCall(callnum)) {
598       if (retval == -ENOSYS) { // grab the mmap region end address
599          mappedRegionEnd.push_back(getMmapLength(callnum, &regs));
600       } else { // the return value of mmap is the region's start address
601          mappedRegionStart.push_back(retval);
602          // turn the OFFSET we put into mappedRegionEnd into an absolute Address
603          mappedRegionEnd[mappedRegionEnd.size()-1] 
604             = mappedRegionEnd[mappedRegionEnd.size()-1] + retval;
605          startup_printf("%s[%d]: traced mmap syscall for region[0x%x 0x%x]\n",
606                __FILE__,__LINE__,
607                (int)mappedRegionStart[mappedRegionStart.size()-1],
608                (int)mappedRegionEnd[mappedRegionEnd.size()-1]);
609       }
610    }
611    // munmap: we also keep track of memory regions that are removed
612    else if (callnum==SYS_munmap && retval == -ENOSYS) { 
613       Address regionStart = params[0];
614       munmappedRegions.push_back(regionStart);
615       startup_printf("%s[%d]: traced munmap syscall for region at 0x%x\n",
616             __FILE__,__LINE__, (int)regionStart);
617    }
618
619    // switch on state, this is an automaton
620    switch (getTraceState()) { 
621       case libcOpenCall_ts: // wait for call to open libc.so
622          if(callnum == SYS_open) { // open syscall
623             char *oneword = (char*) malloc(addrWidth);
624             char *pathbuffer = (char*) malloc(256);
625             char *ptr = pathbuffer;
626             int lastchar = addrWidth;
627             Address stringAddr = params[0];
628             // recover the opened path from the call's arguments
629             do {
630                if (!readDataSpace((void*)stringAddr, addrWidth,
631                         (void*)oneword,true)) {
632                   fprintf(stderr,"%s[%d]: failed readDataSpace\n",FILE__,__LINE__ );
633                   return false;
634                }
635                strncpy(ptr, oneword, addrWidth);
636                stringAddr += addrWidth; 
637                ptr += addrWidth;
638                for (int idx=0; idx < addrWidth; idx++) {
639                   if (oneword[idx] == '\0') {
640                      lastchar = idx;
641                   }
642                }
643             }while (ptr - pathbuffer < 256 && lastchar == addrWidth);
644             pathbuffer[255] = '\0';
645             // if the path matches libc.so, transition state
646             if (strstr(pathbuffer, "libc.so")) {
647                setTraceState(libcOpenRet_ts);
648             }
649             free(pathbuffer);
650             free(oneword);
651          } // end if syscall to open
652          break;
653       case libcOpenRet_ts: // Save file-handle returned by open
654          // syscall on libc
655          if(callnum == SYS_open) { // call to open
656             if (retval >= 0) {
657                libcHandle_ = retval; 
658                setTraceState(libcClose_ts);
659             }
660             else {// open syscall was unsuccessful, revert to previous state
661                setTraceState(libcOpenCall_ts);
662             }
663          }
664          break;
665       case libcClose_ts:  //find close syscall matching libc open 
666          if (callnum == SYS_close && retval == -ENOSYS) {
667             int fd = params[0];
668             if (traceerr != 0) { 
669                fprintf(stderr,"[%s][%d]: ptrace err here\n", __FILE__,__LINE__); 
670             }
671             if (fd == libcHandle_) { // found close
672                setTraceState(instrumentLibc_ts); 
673                setBootstrapState(libcLoaded_bs);
674                ev.type = evtLibcLoaded;
675             }
676          }
677          break;
678       case instrumentLibc_ts: // results in handling of trap in startmain 
679          if (abs((long)getlibcstartmain_brk_addr() -(long)programCounter) <= 1) {
680             setTraceState(done_ts);
681             setTraceSysCalls(false);
682             ev.type = evtLibcTrap;
683          }
684          else {
685             return false;
686          }
687          break;
688       default:
689          fprintf(stderr,"[%s][%d] Internal error, should not reach this point\n",
690                __FILE__,__LINE__);
691          return false;
692    }// end switch statement
693    return true;
694 }// end decodeStartupSysCalls
695
696 /* Find libc and add it as a shared object
697  * Search for __libc_start_main
698  * Save old code at beginning of __libc_start_main
699  * Insert trap
700  * Signal thread to continue
701  */
702 bool process::instrumentLibcStartMain() 
703 {
704     unsigned int maps_size =0;
705     map_entries *maps = getLinuxMaps(getPid(), maps_size);
706     unsigned int libcIdx=0;
707     while (libcIdx < maps_size &&
708            ! (strstr(maps[libcIdx].path,"/libc")
709               && strstr(maps[libcIdx].path,".so"))) {
710        libcIdx++;
711     }
712     assert(libcIdx != maps_size);
713     //KEVINTODO: address code and data are not always 0,0: need to fix this
714     fileDescriptor libcFD = fileDescriptor(maps[libcIdx].path,0,0,true);
715     mapped_object *libc = mapped_object::createMappedObject(libcFD, this);
716     addASharedObject(libc);
717
718     // find __libc_startmain
719     const pdvector<int_function*> *funcs;
720     funcs = libc->findFuncVectorByPretty("__libc_start_main");
721     if(funcs->size() == 0 || (*funcs)[0] == NULL) {
722         logLine( "Couldn't find __libc_start_main\n");
723         return false;
724     } else if (funcs->size() > 1) {
725        startup_printf("[%s:%u] - Found %d functions called __libc_start_main, weird\n",
726                       FILE__, __LINE__, funcs->size());
727     }
728     if (!(*funcs)[0]->isInstrumentable()) {
729         logLine( "__libc_start_main is not instrumentable\n");
730         return false;
731     }
732     Address addr = (*funcs)[0]->getAddress();
733     startup_printf("%s[%d]: Instrumenting libc.so:__libc_start_main() at 0x%x\n", 
734                    FILE__, __LINE__, (int)addr);
735
736     // save original code at beginning of function
737     if (!readDataSpace((void *)addr, sizeof(savedCodeBuffer),savedCodeBuffer,true)) {
738         fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
739         fprintf(stderr, "%s[%d][%s]:  failing instrumentLibcStartMain\n",
740             __FILE__, __LINE__, getThreadStr(getExecThreadID()));
741       fprintf(stderr, "Failed to read at address 0x%lx\n", addr);
742       return false;
743    }
744    startup_printf("%s[%d]: Saved %d bytes from entry of __libc_start_main\n", 
745          FILE__, __LINE__, sizeof(savedCodeBuffer));
746    // insert trap
747    codeGen gen(1);
748    insnCodeGen::generateTrap(gen);
749    if (!writeDataSpace((void *)addr, gen.used(), gen.start_ptr())) {
750       fprintf(stderr, "%s[%d][%s]:  failing instrumentLibcStartMain\n",
751             __FILE__, __LINE__, getThreadStr(getExecThreadID()));
752       return false;
753    }
754    libcstartmain_brk_addr = addr;
755    continueProc(); // signal process to continue
756    return true;
757 }// end instrumentLibcStartMain
758
759
760 /* Read parameters to startmain including the address of main.
761  * See if there's an existing mapped object that contains the address of
762  *   main, which we'll call a_out, and set to be a.out for the process
763  * Restore original instruction in the libc library
764  * Call insertTrapAtMain
765  */
766 bool process::handleTrapAtLibcStartMain(dyn_lwp *trappingLWP)
767 {
768     assert(libcstartmain_brk_addr);
769     assert(trappingLWP);
770
771     // Read the parameters from the call to libcStartMain
772     Address mainaddr = getLibcStartMainParam(trappingLWP);
773     mapped_object *a_out = findObject(mainaddr);
774
775     char namebuf[64];
776     Address regionStart = 0;
777     Address regionEnd = 0;
778     // there might not be an object that corresponds to the a_out
779     if (a_out == NULL) {
780         // determine confines of region that encloses main, search from
781         // end to get most recent mmap of an enclosing region
782         int idx =  (int)mappedRegionStart.size()-1;
783         while (idx >= 0  && 
784                !(mappedRegionStart[idx] <= mainaddr 
785                  && mainaddr <= mappedRegionEnd[idx])) {
786             idx--;
787         }
788         if (idx < 0) {
789             fprintf(stderr,"%s[%d] No valid memory region seems to contain "
790                     "the address of main=0x%x\n",__FILE__,__LINE__, 
791                     (int)mainaddr);
792             return false;
793         }
794         regionStart = mappedRegionStart[idx];
795         regionEnd = mappedRegionEnd[idx];
796         startup_printf("main(0x%x) is in region [0x%X 0x%X]\n", 
797                        (int)mainaddr, (int)regionStart, (int)regionEnd);
798
799         // found the right region, copy its contents to a temp file
800         void *regionBuf = malloc(regionEnd - regionStart);
801         if (!readDataSpace((void*)regionStart, regionEnd-regionStart, 
802                           regionBuf, false)) {
803             fprintf(stderr, "%s[%d]: Failed to read from region [%X %X]\n",
804                        __FILE__, __LINE__,(int)regionStart, 
805                        (int)regionEnd);
806         }
807         // Make sure bytes 12-15 of magic header are set to 0 (for x86-64 bit)
808         ((int*)regionBuf)[3] = 0;
809         // We have no section information, so don't try to point to it
810         ((int*)regionBuf)[10] = 0;
811
812         snprintf(namebuf, 64, "/tmp/MemRegion_%X_%X", 
813                  (int)regionStart, (int)regionEnd);
814         namebuf[63]='\0';
815         FILE *regionFD = fopen(namebuf, "w");
816         assert(regionFD != NULL);
817         fwrite(regionBuf, 1, regionEnd-regionStart, regionFD);
818         fclose(regionFD);
819         free(regionBuf);
820         startup_printf("%s[%d]: Read region [%X %X] into temp file %s\n",
821                        __FILE__, __LINE__,(int)regionStart, 
822                        (int)regionEnd, namebuf);
823
824         //KEVINTODO: address code and data are not always 0,0: need to fix this
825         // create a fileDescriptor and a new mapped_object for the region
826         // create it as though it were a shared object
827         fileDescriptor fdesc = fileDescriptor(namebuf, 0, 0, true);
828         a_out = mapped_object::createMappedObject(fdesc, this);
829
830         // There is no function for adding an a.out, so we'll call
831         // addASharedObject, and switch the old a.out to be this one.
832         // a.out is always the first object in the mapped_objects
833         // vector, our new mapped_object should be at or near the end.
834         addASharedObject(a_out);
835         idx = mapped_objects.size() -1;
836         while (mapped_objects[idx] != a_out && idx >= 0) {
837             idx--;
838         }
839         assert(idx >= 0);
840         mapped_objects[idx] = mapped_objects[0];
841         mapped_objects[0] = a_out;
842         ((fileDescriptor)(a_out->getFileDesc())).setIsShared(false);
843     }
844     else {// (a_out != NULL)
845         regionStart = a_out->getFileDesc().loadAddr();
846         regionEnd = regionStart + a_out->imageSize();
847     }
848
849     // if gap parsing is on, check for a function at mainaddr, rename
850     // it to "main" and set main_function to its int_function
851     int_function* mainfunc = NULL;
852     if (a_out->parse_img()->parseGaps()) {
853         a_out->analyze();
854         snprintf(namebuf,64,"gap_%lx", (long)mainaddr);
855         int_function* mainfunc = findOnlyOneFunction(namebuf,a_out->fileName());
856         if (mainfunc) {
857             mainfunc->addSymTabName("main", true);
858             mainfunc->addPrettyName("main", true);
859             main_function = mainfunc;
860             startup_printf("found main via gap parsing at %x in mapped_obj [%x %x]\n",
861                            (int)main_function->getAddress(),
862                            (int)a_out->getFileDesc().loadAddr(),
863                            (int)(a_out->getFileDesc().loadAddr() + a_out->imageSize()));
864         }
865     }
866     // parse the binary with "main" as a function location
867     if (!mainfunc) {
868         startup_printf("Parsing main at 0x%x in mapped object [%x %x]"
869                        " which is its location according to __libc_start_main \n",
870                 (int)mainaddr,
871                 (int)a_out->getFileDesc().loadAddr(),
872                 (int)(a_out->getFileDesc().loadAddr() + a_out->imageSize()));
873         // add function stub and parsed object
874         a_out->parse_img()->addFunction(mainaddr, "main");
875         a_out->analyze(); 
876     }
877
878    // Restore __libc_start_main to its original state
879    if (!writeDataSpace((void *)libcstartmain_brk_addr, 
880             sizeof(savedCodeBuffer), 
881             (char *)savedCodeBuffer)) {
882       fprintf(stderr, "%s[%d]: Failed to restore code in libcstartmain at 0x%X\n",
883             __FILE__, __LINE__,(int)libcstartmain_brk_addr);
884       return false;
885    }
886    if (! trappingLWP->changePC(libcstartmain_brk_addr,NULL)) {
887       logLine("WARNING: in handleTrapAtLibcStartMain: "
888             "changePC failed in handleTrapAtLibcStartmain\n");
889       assert(0);
890    }
891    libcstartmain_brk_addr = 0;
892    // now let insertTrapAtEntryPointOfMain insert the trap at main
893    return insertTrapAtEntryPointOfMain();
894 }// handleTrapAtLibcStartmain
895
896
897 extern bool isFramePush(instruction &i);
898
899 /**
900  * Signal handler return points can be found in the vsyscall page.
901  * this function reads the symbol information that describes these
902  * points out of the vsyscall page.
903  **/
904 #define VSYS_SIGRETURN_NAME "_sigreturn"
905 static void getVSyscallSignalSyms(char *buffer, unsigned dso_size, process *p)
906 {
907    Elf_Scn *sec;
908    Elf32_Shdr *shdr;
909    Elf32_Ehdr *ehdr;
910    Elf32_Sym *syms;
911    unsigned i;
912    size_t dynstr = 0, shstr;
913    
914    Elf *elf = elf_memory(buffer, dso_size);
915    if (elf == NULL)
916       goto err_handler;
917    ehdr = elf32_getehdr(elf);
918    if (ehdr == NULL)
919       goto err_handler;
920    
921    //Get string section indexes
922    shstr = ehdr->e_shstrndx;
923    for (i = 0; i < ehdr->e_shnum; i++)
924    {
925       shdr = elf32_getshdr(elf_getscn(elf, i));
926       if (shdr != NULL && shdr->sh_type == SHT_STRTAB &&        
927           strcmp(elf_strptr(elf, shstr, shdr->sh_name), ".dynstr") == 0)
928       {
929          dynstr = i;
930          break;
931       }
932    }
933    
934    //For each section..
935    for (sec = elf_nextscn(elf, NULL); sec != NULL; sec = elf_nextscn(elf, sec))
936    {
937       shdr = elf32_getshdr(sec);
938       if (shdr == NULL) goto err_handler;
939       if (!p->getVsyscallText() && (shdr->sh_flags & SHF_EXECINSTR)) {
940          p->setVsyscallText(shdr->sh_addr);
941       }
942       if (shdr->sh_type == SHT_DYNSYM)
943       {
944          syms = (Elf32_Sym *) elf_getdata(sec, NULL)->d_buf;
945          //For each symbol ..
946          for (i = 0; i < (shdr->sh_size / sizeof(Elf32_Sym)); i++)
947          {
948             if ((syms[i].st_info & 0xf) == STT_FUNC)
949             {
950                //Check if this is a function symbol
951                char *name = elf_strptr(elf, dynstr, syms[i].st_name);
952                if (strstr(name, VSYS_SIGRETURN_NAME) != NULL)
953                {            
954                   // Aggravating... FC3 has these as offsets from the entry
955                   // of the vsyscall page. Others have these as absolutes.
956                   // We hates them, my precioussss....
957                   Address signal_addr = syms[i].st_value;
958                   if (signal_addr < p->getVsyscallEnd() - p->getVsyscallStart()) {
959                      p->addSignalHandler(syms[i].st_value + 
960                                          p->getVsyscallStart(), 4);
961                   }
962                   else if (signal_addr < p->getVsyscallStart() ||
963                            signal_addr >= p->getVsyscallEnd()) {
964                      //FC-9 moved the vsyscall page, but didn't update its debug
965                      // info or symbols from some hardcoded values.  Fix up the
966                      // bad signal values.
967                      p->addSignalHandler(syms[i].st_value - 0xffffe000 +
968                                          p->getVsyscallStart(), 4);
969                   }
970                   else 
971                      p->addSignalHandler(syms[i].st_value, 4);
972                } 
973             }
974          }
975       }
976    }
977    
978    elf_end(elf);
979    return;
980
981 err_handler:
982    if (elf != NULL)
983       elf_end(elf);
984 }
985
986 static volatile int segfaulted = 0;
987 static void catchSigSegV(int) {
988    segfaulted = 1;
989 }
990
991 static char *execVsyscallFetch(process *p, char *buffer) {
992    //We can't read the Vsyscall page out of the process addr
993    // space do to a kernel bug.  However, the versions of the
994    // kernel with this bug don't move the vsyscall page between
995    // processes, so let's read it out of the mutator's.
996    //Latter versions of the kernel do move the page between
997    // processes, which makes our read attempt seg fault.  Let's
998    // install a handler to be safe.
999    volatile char *start;
1000    unsigned size;
1001    sighandler_t old_segv;
1002
1003    segfaulted = 0;
1004    start = (char *) p->getVsyscallStart();
1005    size = p->getVsyscallEnd() - p->getVsyscallStart();
1006
1007    //Install SegSegV handler.
1008    old_segv = signal(SIGSEGV, catchSigSegV);
1009
1010    //Copy buffer
1011    for (unsigned i=0; i<size; i++) {
1012       buffer[i] = start[i];
1013       if (segfaulted) 
1014          break;
1015    }
1016
1017    //Restore handler.
1018    signal(SIGSEGV, old_segv);
1019    if (segfaulted)
1020       return NULL;
1021    return buffer;
1022 }
1023
1024 static bool isVsyscallData(char *buffer, int dso_size) {
1025    //Start with an elf header?
1026    if (dso_size < 4)
1027       return false;
1028    return (buffer[0] == 0x7f && buffer[1] == 'E' && buffer[2] == 'L' &&
1029            buffer[3] == 'F');
1030    
1031 }
1032
1033
1034 void calcVSyscallFrame(process *p)
1035 {
1036   unsigned dso_size;
1037   char *buffer;
1038
1039   /**
1040    * If we've already calculated and cached the DSO information then 
1041    * just return.
1042    **/
1043   if (p->getVsyscallObject())
1044      return;
1045   
1046
1047   if (p->getAddressWidth() == 8) {
1048      // FIXME: HACK to disable vsyscall page for AMD64, for now.
1049      //  Reading the VSyscall data on ginger seems to trigger a
1050      //  kernel panic.
1051      p->setVsyscallRange(0x1000, 0x0);
1052      return;
1053   }
1054
1055   /**
1056    * Read the location of the vsyscall page from /proc/.
1057    **/
1058   p->readAuxvInfo();
1059   if (p->getVsyscallStatus() != vsys_found) {
1060      p->setVsyscallRange(0x0, 0x0);
1061      return;
1062   }
1063   
1064   /**
1065    * Read the vsyscall page out of process memory.
1066    **/
1067   dso_size = p->getVsyscallEnd() - p->getVsyscallStart();
1068   buffer = (char *) calloc(1, dso_size);
1069   assert(buffer);
1070   if (!p->readDataSpace((caddr_t)p->getVsyscallStart(), dso_size, buffer,false))     
1071   {
1072      int major, minor, sub;
1073      get_linux_version(major, minor, sub);
1074      if (major == 2 && minor == 6 && sub <= 2 && sub >= 0) {
1075         //Linux 2.6.0 - Linux 2.6.2 has a  bug where ptrace 
1076         // can't read from the DSO.  The process can read the memory, 
1077         // it's just ptrace that's acting stubborn.
1078         if (!execVsyscallFetch(p, buffer))
1079         {
1080            p->setVsyscallStatus(vsys_notfound);
1081            return;
1082         }
1083      }
1084   }
1085
1086   if (!isVsyscallData(buffer, dso_size)) {
1087      p->setVsyscallRange(0x0, 0x0);
1088      p->setVsyscallStatus(vsys_notfound);
1089      return;     
1090   }
1091   getVSyscallSignalSyms(buffer, dso_size, p);
1092
1093   Symtab *obj;
1094   bool result = Symtab::openFile(obj, buffer, dso_size);
1095   if (result)
1096      p->setVsyscallObject(obj);
1097   return;
1098 }
1099
1100 bool Frame::setPC(Address newpc) {
1101    if (!pcAddr_)
1102    {
1103        //fprintf(stderr, "[%s:%u] - Frame::setPC aborted", __FILE__, __LINE__);
1104       return false;
1105    }
1106
1107    //fprintf(stderr, "[%s:%u] - Frame::setPC setting %x to %x",
1108    //__FILE__, __LINE__, pcAddr_, newpc);
1109    if (!getProc()->writeDataSpace((void*)pcAddr_, sizeof(Address), &newpc))
1110       return false;
1111    pc_ = newpc;
1112    range_ = NULL;
1113
1114    return true;
1115 }
1116
1117 // Laziness here: this func is used by the iRPC code
1118 // to get result registers. Don't use it other than that. 
1119
1120 Address dyn_lwp::readRegister(Register /*reg*/) {
1121    // On x86, the result is always stashed in %EAX
1122    if(status() == running) {
1123       cerr << "    performance problem in call to dyn_lwp::readRegister\n"
1124            << "       successive pauses and continues with ptrace calls\n";
1125    }
1126
1127    int ptrace_errno = 0;
1128    Address ret = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(), P_offsetof(struct user_regs_struct, PTRACE_REG_AX), 0,
1129                         &ptrace_errno, proc_->getAddressWidth(),  __FILE__, __LINE__);
1130    return ret;
1131 }
1132
1133
1134 void print_read_error_info(const relocationEntry entry, 
1135       int_function *&target_pdf, Address base_addr) {
1136
1137     sprintf(errorLine, "  entry      : target_addr 0x%x\n",
1138             (unsigned)entry.target_addr());
1139     logLine(errorLine);
1140     sprintf(errorLine, "               rel_addr 0x%x\n", (unsigned)entry.rel_addr());
1141     logLine(errorLine);
1142     sprintf(errorLine, "               name %s\n", (entry.name()).c_str());
1143     logLine(errorLine);
1144
1145     if (target_pdf) {
1146       sprintf(errorLine, "  target_pdf : symTabName %s\n",
1147               (target_pdf->symTabName()).c_str());
1148       logLine(errorLine);    
1149       sprintf(errorLine , "              prettyName %s\n",
1150               (target_pdf->symTabName()).c_str());
1151       logLine(errorLine);
1152       /*
1153       // Size bad. <smack>
1154       sprintf(errorLine , "              size %i\n",
1155       target_pdf->getSize());
1156       logLine(errorLine);
1157       */
1158       sprintf(errorLine , "              addr 0x%x\n",
1159               (unsigned)target_pdf->getAddress());
1160       logLine(errorLine);
1161     }
1162     sprintf(errorLine, "  base_addr  0x%x\n", (unsigned)base_addr);
1163     logLine(errorLine);
1164 }
1165
1166 // hasBeenBound: returns true if the runtime linker has bound the
1167 // function symbol corresponding to the relocation entry in at the address
1168 // specified by entry and base_addr.  If it has been bound, then the callee 
1169 // function is returned in "target_pdf", else it returns false.
1170 bool process::hasBeenBound(const relocationEntry &entry, 
1171                            int_function *&target_pdf, Address base_addr) {
1172
1173     if (status() == exited) return false;
1174
1175     // if the relocationEntry has not been bound yet, then the value
1176     // at rel_addr is the address of the instruction immediately following
1177     // the first instruction in the PLT entry (which is at the target_addr) 
1178     // The PLT entries are never modified, instead they use an indirrect 
1179     // jump to an address stored in the _GLOBAL_OFFSET_TABLE_.  When the 
1180     // function symbol is bound by the runtime linker, it changes the address
1181     // in the _GLOBAL_OFFSET_TABLE_ corresponding to the PLT entry
1182
1183     Address got_entry = entry.rel_addr() + base_addr;
1184     Address bound_addr = 0;
1185     if(!readDataSpace((const void*)got_entry, sizeof(Address), 
1186                         &bound_addr, true)){
1187         sprintf(errorLine, "read error in process::hasBeenBound addr 0x%x, pid=%d\n (readDataSpace returns 0)",(unsigned)got_entry,getPid());
1188         logLine(errorLine);
1189         print_read_error_info(entry, target_pdf, base_addr);
1190         return false;
1191     }
1192
1193     if( !( bound_addr == (entry.target_addr()+6+base_addr)) ) {
1194         // the callee function has been bound by the runtime linker
1195         // find the function and return it
1196         target_pdf = findFuncByAddr(bound_addr);
1197         if(!target_pdf){
1198             return false;
1199         }
1200         return true;    
1201     }
1202     return false;
1203 }
1204
1205 bool AddressSpace::getDyninstRTLibName() {
1206    startup_printf("dyninstRT_name: %s\n", dyninstRT_name.c_str());
1207     if (dyninstRT_name.length() == 0) {
1208         // Get env variable
1209         if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
1210             dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
1211         }
1212         else {
1213            std::string msg;
1214            process *proc;
1215            if ((proc = dynamic_cast<process *>(this)) != NULL) {
1216               msg = std::string("Environment variable ") +
1217                  std::string("DYNINSTAPI_RT_LIB") +
1218                  std::string(" has not been defined for process ") +
1219                  utos(proc->getPid());
1220            }
1221            else {
1222               msg = std::string("Environment variable ") +
1223                  std::string("DYNINSTAPI_RT_LIB") +
1224                  std::string(" has not been defined");
1225            }           
1226            showErrorCallback(101, msg);
1227            return false;
1228         }
1229     }
1230
1231     // Automatically choose 32-bit library if necessary.
1232     const char *modifier = "_m32";
1233     const char *name = dyninstRT_name.c_str();
1234
1235     const char *split = P_strrchr(name, '/');
1236     if ( !split ) split = name;
1237     split = P_strchr(split, '.');
1238     if ( !split || P_strlen(split) <= 1 ) {
1239         // We should probably print some error here.
1240         // Then, of course, the user will find out soon enough.
1241         startup_printf("Invalid Dyninst RT lib name: %s\n", 
1242                 dyninstRT_name.c_str());
1243         return false;
1244     }
1245
1246     if ( getAddressWidth() == sizeof(void *) || P_strstr(name, modifier) ) {
1247         modifier = "";
1248     }
1249
1250     const char *suffix = split;
1251     if( getAOut()->isStaticExec() ) {
1252         suffix = ".a";
1253     }else{
1254         if( P_strncmp(suffix, ".a", 2) == 0 ) {
1255           // Add symlinks in makefiles as follows:
1256           // (lib).so => lib.so.(major)
1257           // lib.so.major => lib.so.major.minor
1258           // lib.so.major.minor => lib.so.major.minor.maintenance
1259           suffix = ".so";
1260         }
1261     }
1262
1263     dyninstRT_name = std::string(name, split - name) +
1264                      std::string(modifier) +
1265                      std::string(suffix);
1266
1267     startup_printf("Dyninst RT Library name set to '%s'\n",
1268             dyninstRT_name.c_str());
1269
1270     // Check to see if the library given exists.
1271     if (access(dyninstRT_name.c_str(), R_OK)) {
1272         std::string msg = std::string("Runtime library ") + dyninstRT_name
1273         + std::string(" does not exist or cannot be accessed!");
1274         showErrorCallback(101, msg);
1275         return false;
1276     }
1277
1278     return true;
1279 }
1280
1281 bool process::loadDYNINSTlib()
1282 {
1283     pdvector<int_function *> dlopen_funcs;
1284
1285         //  allow user to override default dlopen func names 
1286         //  with env. var
1287
1288         DL_OPEN_FUNC_USER = getenv("DYNINST_DLOPEN_FUNC");
1289
1290         if (DL_OPEN_FUNC_USER)
1291         {
1292                 if (findFuncsByAll(DL_OPEN_FUNC_USER, dlopen_funcs)) 
1293                 {
1294                         bool ok =  loadDYNINSTlib_exported(DL_OPEN_FUNC_USER);
1295
1296                         if (ok) 
1297                                 return true;
1298
1299                         //  else fall through and try the default dlopen names
1300                 } 
1301         }
1302
1303     if (findFuncsByAll(DL_OPEN_FUNC_EXPORTED, dlopen_funcs)) 
1304         {
1305                 return loadDYNINSTlib_exported(DL_OPEN_FUNC_EXPORTED);
1306     } 
1307     else 
1308         {
1309                 return loadDYNINSTlib_hidden();
1310     }
1311 }
1312
1313 // Defined in inst-x86.C...
1314 void emitPushImm(unsigned int imm, unsigned char *&insn); 
1315
1316 bool process::loadDYNINSTlib_hidden() {
1317 #if false && defined(PTRACEDEBUG)
1318   debug_ptrace = true;
1319 #endif
1320   startup_printf("**** LIBC21 dlopen for RT lib\n");
1321   // do_dlopen takes a struct argument. This is as follows:
1322   // const char *libname;
1323   // int mode;
1324   // void *result;
1325   // void *caller_addr
1326   // Now, we have to put this somewhere writable. The idea is to
1327   // put it on the stack....
1328
1329   Address codeBase = findFunctionToHijack(this);
1330
1331   if(!codeBase)
1332   {
1333       startup_cerr << "Couldn't find a point to insert dlopen call" << endl;
1334       return false;
1335   }
1336
1337   startup_printf("(%d) writing in dlopen call at addr %p\n", getPid(), (void *)codeBase);
1338
1339   codeGen scratchCodeBuffer(MAX_IRPC_SIZE);
1340   scratchCodeBuffer.setAddrSpace(this);
1341   scratchCodeBuffer.setRegisterSpace(registerSpace::irpcRegSpace(this));
1342
1343   // we need to make a call to dlopen to open our runtime library
1344
1345   // Variables what we're filling in
1346   Address dyninstlib_str_addr = 0;
1347   Address dlopen_call_addr = 0;
1348
1349   pdvector<int_function *> dlopen_funcs;
1350   if (!findFuncsByAll(DL_OPEN_FUNC_NAME, dlopen_funcs))
1351   {
1352     pdvector<int_function *> dlopen_int_funcs;                                    
1353     // If we can't find the do_dlopen function (because this library
1354     // is stripped, for example), try searching for the internal
1355     // _dl_open function and find the do_dlopen function by examining
1356     // the functions that call it. This depends on the do_dlopen
1357     // function having been parsed (though its name is not known)
1358     // through speculative parsing.
1359     if(!findFuncsByAll(DL_OPEN_FUNC_INTERNAL, dlopen_int_funcs))
1360     {    
1361       startup_printf("Failed to find _dl_open\n");
1362     } 
1363     else
1364     { 
1365       if(dlopen_int_funcs.size() > 1)
1366         {
1367             startup_printf("%s[%d] warning: found %d matches for %s\n",
1368                            __FILE__,__LINE__,dlopen_int_funcs.size(),
1369                            DL_OPEN_FUNC_INTERNAL);
1370         }
1371         dlopen_int_funcs[0]->getStaticCallers(dlopen_funcs);
1372         if(dlopen_funcs.size() > 1)
1373         {
1374             startup_printf("%s[%d] warning: found %d do_dlopen candidates\n",
1375                            __FILE__,__LINE__,dlopen_funcs.size());
1376         }
1377   
1378         if(dlopen_funcs.size() > 0)
1379         {
1380             // give it a name
1381             dlopen_funcs[0]->addSymTabName("do_dlopen",true);
1382         }
1383     }
1384   }
1385
1386     if(dlopen_funcs.size() == 0)
1387     {
1388       startup_cerr << "Couldn't find method to load dynamic library" << endl;
1389       return false;
1390     } 
1391
1392   Address dlopen_addr = dlopen_funcs[0]->getAddress();
1393
1394   assert(dyninstRT_name.length() < BYTES_TO_SAVE);
1395   // We now fill in the scratch code buffer with appropriate data
1396   startup_cerr << "Dyninst RT lib name: " << dyninstRT_name << endl;
1397
1398   dyninstlib_str_addr = codeBase + scratchCodeBuffer.used();
1399   scratchCodeBuffer.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
1400
1401   startup_printf("(%d) dyninst str addr at 0x%x\n", getPid(), dyninstlib_str_addr);
1402
1403   startup_printf("(%d) after copy, %d used\n", getPid(), scratchCodeBuffer.used());
1404
1405
1406 #if defined(bug_syscall_changepc_rewind)
1407   // Reported by SGI, during attach to a process in a system call:
1408
1409   // Insert eight NOP instructions before the actual call to dlopen(). Loading
1410   // the runtime library when the mutatee was in a system call will sometimes
1411   // cause the process to (on IA32 anyway) execute the instruction four bytes
1412   // PREVIOUS to the PC we actually set here. No idea why. Prepending the
1413   // actual dlopen() call with eight NOP instructions insures this doesn't
1414   // really matter. Eight was selected rather than four because I don't know
1415   // if x86-64 does the same thing (and jumps eight bytes instead of four).
1416
1417   // We will put in <addr width> rather than always 8; this will be 4 on x86 and
1418   // 32-bit AMD64, and 8 on 64-bit AMD64.
1419
1420   scratchCodeBuffer.fill(getAddressWidth(), codeGen::cgNOP);
1421
1422   // And since we apparently execute at (addr - <width>), shift dlopen_call_addr
1423   // up past the NOPs.
1424 #endif
1425
1426   // Sync with whatever we've put in so far.
1427   dlopen_call_addr = codeBase + scratchCodeBuffer.used();
1428
1429   if( !theRpcMgr->emitInferiorRPCheader(scratchCodeBuffer) ) {
1430     startup_cerr << "Couldn't emit inferior RPC header" << endl;
1431     return false;
1432   }
1433
1434   // Since we are punching our way down to an internal function, we
1435   // may run into problems due to stack execute protection. Basically,
1436   // glibc knows that it needs to be able to execute on the stack in
1437   // in order to load libraries with dl_open(). It has code in
1438   // _dl_map_object_from_fd (the workhorse of dynamic library loading)
1439   // that unprotects a global, exported variable (__stack_prot), sets
1440   // the execute flag, and reprotects it. This only happens, however,
1441   // when the higher-level dl_open() functions (which we skip) are called,
1442   // as they append an undocumented flag to the library open mode. Otherwise,
1443   // assignment to the variable happens without protection, which will
1444   // cause a fault.
1445   //
1446   // Instead of chasing the value of the undocumented flag, we will
1447   // unprotect the __stack_prot variable ourselves (if we can find it).
1448
1449   if(!tryUnprotectStack(scratchCodeBuffer,codeBase)) {
1450     startup_printf("Failed to disable stack protection.\n");
1451   }
1452
1453 #if defined(cap_32_64)
1454   if (getAddressWidth() == 4) {
1455 #endif
1456
1457       // Push caller
1458       emitPushImm(dlopen_addr, scratchCodeBuffer);
1459       
1460       // Push hole for result
1461       emitPushImm(0, scratchCodeBuffer);
1462       
1463       // Push mode
1464       emitPushImm(DLOPEN_MODE, scratchCodeBuffer);
1465       
1466       // Push string addr
1467       emitPushImm(dyninstlib_str_addr, scratchCodeBuffer);
1468       
1469       // Push the addr of the struct: esp
1470       emitSimpleInsn(PUSHESP, scratchCodeBuffer);
1471       
1472       startup_printf("(%d): emitting call from 0x%x to 0x%x\n",
1473                      getPid(), codeBase + scratchCodeBuffer.used(), dlopen_addr);
1474       insnCodeGen::generateCall(scratchCodeBuffer, scratchCodeBuffer.used() + codeBase, dlopen_addr);
1475       
1476       const unsigned stackUsage = 5*4; // 5 pushes
1477       RealRegister esp(REGNUM_ESP);
1478       RealRegister enull(Null_Register);
1479       emitLEA(esp, enull, 0, stackUsage, esp, scratchCodeBuffer);
1480       scratchCodeBuffer.rs()->incStack(-(stackUsage-4)); // 4 registered pushes
1481
1482 #if defined(cap_32_64)
1483   } else {
1484       // Push caller
1485       emitMovImmToReg64(REGNUM_RAX, dlopen_addr, true, scratchCodeBuffer);
1486       emitSimpleInsn(0x50, scratchCodeBuffer); // push %rax
1487
1488       // Push hole for result
1489       emitSimpleInsn(0x50, scratchCodeBuffer); // push %rax
1490
1491       // Push padding and mode
1492       emitMovImmToReg64(REGNUM_EAX, DLOPEN_MODE, false, scratchCodeBuffer); // 32-bit mov: clears high dword
1493       emitSimpleInsn(0x50, scratchCodeBuffer); // push %rax
1494
1495       // Push string addr
1496       emitMovImmToReg64(REGNUM_RAX, dyninstlib_str_addr, true, scratchCodeBuffer);
1497       emitSimpleInsn(0x50, scratchCodeBuffer); // push %rax
1498       
1499       // Set up the argument: the current stack pointer
1500       emitMovRegToReg64(REGNUM_RDI, REGNUM_RSP, true, scratchCodeBuffer);
1501       
1502       // The call (must be done through a register in order to reach)
1503       emitMovImmToReg64(REGNUM_RAX, dlopen_addr, true, scratchCodeBuffer);
1504       emitSimpleInsn(0xff, scratchCodeBuffer); // group 5
1505       emitSimpleInsn(0xd0, scratchCodeBuffer); // mod = 11, ext_op = 2 (call Ev), r/m = 0 (RAX)
1506
1507       const unsigned stackUsage = 4*8; // 4 pushes
1508       emitLEA64(REGNUM_RSP, Null_Register, 0, stackUsage, REGNUM_RSP, true, scratchCodeBuffer);
1509   }
1510 #endif
1511
1512   // The break point address is computed by the following function
1513   unsigned breakOffset = 0;
1514   unsigned unused;
1515   if( !theRpcMgr->emitInferiorRPCtrailer(scratchCodeBuffer, breakOffset, 
1516                 false, unused, unused) ) 
1517   {
1518     startup_cerr << "Couldn't emit inferior RPC trailer" << endl;
1519     return false;
1520   }
1521   dyninstlib_brk_addr = codeBase + breakOffset;
1522
1523   startup_printf("(%d) dyninst lib string addr at 0x%x\n", getPid(), dyninstlib_str_addr);
1524   startup_printf("(%d) dyninst lib call addr at 0x%x\n", getPid(), dlopen_call_addr);
1525   startup_printf("(%d) break address is at %p\n", getPid(), (void *) dyninstlib_brk_addr);
1526   startup_printf("(%d) writing %d bytes\n", getPid(), scratchCodeBuffer.used());
1527
1528   // savedCodeBuffer[BYTES_TO_SAVE] is declared in process.h
1529   // We can tighten this up if we record how much we saved
1530
1531   if (!readDataSpace((void *)codeBase, sizeof(savedCodeBuffer), savedCodeBuffer, true))
1532          fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
1533
1534   startup_printf("(%d) Writing from %p to %p\n", getPid(), (char *)scratchCodeBuffer.start_ptr(), (char *)codeBase);
1535   writeDataSpace((void *)(codeBase), scratchCodeBuffer.used(), scratchCodeBuffer.start_ptr());
1536
1537   // save registers
1538   dyn_lwp *lwp_to_use = NULL;
1539   if(process::IndependentLwpControl() && getRepresentativeLWP() ==NULL)
1540      lwp_to_use = getInitialThread()->get_lwp();
1541   else
1542      lwp_to_use = getRepresentativeLWP();
1543
1544   savedRegs = new dyn_saved_regs;
1545   bool status = lwp_to_use->getRegisters(savedRegs);
1546
1547   assert((status!=false) && (savedRegs!=(void *)-1));
1548
1549   lwp_to_use = NULL;
1550
1551   if(process::IndependentLwpControl() && getRepresentativeLWP() ==NULL)
1552      lwp_to_use = getInitialThread()->get_lwp();
1553   else
1554      lwp_to_use = getRepresentativeLWP();
1555
1556   Address destPC = dlopen_call_addr;
1557
1558   startup_printf("Changing PC to 0x%x\n", destPC);
1559   startup_printf("String at 0x%x\n", dyninstlib_str_addr);
1560
1561   if (! lwp_to_use->changePC(destPC,NULL))
1562     {
1563       logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
1564       assert(0);
1565     }
1566
1567
1568 #if false && defined(PTRACEDEBUG)
1569   debug_ptrace = false;
1570 #endif
1571
1572
1573   setBootstrapState(loadingRT_bs);
1574   return true;
1575 }
1576
1577 bool process::loadDYNINSTlib_exported(const char *dlopen_name)
1578 {
1579         // dlopen takes two arguments:
1580         // const char *libname;
1581         // int mode;
1582         // We put the library name on the stack, push the args, and
1583         // emit the call
1584
1585         Address codeBase = findFunctionToHijack(this);
1586         if (!codeBase) 
1587         {
1588                 startup_cerr << "Couldn't find a point to insert dlopen call" << endl;
1589                 return false;
1590         }
1591
1592         Address dyninstlib_str_addr = 0;
1593         Address dlopen_call_addr = 0;
1594
1595         pdvector<int_function *> dlopen_funcs;
1596
1597         if (!findFuncsByAll(dlopen_name ? dlopen_name : DL_OPEN_FUNC_EXPORTED, dlopen_funcs)) 
1598         {
1599                 startup_cerr << "Couldn't find method to load dynamic library" << endl;
1600                 return false;
1601         } 
1602
1603         assert(dlopen_funcs.size() != 0);
1604         
1605         if (dlopen_funcs.size() > 1) 
1606         {
1607                 logLine("WARNING: More than one dlopen found, using the first\n");
1608         }
1609
1610         Address dlopen_addr = dlopen_funcs[0]->getAddress();
1611
1612         // We now fill in the scratch code buffer with appropriate data
1613         codeGen scratchCodeBuffer(MAX_IRPC_SIZE);
1614         scratchCodeBuffer.setAddrSpace(this);
1615         scratchCodeBuffer.setRegisterSpace(registerSpace::irpcRegSpace(this));
1616
1617         assert(dyninstRT_name.length() < MAX_IRPC_SIZE);
1618
1619         // The library name goes first
1620         dyninstlib_str_addr = codeBase;
1621         scratchCodeBuffer.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
1622
1623 #if defined(bug_syscall_changepc_rewind)
1624         //Fill in with NOPs, see loadDYNINSTlib_hidden
1625         scratchCodeBuffer.fill(getAddressWidth(), codeGen::cgNOP);
1626 #endif
1627         // Now the real code
1628         dlopen_call_addr = codeBase + scratchCodeBuffer.used();
1629
1630         if( !theRpcMgr->emitInferiorRPCheader(scratchCodeBuffer) ) {
1631             startup_cerr << "Couldn't emit inferior RPC header" << endl;
1632             return false;
1633         }
1634         
1635         bool mode64bit = (getAddressWidth() == sizeof(uint64_t));
1636
1637         if (!mode64bit) 
1638         {
1639                 // Push mode
1640                 emitPushImm(DLOPEN_MODE, scratchCodeBuffer);
1641
1642                 // Push string addr
1643                 emitPushImm(dyninstlib_str_addr, scratchCodeBuffer);
1644
1645                 insnCodeGen::generateCall(scratchCodeBuffer,
1646                                 scratchCodeBuffer.used() + codeBase,
1647                                 dlopen_addr);
1648                 const unsigned stackUsage = 2*4; // 2 pushes
1649                 RealRegister esp(REGNUM_ESP);
1650                 RealRegister enull(Null_Register);
1651                 emitLEA(esp, enull, 0, stackUsage, esp, scratchCodeBuffer);
1652                 scratchCodeBuffer.rs()->incStack(-stackUsage);
1653         }
1654         else 
1655         {
1656                 // Set mode
1657                 emitMovImmToReg64(REGNUM_RSI, DLOPEN_MODE, false, scratchCodeBuffer);
1658                 // Set string addr
1659                 emitMovImmToReg64(REGNUM_RDI, dyninstlib_str_addr, true,
1660                                 scratchCodeBuffer);
1661                 // The call (must be done through a register in order to reach)
1662                 emitMovImmToReg64(REGNUM_RAX, dlopen_addr, true, scratchCodeBuffer);
1663                 emitSimpleInsn(0xff, scratchCodeBuffer);
1664                 emitSimpleInsn(0xd0, scratchCodeBuffer);
1665         }
1666
1667         // The break point address is computed by the following function
1668         unsigned breakOffset = 0;
1669         unsigned unused;
1670         if( !theRpcMgr->emitInferiorRPCtrailer(scratchCodeBuffer, breakOffset, 
1671                     false, unused, unused) ) 
1672         {
1673             startup_cerr << "Couldn't emit inferior RPC trailer" << endl;
1674             return false;
1675         }
1676         dyninstlib_brk_addr = codeBase + breakOffset;
1677
1678         if (!readDataSpace((void *)codeBase,
1679                                 sizeof(savedCodeBuffer), savedCodeBuffer, true)) 
1680         {
1681                 fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
1682                 return false;
1683         }
1684
1685         if (!writeDataSpace((void *)(codeBase), scratchCodeBuffer.used(),
1686                                 scratchCodeBuffer.start_ptr())) 
1687         {
1688                 fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
1689                 return false;
1690         }
1691
1692         // save registers
1693         dyn_lwp *lwp_to_use = NULL;
1694
1695         if (process::IndependentLwpControl() && getRepresentativeLWP() == NULL)
1696         {
1697                 lwp_to_use = getInitialThread()->get_lwp();
1698         }
1699         else
1700         {
1701                 lwp_to_use = getRepresentativeLWP();
1702         }
1703
1704         savedRegs = new dyn_saved_regs;
1705         bool status = lwp_to_use->getRegisters(savedRegs);
1706
1707         assert((status != false) && (savedRegs != (void *)-1));
1708
1709         if (!lwp_to_use->changePC(dlopen_call_addr,NULL))  
1710         {
1711                 logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
1712                 return false;
1713         }
1714
1715         setBootstrapState(loadingRT_bs);
1716         return true;
1717 }
1718
1719 Address process::tryUnprotectStack(codeGen &buf, Address codeBase) 
1720 {
1721         // find variable __stack_prot
1722
1723         // mprotect READ/WRITE __stack_prot
1724         pdvector<int_variable *> vars; 
1725         pdvector<int_function *> funcs;
1726
1727         Address var_addr;
1728         Address func_addr;
1729         Address ret_addr;
1730         int size;
1731         int pagesize;
1732     Address page_start;
1733     bool ret;
1734     
1735     ret = findVarsByAll("__stack_prot", vars);
1736
1737     if(!ret || vars.size() == 0) {
1738         return 0;
1739     } else if(vars.size() > 1) {
1740         startup_printf("Warning: found more than one __stack_prot variable\n");
1741     }
1742
1743     pagesize = getpagesize();
1744
1745     var_addr = vars[0]->getAddress();
1746     page_start = var_addr & ~(pagesize -1);
1747     size = var_addr - page_start +sizeof(int);
1748
1749     ret = findFuncsByAll("mprotect",funcs);
1750
1751     if(!ret || funcs.size() == 0) {
1752         startup_printf("Couldn't find mprotect\n");
1753         return 0;
1754     }
1755
1756     int_function * mprot = funcs[0];
1757     func_addr = mprot->getAddress();
1758     ret_addr = codeBase + buf.used();
1759
1760 #if defined(arch_x86_64)
1761   if (getAddressWidth() == 4) {
1762 #endif
1763       // Push caller
1764       emitPushImm(func_addr, buf);
1765       
1766       // Push mode (READ|WRITE|EXECUTE)
1767       emitPushImm(7, buf);
1768       
1769       // Push variable size
1770       emitPushImm(size, buf);
1771       
1772       // Push variable location
1773       emitPushImm(page_start, buf);
1774      
1775       startup_printf("(%d): emitting call for mprotect from 0x%x to 0x%x\n",
1776                      getPid(), codeBase + buf.used(), func_addr);
1777       insnCodeGen::generateCall(buf, buf.used() + codeBase, func_addr);
1778
1779       const unsigned stackUsage = 4*4; // 4 pushes
1780       RealRegister esp(REGNUM_ESP);
1781       RealRegister enull(Null_Register);
1782       emitLEA(esp, enull, 0, stackUsage, esp, buf);
1783       buf.rs()->incStack(-stackUsage);
1784
1785 #if defined(arch_x86_64)
1786   } else {
1787       // Push caller
1788       //emitMovImmToReg64(REGNUM_RAX, func_addr, true, buf);
1789       //emitSimpleInsn(0x50, buf); // push %rax       
1790
1791       // Push mode (READ|WRITE|EXECUTE)
1792       emitMovImmToReg64(REGNUM_RDX, 7, true, buf); //32-bit mov
1793    
1794       // Push variable size
1795       emitMovImmToReg64(REGNUM_RSI, size, true, buf); //32-bit mov
1796
1797       // Push variable location 
1798       emitMovImmToReg64(REGNUM_RDI, page_start, true, buf);
1799
1800       // The call (must be done through a register in order to reach)
1801       emitMovImmToReg64(REGNUM_RAX, func_addr, true, buf);
1802       emitSimpleInsn(0xff, buf); // group 5
1803       emitSimpleInsn(0xd0, buf); // mod=11, ext_op=2 (call Ev), r/m=0 (RAX)
1804   }
1805 #endif
1806     
1807     return ret_addr;
1808 }
1809
1810
1811
1812 Frame process::preStackWalkInit(Frame startFrame) 
1813 {
1814   /* Do a special check for the vsyscall page.  Silently drop
1815      the page if it exists. */
1816   calcVSyscallFrame( this );
1817   
1818   Address next_pc = startFrame.getPC();
1819   if ((next_pc >= getVsyscallStart() && next_pc < getVsyscallEnd()) ||
1820       /* RH9 Hack */ (next_pc >= 0xffffe000 && next_pc < 0xfffff000)) {
1821      return startFrame.getCallerFrame();
1822   }
1823   return startFrame;
1824 }
1825
1826 #if defined(arch_x86_64)
1827 void print_regs(dyn_lwp *lwp)
1828 {
1829    struct dyn_saved_regs regs;
1830    bool result = lwp->getRegisters(&regs, false);
1831
1832    if (result)
1833       fprintf(stderr, "rax = %lx\n", regs.gprs.rax);
1834 }
1835 #endif