Fix instrumentation side effects; we had been erroneously moving the PC when handling...
[dyninst.git] / dyninstAPI / src / linux-power.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-power.C,v 1.19 2008/06/19 19:53:26 legendre Exp $
33
34 #include <string>
35 #include <dlfcn.h>
36
37 #include "dyninstAPI/src/debuggerinterface.h"
38 #include "dyninstAPI/src/dyn_lwp.h"
39 #include "dyninstAPI/src/dyn_thread.h"
40 #include "dyninstAPI/src/linux-power.h"
41 #include "dyninstAPI/src/mapped_object.h"
42 #include "dyninstAPI/src/process.h"
43 #include "dyninstAPI/src/inst-power.h"
44 #include "dyninstAPI/src/multiTramp.h"
45 #include "dyninstAPI/src/baseTramp.h"
46 #include "dyninstAPI/src/miniTramp.h"
47 #include "dyninstAPI/src/signalgenerator.h"
48 #include "dyninstAPI/src/registerSpace.h"
49 #include "dyninstAPI/src/function.h"
50
51 #define DLOPEN_MODE (RTLD_NOW | RTLD_GLOBAL)
52
53 const char DL_OPEN_FUNC_EXPORTED[] = "dlopen";
54 const char DL_OPEN_FUNC_INTERNAL[] = "_dl_open";
55 const char DL_OPEN_FUNC_NAME[] = "do_dlopen";
56
57 #define P_offsetof(s, m) (Address) &(((s *) NULL)->m)
58
59 #if defined(arch_64bit) && 0 // XXX FIXME - Need a configure variable to see
60                              //             if struct pt_regs32 exists.
61 #define PT_REGS_OFFSET(m, mutatee_address_width)           \
62         (                                                  \
63             ((mutatee_address_width) == sizeof(uint64_t))  \
64             ? (   /* 64-bit mutatee */                     \
65                   P_offsetof(struct pt_regs, m)            \
66               )                                            \
67             : (   /* 32-bit mutatee */                     \
68                   P_offsetof(struct pt_regs32, m)          \
69               )                                            \
70         )
71 #else
72 #define PT_REGS_OFFSET(m, mutatee_address_width)           \
73         (                                                  \
74             P_offsetof(struct pt_regs, m)                  \
75         )
76 #endif
77
78
79 #define PT_FPSCR_OFFSET(mutatee_address_width)                  \
80         (                                                       \
81             ((mutatee_address_width) == sizeof(PTRACE_RETURN))  \
82             ? (   /* N-bit mutatee, N-bit mutator   */          \
83                   PT_FPSCR * sizeof(PTRACE_RETURN)              \
84               )                                                 \
85             : (   /* 32-bit mutatee, 64-bit mutator */          \
86                   (PT_FPR0 + 2*32 + 1) * sizeof(uint32_t)       \
87               )                                                 \
88         )
89
90
91 #define SIZEOF_PTRACE_DATA(mutatee_address_width)  (mutatee_address_width)
92
93
94 void calcVSyscallFrame(process *p)
95 {
96   assert(0);  //sunlung
97   unsigned dso_size;
98   char *buffer;
99
100   /**
101    * If we've already calculated and cached the DSO information then
102    * just return.
103    **/
104
105   if (p->getAddressWidth() == 8) {
106      // FIXME: HACK to disable vsyscall page for AMD64, for now.
107      //  Reading the VSyscall data on ginger seems to trigger a
108      //  kernel panic.
109      p->setVsyscallRange(0x1000, 0x0);
110      return;
111   }
112
113   /**
114    * Read the location of the vsyscall page from /proc/.
115    **/
116   p->readAuxvInfo();
117   if (p->getVsyscallStatus() != vsys_found) {
118      p->setVsyscallRange(0x0, 0x0);
119      return;
120   }
121
122   /**
123    * Read the vsyscall page out of process memory.
124    **/
125   dso_size = p->getVsyscallEnd() - p->getVsyscallStart();
126   buffer = (char *) calloc(1, dso_size);
127   assert(buffer);
128 /*if (!p->readDataSpace((caddr_t)p->getVsyscallStart(), dso_size, buffer,false))
129   {
130      int major, minor, sub;
131      get_linux_version(major, minor, sub);
132      if (major == 2 && minor == 6 && sub <= 2 && sub >= 0) {
133         //Linux 2.6.0 - Linux 2.6.2 has a  bug where ptrace
134         // can't read from the DSO.  The process can read the memory,
135         // it's just ptrace that's acting stubborn.
136         if (!execVsyscallFetch(p, buffer))
137         {
138            p->setVsyscallStatus(vsys_notfound);
139            return;
140         }
141      }
142   }
143
144   if (!isVsyscallData(buffer, dso_size)) {
145      p->setVsyscallRange(0x0, 0x0);
146      p->setVsyscallStatus(vsys_notfound);
147      return;
148   }
149   getVSyscallSignalSyms(buffer, dso_size, p);
150   result = parseVsyscallPage(buffer, dso_size, p);
151 */
152   return;
153 }
154
155
156 bool dyn_lwp::changePC(Address loc,
157                        struct dyn_saved_regs */*ignored registers*/)
158 {
159    Address regaddr = PT_REGS_OFFSET(PTRACE_REG_IP, proc_->getAddressWidth());
160    assert(get_lwp_id() != 0);
161    int ptrace_errno = 0;
162    if (0 != DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(), regaddr, loc,
163                        &ptrace_errno, proc_->getAddressWidth(),
164                        __FILE__, __LINE__ )) {
165       fprintf(stderr, "dyn_lwp::changePC - PTRACE_POKEUSER failure for %u",
166               get_lwp_id());
167       return false;
168    }
169
170    return true;
171 }
172
173
174 // getActiveFrame(): populate Frame object using toplevel frame
175 Frame dyn_lwp::getActiveFrame()
176 {
177    if(status() == running) {
178       fprintf(stderr, "%s[%d][%s]:  FIXME\n", __FILE__, __LINE__,
179               getThreadStr(getExecThreadID()));
180       cerr << "    performance problem in call to dyn_lwp::getActiveFrame\n"
181            << "       successive pauses and continues with ptrace calls\n";
182    }
183
184    Address pc, fp, sp;
185
186    int ptrace_errno = 0;
187
188    // frame pointer
189    fp = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
190                    PT_REGS_OFFSET(PTRACE_REG_FP, proc_->getAddressWidth()), 0,
191                    &ptrace_errno, proc_->getAddressWidth(), __FILE__, __LINE__);
192    if (ptrace_errno) return Frame();
193
194    // next instruction pointer
195    pc = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
196                    PT_REGS_OFFSET(PTRACE_REG_IP, proc_->getAddressWidth()), 0,
197                    &ptrace_errno, proc_->getAddressWidth(), __FILE__, __LINE__);
198    if (ptrace_errno) return Frame();
199
200    // no top-of-stack pointer for POWER/PowerPC
201    sp = 0;
202
203    dbi_printf("%s[%d]:  GET ACTIVE FRAME (pc = %p, sp = %p, fp = %p\n",
204               FILE__, __LINE__, pc, sp, fp);
205
206    return Frame(pc, fp, sp, proc_->getPid(), proc_, NULL, this, true);
207 }
208
209
210
211
212 bool dyn_lwp::getRegisters_(struct dyn_saved_regs *regs, bool includeFP) {
213    int           error = 0;
214    int           ptrace_errno;
215    PTRACE_RETURN r;
216
217    assert(get_lwp_id() != 0);
218
219    // no PTRACE_GETREGS on PowerPC Linux 2.6.5
220    for (int i = 0; i < 32; i++) {
221       ptrace_errno = 0;
222       r = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
223                      PT_REGS_OFFSET(gpr[i], proc_->getAddressWidth()), 0,
224                      &ptrace_errno, proc_->getAddressWidth(), __FILE__,
225                      __LINE__);
226       if ((r == -1) && ptrace_errno)
227          error++;
228       else
229          regs->gprs.gpr[i] = r;
230    }
231
232    ptrace_errno = 0; 
233    r = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
234                   PT_REGS_OFFSET(nip, proc_->getAddressWidth()), 0,
235                   &ptrace_errno, proc_->getAddressWidth(), __FILE__, __LINE__);
236    if ((r == -1) && ptrace_errno)
237       error++;
238    else
239       regs->gprs.nip = r;
240
241    ptrace_errno = 0;
242    r = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
243                   PT_REGS_OFFSET(msr, proc_->getAddressWidth()), 0,
244                   &ptrace_errno, proc_->getAddressWidth(), __FILE__, __LINE__);
245    if ((r == -1) && ptrace_errno)
246       error++;
247    else
248       regs->gprs.msr = r;
249
250    ptrace_errno = 0;
251    r = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
252                   PT_REGS_OFFSET(ctr, proc_->getAddressWidth()), 0,
253                   &ptrace_errno, proc_->getAddressWidth(), __FILE__, __LINE__);
254    if ((r == -1) && ptrace_errno)
255       error++;
256    else
257       regs->gprs.ctr = r;
258
259    ptrace_errno = 0;
260    r = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
261                   PT_REGS_OFFSET(link, proc_->getAddressWidth()), 0,
262                   &ptrace_errno, proc_->getAddressWidth(), __FILE__, __LINE__);
263    if ((r == -1) && ptrace_errno)
264       error++;
265    else
266       regs->gprs.link = r;
267
268    ptrace_errno = 0;
269    r = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
270                   PT_REGS_OFFSET(xer, proc_->getAddressWidth()), 0,
271                   &ptrace_errno, proc_->getAddressWidth(), __FILE__, __LINE__);
272    if ((r == -1) && ptrace_errno)
273       error++;
274    else
275       regs->gprs.xer = r;
276
277    ptrace_errno = 0;
278    r = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
279                   PT_REGS_OFFSET(ccr, proc_->getAddressWidth()), 0,
280                   &ptrace_errno, proc_->getAddressWidth(), __FILE__, __LINE__);
281    if ((r == -1) && ptrace_errno)
282       error++;
283    else
284       regs->gprs.ccr = r;
285
286    if (error) {
287       perror("dyn_lwp::getRegisters PTRACE_GETREGS" );
288       return false;
289    }
290
291    if (includeFP) {
292       // no PTRACE_GETFPREGS on PowerPC Linux 2.6.5
293
294       size_t PEEKsPerFPR = sizeof(regs->fprs.fpr[0])
295                            / SIZEOF_PTRACE_DATA(proc_->getAddressWidth());
296       assert(PEEKsPerFPR * SIZEOF_PTRACE_DATA(proc_->getAddressWidth()) ==
297              sizeof(regs->fprs.fpr[0]));
298
299       for (int i = 0; i < 32; i++) {
300          PTRACE_RETURN rs[PEEKsPerFPR];
301          uint32_t      rs32[PEEKsPerFPR];
302          for (size_t n = 0; n < PEEKsPerFPR; n++) {
303             ptrace_errno = 0;
304             r = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
305                            (PT_FPR0 + i*PEEKsPerFPR + n)
306                            * SIZEOF_PTRACE_DATA(proc_->getAddressWidth()),
307                            0, &ptrace_errno, proc_->getAddressWidth(),
308                            __FILE__, __LINE__);
309             if ((r == -1) && ptrace_errno) {
310                error++;
311                break;
312             }
313             rs32[n] = rs[n] = r;
314             if (n == PEEKsPerFPR - 1) {
315               if (SIZEOF_PTRACE_DATA(proc_->getAddressWidth()) ==
316                   sizeof(uint32_t))
317                   memcpy(&regs->fprs.fpr[i], rs32, sizeof(regs->fprs.fpr[i]));
318                 else
319                   memcpy(&regs->fprs.fpr[i], rs, sizeof(regs->fprs.fpr[i]));
320             }
321          }
322       }
323
324       ptrace_errno = 0;
325       r = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
326                      PT_FPSCR_OFFSET(proc_->getAddressWidth()), 0,
327                      &ptrace_errno, proc_->getAddressWidth(), __FILE__,
328                      __LINE__);
329       if ((r == -1) && ptrace_errno)
330          error++;
331       else
332          regs->fprs.fpscr = r;
333
334       if (error) {
335          perror("dyn_lwp::getRegisters PTRACE_GETFPREGS" );
336          return false;
337       }
338    }
339
340    return true;
341 }
342
343
344
345 Address dyn_lwp::readRegister(Register reg) {
346    if(status() == running) {
347       cerr << "    performance problem in call to dyn_lwp::readRegister\n"
348            << "       successive pauses and continues with ptrace calls\n";
349    }
350
351    int ptrace_errno = 0;
352    Address ret = DBI_ptrace(PTRACE_PEEKUSER, get_lwp_id(),
353                             PT_REGS_OFFSET(gpr[reg], proc_->getAddressWidth()),
354                             0, &ptrace_errno, proc_->getAddressWidth(),
355                             __FILE__, __LINE__);
356    return ret;
357 }
358
359
360 bool dyn_lwp::restoreRegisters_(const struct dyn_saved_regs &regs, bool includeFP) {
361    // Cycle through all registers, writing each from the
362    // buffer with ptrace(PTRACE_POKEUSER ...
363
364    bool retVal = true;
365    int ptrace_errno = 0;
366    int error = 0;
367
368    assert(get_lwp_id() != 0);
369
370    // no PTRACE_SETREGS on PowerPC Linux 2.6.5
371    for (int i = 0; i < 32; i++) {
372       error += DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(),
373                           PT_REGS_OFFSET(gpr[i], proc_->getAddressWidth()),
374                           regs.gprs.gpr[i], &ptrace_errno,
375                           proc_->getAddressWidth(), __FILE__, __LINE__);
376    }
377
378    error += DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(),
379                        PT_REGS_OFFSET(nip, proc_->getAddressWidth()),
380                        regs.gprs.nip, &ptrace_errno,
381                        proc_->getAddressWidth(), __FILE__, __LINE__);
382
383    error += DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(),
384                        PT_REGS_OFFSET(msr, proc_->getAddressWidth()),
385                        regs.gprs.msr, &ptrace_errno,
386                        proc_->getAddressWidth(), __FILE__, __LINE__);
387
388    error += DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(),
389                        PT_REGS_OFFSET(ctr, proc_->getAddressWidth()),
390                        regs.gprs.ctr, &ptrace_errno,
391                        proc_->getAddressWidth(), __FILE__, __LINE__);
392
393    error += DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(),
394                        PT_REGS_OFFSET(link, proc_->getAddressWidth()),
395                        regs.gprs.link, &ptrace_errno,
396                        proc_->getAddressWidth(), __FILE__, __LINE__);
397
398    error += DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(),
399                        PT_REGS_OFFSET(xer, proc_->getAddressWidth()),
400                        regs.gprs.xer, &ptrace_errno,
401                        proc_->getAddressWidth(), __FILE__, __LINE__);
402
403    error += DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(),
404                        PT_REGS_OFFSET(ccr, proc_->getAddressWidth()),
405                        regs.gprs.ccr, &ptrace_errno,
406                        proc_->getAddressWidth(), __FILE__, __LINE__);
407
408    if (error) {
409       perror("dyn_lwp::restoreRegisters PTRACE_SETREGS" );
410       retVal = false;
411    }
412    error = 0;
413
414    if (includeFP) {
415       // no PTRACE_SETFPREGS on PowerPC Linux 2.6.5
416
417       size_t POKEsPerFPR = sizeof(regs.fprs.fpr[0])
418                            / SIZEOF_PTRACE_DATA(proc_->getAddressWidth());
419       assert(POKEsPerFPR * SIZEOF_PTRACE_DATA(proc_->getAddressWidth()) ==
420              sizeof(regs.fprs.fpr[0]));
421
422       for (int i = 0; i < 32; i++) {
423          PTRACE_RETURN ps[POKEsPerFPR];
424          memcpy(ps, &regs.fprs.fpr[i], sizeof(regs.fprs.fpr[i]));
425          if (SIZEOF_PTRACE_DATA(proc_->getAddressWidth()) == sizeof(uint32_t)) {
426             uint32_t ps32[POKEsPerFPR];
427             memcpy(ps32, &regs.fprs.fpr[i], sizeof(regs.fprs.fpr[i]));
428             for (size_t n = 0; n < POKEsPerFPR; n++)
429                ps[n] = ps32[n];
430          }
431          for (size_t n = 0; n < POKEsPerFPR; n++) {
432             error += DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(),
433                                 (PT_FPR0 + i*POKEsPerFPR + n)
434                                 * SIZEOF_PTRACE_DATA(proc_->getAddressWidth()),
435                                 ps[n], &ptrace_errno, proc_->getAddressWidth(),
436                                 __FILE__, __LINE__);
437          }
438       }
439
440       error += DBI_ptrace(PTRACE_POKEUSER, get_lwp_id(),
441                           PT_FPSCR_OFFSET(proc_->getAddressWidth()),
442                           regs.fprs.fpscr, &ptrace_errno,
443                           proc_->getAddressWidth(), __FILE__, __LINE__);
444
445       if (error) {
446          perror("dyn_lwp::restoreRegisters PTRACE_SETFPREGS" );
447          retVal = false;
448       }
449    }
450
451    return retVal;
452 }
453
454
455 Frame Frame::getCallerFrame()
456 {
457 // Matt's DynStackwalker will replace this
458
459 //Change this struct and add Vsyscall to see if mutatee is in a syscall
460 //--in a syscall, frame is in a different form
461   typedef union {
462       struct {
463           uint32_t oldFp;
464           uint32_t savedLR;
465       } elf32;
466       struct {
467           uint64_t oldFp;
468           uint64_t savedCR;
469           uint64_t savedLR;
470       } elf64;
471   } linkArea_t;
472
473   int savedLROffset;
474   if (getProc()->getAddressWidth() == sizeof(uint64_t))
475     savedLROffset = P_offsetof(linkArea_t, elf64.savedLR);
476   else
477     savedLROffset = P_offsetof(linkArea_t, elf32.savedLR);
478
479   linkArea_t thisStackFrame;
480   linkArea_t lastStackFrame;
481   linkArea_t stackFrame;
482   Address basePCAddr;
483
484   Address newPC=0;
485   Address newFP=0;
486   Address newpcAddr=0;
487
488   // Are we in a leaf function?
489   bool isLeaf = false;
490   bool noFrame = false;
491
492   codeRange *range = getRange();
493   int_function *func = range->is_function();
494
495   if (uppermost_) {
496     if (func) {
497       //isLeaf = func->isLeafFunc();
498       isLeaf = !func->savesReturnAddr();
499       noFrame = func->hasNoStackFrame();
500     }
501   }
502
503   // Get current stack frame link area
504   if (getProc()->getAddressWidth() == sizeof(uint64_t)) {
505     if (!getProc()->readDataSpace((caddr_t)fp_, sizeof(thisStackFrame.elf64),
506                                   (caddr_t)&thisStackFrame.elf64, false))
507       return Frame();
508   }
509   else {
510     if (!getProc()->readDataSpace((caddr_t)fp_, sizeof(thisStackFrame.elf32),
511                                   (caddr_t)&thisStackFrame.elf32, false))
512       return Frame();
513   }
514
515   if (getProc()->getAddressWidth() == sizeof(uint64_t))
516     getProc()->readDataSpace((caddr_t) (Address) thisStackFrame.elf64.oldFp,
517                              sizeof(lastStackFrame.elf64),
518                              (caddr_t) &lastStackFrame.elf64, false);
519   else
520     getProc()->readDataSpace((caddr_t) (Address) thisStackFrame.elf32.oldFp,
521                              sizeof(lastStackFrame.elf32),
522                              (caddr_t) &lastStackFrame.elf32, false);
523
524   if (noFrame) {
525     stackFrame = thisStackFrame;
526     basePCAddr = fp_;
527   }
528   else {
529     stackFrame = lastStackFrame;
530     if (getProc()->getAddressWidth() == sizeof(uint64_t))
531       basePCAddr = thisStackFrame.elf64.oldFp;
532     else
533       basePCAddr = thisStackFrame.elf32.oldFp;
534   }
535
536   // See if we're in instrumentation
537   baseTrampInstance *bti = NULL;
538   
539   if (range->is_multitramp()) {
540       bti = range->is_multitramp()->getBaseTrampInstanceByAddr(getPC());
541       if (bti) {
542           // If we're not in instru, then re-set this to NULL
543           if (!bti->isInInstru(getPC()))
544               bti = NULL;
545       }
546   }
547   else if (range->is_minitramp()) {
548       bti = range->is_minitramp()->baseTI;
549   }
550   if (bti) {
551       // Oy. We saved the LR in the middle of the tramp; so pull it out
552       // by hand.
553       newpcAddr = fp_ + TRAMP_SPR_OFFSET + STK_LR;
554       if (getProc()->getAddressWidth() == sizeof(uint64_t))
555         newFP = thisStackFrame.elf64.oldFp;
556       else
557         newFP = thisStackFrame.elf32.oldFp;
558
559       if (getProc()->getAddressWidth() == sizeof(uint64_t)) {
560         if (!getProc()->readDataSpace((caddr_t) newpcAddr,
561                                       sizeof(newPC), (caddr_t) &newPC, false))
562           return Frame();
563       }
564       else {
565         uint32_t u32;
566         if (!getProc()->readDataSpace((caddr_t) newpcAddr,
567                                       sizeof(u32), (caddr_t) &u32, false))
568           return Frame();
569         newPC = u32;
570       }
571
572       // Instrumentation makes its own frame; we want to skip the
573       // function frame if there is one as well.
574       instPoint *point = bti->baseT->instP();
575       assert(point); // Will only be null if we're in an inferior RPC, which can't be.
576       // If we're inside the function (callSite or arbitrary; bad assumption about
577       // arbitrary but we don't know exactly where the frame was constructed) and the
578       // function has a frame, tear it down as well.
579       if ((point->getPointType() == callSite ||
580           point->getPointType() == otherPoint) &&
581           !point->func()->hasNoStackFrame()) {
582         if (getProc()->getAddressWidth() == sizeof(uint64_t)) {
583           if (!getProc()->readDataSpace((caddr_t) (Address)
584                                         thisStackFrame.elf64.oldFp,
585                                         sizeof(newFP),
586                                         (caddr_t) &newFP, false))
587             return Frame();
588         }
589         else {
590           uint32_t u32;
591           if (!getProc()->readDataSpace((caddr_t) (Address)
592                                         thisStackFrame.elf32.oldFp,
593                                         sizeof(u32), (caddr_t) &u32, false))
594             return Frame();
595           newFP = u32;
596         }
597       }
598       // Otherwise must be at a reloc insn
599   }
600   else if (isLeaf) {
601       // isLeaf: get the LR from the register instead of saved location on the stack
602       if (lwp_ && lwp_->get_lwp_id()) {
603           dyn_saved_regs regs;
604           bool status = lwp_->getRegisters(&regs);
605           if (! status) {
606               return Frame();
607           }
608           newPC = regs.gprs.nip;
609           newpcAddr = (Address) 1;
610           // I'm using an address to signify a register
611       }
612       else if (thread_ && thread_->get_tid()) {
613           cerr << "NOT IMPLEMENTED YET" << endl;
614       }
615       else { // normal
616           dyn_saved_regs regs;
617           bool status = getProc()->getRepresentativeLWP()->getRegisters(&regs);
618           if (!status) {
619               return Frame();
620           }
621           newPC = regs.gprs.nip;
622           newpcAddr = (Address) 1;
623       }
624
625
626       if (noFrame)
627           newFP = fp_;
628       else
629           if (getProc()->getAddressWidth() == sizeof(uint64_t))
630               newFP = thisStackFrame.elf64.oldFp;
631           else
632               newFP = thisStackFrame.elf32.oldFp;
633   }
634   else {
635       // Common case.
636       if (getProc()->getAddressWidth() == sizeof(uint64_t))
637         newPC = stackFrame.elf64.savedLR;
638       else
639         newPC = stackFrame.elf32.savedLR;
640       newpcAddr = basePCAddr + savedLROffset;
641       if (noFrame)
642         newFP = fp_;
643       else
644         if (getProc()->getAddressWidth() == sizeof(uint64_t))
645           newFP = thisStackFrame.elf64.oldFp;
646         else
647           newFP = thisStackFrame.elf32.oldFp;
648   }
649
650 #ifdef DEBUG_STACKWALK
651   fprintf(stderr, "PC %x, FP %x\n", newPC, newFP);
652 #endif
653   return Frame(newPC, newFP, 0, newpcAddr, this);
654 }
655
656
657
658 bool Frame::setPC(Address newpc) {
659    if (!pcAddr_)
660    {
661        //fprintf(stderr, "[%s:%u] - Frame::setPC aborted", __FILE__, __LINE__);
662       return false;
663    }
664
665    //fprintf(stderr, "[%s:%u] - Frame::setPC setting %x to %x",
666    //__FILE__, __LINE__, pcAddr_, newpc);
667    if (getProc()->getAddressWidth() == sizeof(uint64_t)) {
668       uint64_t newpc64 = newpc;
669       if (!getProc()->writeDataSpace((void*)pcAddr_, sizeof(newpc64), &newpc64))
670          return false;
671    }
672    else {
673       uint32_t newpc32 = newpc;
674       if (!getProc()->writeDataSpace((void*)pcAddr_, sizeof(newpc32), &newpc32))
675          return false;
676    }
677    pc_ = newpc;
678    range_ = NULL;
679
680    return true;
681 }
682
683 bool AddressSpace::getDyninstRTLibName() {
684 //full path to libdyninstAPI_RT (used an _m32 suffix for 32-bit version)
685     startup_printf("dyninstRT_name: %s\n", dyninstRT_name.c_str());
686     if (dyninstRT_name.length() == 0) {
687         // Get env variable
688         if (getenv("DYNINSTAPI_RT_LIB") != NULL) {
689             dyninstRT_name = getenv("DYNINSTAPI_RT_LIB");
690         }
691         else {
692             std::string msg = std::string("Environment variable ") +
693                 std::string("DYNINSTAPI_RT_LIB") +
694                std::string(" has not been defined");
695             showErrorCallback(101, msg);
696             return false;
697         }
698     }
699
700     // Automatically choose 32-bit library if necessary.
701     const char *modifier = "_m32";
702     const char *name = dyninstRT_name.c_str();
703
704     const char *split = P_strrchr(name, '/');
705     if ( !split ) split = name;
706     split = P_strchr(split, '.');
707     if ( !split || P_strlen(split) <= 1 ) {
708         // We should probably print some error here.
709         // Then, of course, the user will find out soon enough.
710         startup_printf("Invalid Dyninst RT lib name: %s\n", 
711                 dyninstRT_name.c_str());
712         return false;
713     }
714
715     if ( getAddressWidth() == sizeof(void *) || P_strstr(name, modifier) ) {
716         modifier = "";
717     }
718
719     const char *suffix = split;
720     if( getAOut()->isStaticExec() ) {
721         suffix = ".a";
722     }else{
723         if( P_strncmp(suffix, ".a", 2) == 0 ) {
724             // This will be incorrect if the RT library's version changes
725             suffix = ".so";
726         }
727     }
728
729     dyninstRT_name = std::string(name, split - name) +
730                      std::string(modifier) +
731                      std::string(suffix);
732
733     startup_printf("Dyninst RT Library name set to '%s'\n",
734             dyninstRT_name.c_str());
735
736     // Check to see if the library given exists.
737     if (access(dyninstRT_name.c_str(), R_OK)) {
738         std::string msg = std::string("Runtime library ") + dyninstRT_name
739         + std::string(" does not exist or cannot be accessed!");
740         showErrorCallback(101, msg);
741         return false;
742     }
743     return true;
744 }
745
746
747
748 bool process::handleTrapAtEntryPointOfMain(dyn_lwp *trappingLWP)
749 {
750     assert(main_brk_addr);
751     assert(trappingLWP);
752     // restore original instruction
753
754     if (!writeDataSpace((void *)main_brk_addr, instruction::size(),
755                         (char *)savedCodeBuffer))
756         return false;
757
758     if (! trappingLWP->changePC(main_brk_addr,NULL))
759         {
760             logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
761             assert(0);
762         }
763
764     main_brk_addr = 0;
765     return true;
766 }
767
768
769 bool process::insertTrapAtEntryPointOfMain()
770 {
771     // copied from aix.C
772     int_function *f_main = NULL;
773     pdvector<int_function *> funcs;
774     bool res = findFuncsByPretty("main", funcs);
775     if (!res) {
776         // we can't instrument main - naim
777         showErrorCallback(108,"main() uninstrumentable");
778         return false;
779     }
780
781     if( funcs.size() > 1 ) {
782       for (unsigned j = 0; j < funcs.size(); ++j) {
783         funcs[j]->debugPrint();
784       }
785
786         cerr << __FILE__ << __LINE__
787              << ": found more than one main! using the first" << endl;
788     }
789     f_main = funcs[0];
790     assert(f_main);
791
792     Address addr = f_main->getAddress();
793
794     startup_printf("[%d]: inserting trap at 0x%x\n",
795                    getPid(), addr);
796
797     // save original instruction first
798     readDataSpace((void *)addr, instruction::size(), savedCodeBuffer, true);
799     // and now, insert trap
800     codeGen gen(instruction::size());
801     insnCodeGen::generateTrap(gen);
802
803     assert(instruction::size() == gen.used());
804     if (!writeDataSpace((void *)addr, gen.used(), gen.start_ptr()))
805         fprintf(stderr, "%s[%d]:  writeDataSpace failed\n", FILE__, __LINE__);
806     main_brk_addr = addr;
807
808     return true;
809 }
810
811 bool process::handleTrapAtLibcStartMain(dyn_lwp *)  { assert(0); }
812 bool process::instrumentLibcStartMain() { assert(0); }
813 bool process::decodeStartupSysCalls(EventRecord &) { assert(0); }
814 void process::setTraceSysCalls(bool) { assert(0); }
815 void process::setTraceState(traceState_t) { assert(0); }
816 bool process::getSysCallParameters(dyn_saved_regs *, long *, int) { assert(0); }
817 int process::getSysCallNumber(dyn_saved_regs *) { assert(0); }
818 long process::getSysCallReturnValue(dyn_saved_regs *) { assert(0); }
819 Address process::getSysCallProgramCounter(dyn_saved_regs *) { assert(0); }
820 bool process::isMmapSysCall(int) { assert(0); }
821 Offset process::getMmapLength(int, dyn_saved_regs *) { assert(0); }
822 Address process::getLibcStartMainParam(dyn_lwp *) { assert(0); }
823
824 bool process::loadDYNINSTlib()
825 {
826     pdvector<int_function *> dlopen_funcs;
827
828     if (findFuncsByAll(DL_OPEN_FUNC_EXPORTED, dlopen_funcs)) {
829         return loadDYNINSTlib_exported();
830     }
831     else {
832         return loadDYNINSTlib_hidden();
833     }
834 }
835
836
837 bool process::loadDYNINSTlibCleanup(dyn_lwp *trappingLWP)
838 {
839   // rewrite original instructions in the text segment we use for
840   // the inferiorRPC - naim
841   unsigned count = sizeof(savedCodeBuffer);
842
843   Address codeBase = findFunctionToHijack(this);
844   assert(codeBase);
845
846   writeDataSpace((void *)codeBase, count, (char *)savedCodeBuffer);
847
848   // restore registers
849   assert(savedRegs != NULL);
850   trappingLWP->restoreRegisters(*savedRegs);
851
852   delete savedRegs;
853   savedRegs = NULL;
854   return true;
855 }
856
857
858
859 bool process::loadDYNINSTlib_exported(const char *)
860 {
861     // This functions was implemented by mixing parts of
862     // process::loadDYNINSTlib() in aix.C and
863     // process::loadDYNINSTlib_exported() in linux-x86.C.
864
865     // dlopen takes two arguments:
866     // const char *libname;
867     // int mode;
868
869     Address codeBase = findFunctionToHijack(this);
870     if (!codeBase) {
871         startup_cerr << "Couldn't find a point to insert dlopen call" << endl;
872         return false;
873     }
874     Address dyninstlib_str_addr = 0;
875     Address dlopen_call_addr = 0;
876
877     pdvector<int_function *> dlopen_funcs;
878     if (!findFuncsByAll(DL_OPEN_FUNC_EXPORTED, dlopen_funcs)) {
879         startup_cerr << "Couldn't find method to load dynamic library" << endl;
880         return false;
881     }
882
883     assert(dlopen_funcs.size() != 0);
884     if (dlopen_funcs.size() > 1) {
885         logLine("WARNING: More than one dlopen found, using the first\n");
886     }
887     //Address dlopen_addr = dlopen_funcs[0]->getAddress();
888     int_function *dlopen_func = dlopen_funcs[0];  //aix.C
889
890     // We now fill in the scratch code buffer with appropriate data
891     codeGen scratchCodeBuffer(BYTES_TO_SAVE);
892     assert(dyninstRT_name.length() < BYTES_TO_SAVE);
893     scratchCodeBuffer.setAddrSpace(this);  //aix.C
894     scratchCodeBuffer.setAddr(codeBase); //aix.C
895
896     // The library name goes first
897     dyninstlib_str_addr = codeBase;
898     scratchCodeBuffer.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
899
900     // Need a register space                                           //aix.C
901     // make sure this syncs with inst-power.C                          //aix.C
902     registerSpace *dlopenRegSpace = registerSpace::savedRegSpace(this);//aix.C
903     scratchCodeBuffer.setRegisterSpace(dlopenRegSpace);                //aix.C
904
905 #if defined(bug_syscall_changepc_rewind)
906     //Fill in with NOPs, see loadDYNINSTlib_hidden
907     scratchCodeBuffer.fill(getAddressWidth(), codeGen::cgNOP);
908 #endif
909
910     // Now the real code
911     dlopen_call_addr = codeBase + scratchCodeBuffer.used();
912
913     pdvector<AstNodePtr> dlopenAstArgs(2);                         //aix.C
914     AstNodePtr dlopenAst;                                          //aix.C
915     dlopenAstArgs[0] = AstNode::operandNode(AstNode::Constant,     //aix.C
916                                             (void*)dyninstlib_str_addr);
917     dlopenAstArgs[1] = AstNode::operandNode(AstNode::Constant,     //aix.C
918                                             (void*)DLOPEN_MODE);
919     dlopenAst = AstNode::funcCallNode(dlopen_func, dlopenAstArgs); //aix.C
920
921     // We need to push down the stack before we call this  //aix.C
922     pushStack(scratchCodeBuffer);                          //aix.C
923     dlopenAst->generateCode(scratchCodeBuffer, true);      //aix.C
924     popStack(scratchCodeBuffer);                           //aix.C
925  
926     dyninstlib_brk_addr = codeBase + scratchCodeBuffer.used();
927     insnCodeGen::generateTrap(scratchCodeBuffer);
928
929     if (!readDataSpace((void *)codeBase,
930                        sizeof(savedCodeBuffer), savedCodeBuffer, true)) {
931         fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
932         return false;
933     }
934
935     if (!writeDataSpace((void *)(codeBase), scratchCodeBuffer.used(),
936                         scratchCodeBuffer.start_ptr())) {
937         fprintf(stderr, "%s[%d]:  writeDataSpace\n", __FILE__, __LINE__);
938         return false;
939     }
940
941     // save registers
942     dyn_lwp *lwp_to_use = NULL;
943     if (process::IndependentLwpControl() && getRepresentativeLWP() == NULL)
944         lwp_to_use = getInitialThread()->get_lwp();
945     else
946         lwp_to_use = getRepresentativeLWP();
947
948     savedRegs = new dyn_saved_regs;
949     bool status = lwp_to_use->getRegisters(savedRegs);
950
951     assert((status != false) && (savedRegs != (void *)-1));
952
953     if (!lwp_to_use->changePC(dlopen_call_addr,NULL))  {
954         logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
955         return false;
956     }
957     setBootstrapState(loadingRT_bs);
958     return true;
959 }
960
961
962 bool process::loadDYNINSTlib_hidden() {
963   // We need to make a call to do_dlopen to open our runtime library
964
965   // This function was implemented by mixing parts of
966   // process::loadDYNINSTlib() in aix.C and
967   // process::loadDYNINSTlib_hidden() in linux-x86.C.
968
969   startup_printf("**** LIBC21 dlopen for RT lib\n");
970
971   // do_dlopen takes a pointer-to-struct argument. The struct is as follows:
972   // const char *libname;
973   // int mode;
974   // void *result;
975   // void *caller_addr;  (may be obsolete, but no harm leaving in)
976   // Now, we have to put this somewhere writable. The idea is to
977   // put it on the stack....
978
979   union {
980      struct {
981         uint32_t libname;
982         int32_t  mode;
983         uint32_t result;
984         uint32_t caller_addr;
985      } elf32;
986      struct {
987         uint64_t libname;
988         int32_t  mode;
989         uint64_t result;
990         uint64_t caller_addr;
991      } elf64;
992   } do_dlopen_struct;
993
994   Address codeBase = findFunctionToHijack(this);
995
996   if(!codeBase)
997   {
998       startup_cerr << "Couldn't find a point to insert dlopen call" << endl;
999       return false;
1000   }
1001
1002   startup_printf("(%d) writing in dlopen call at addr %p\n", getPid(),
1003                  (void *)codeBase);
1004
1005   codeGen scratchCodeBuffer(BYTES_TO_SAVE);
1006
1007   // Variables what we're filling in
1008   Address dyninstlib_str_addr = 0;
1009   Address dlopen_call_addr = 0;
1010   Address do_dlopen_struct_addr = 0;
1011
1012   pdvector<int_function *> dlopen_funcs;
1013   if (!findFuncsByAll(DL_OPEN_FUNC_NAME, dlopen_funcs))
1014   {
1015     pdvector<int_function *> dlopen_int_funcs;
1016
1017     // If we can't find the do_dlopen function (because this library
1018     // is stripped, for example), try searching for the internal
1019     // _dl_open function and find the do_dlopen function by examining
1020     // the functions that call it. This depends on the do_dlopen
1021     // function having been parsed (though its name is not known)
1022     // through speculative parsing.
1023     if(!findFuncsByAll(DL_OPEN_FUNC_INTERNAL, dlopen_int_funcs))
1024     {
1025         fprintf(stderr,"Failed to find _dl_open\n");
1026     }
1027     else
1028     {
1029         if(dlopen_int_funcs.size() > 1)
1030         {
1031             startup_printf("%s[%d] warning: found %d matches for %s\n",
1032                            __FILE__,__LINE__,dlopen_int_funcs.size(),
1033                            DL_OPEN_FUNC_INTERNAL);
1034         }
1035         dlopen_int_funcs[0]->getStaticCallers(dlopen_funcs);
1036         if(dlopen_funcs.size() > 1)
1037         {
1038             startup_printf("%s[%d] warning: found %d do_dlopen candidates\n",
1039                            __FILE__,__LINE__,dlopen_funcs.size());
1040         }
1041
1042         if(dlopen_funcs.size() > 0)
1043         {
1044             // give it a name
1045             dlopen_funcs[0]->addSymTabName("do_dlopen",true);
1046         }
1047     }
1048   }
1049
1050   if(dlopen_funcs.size() == 0)
1051   {
1052       startup_cerr << "Couldn't find method to load dynamic library" << endl;
1053       return false;
1054   }
1055
1056   Address dlopen_addr = dlopen_funcs[0]->getAddress();
1057   int_function *dlopen_func = dlopen_funcs[0];  //aix.C
1058
1059   assert(dyninstRT_name.length() < BYTES_TO_SAVE);
1060   startup_cerr << "Dyninst RT lib name: " << dyninstRT_name << endl;
1061
1062   // We now fill in the scratch code buffer with appropriate data
1063
1064   scratchCodeBuffer.setAddrSpace(this);  //aix.C
1065   scratchCodeBuffer.setAddr(codeBase); //aix.C
1066
1067   // First copy the RT library name
1068   dyninstlib_str_addr = codeBase + scratchCodeBuffer.used();
1069   scratchCodeBuffer.copy(dyninstRT_name.c_str(), dyninstRT_name.length()+1);
1070
1071   startup_printf("(%d) dyninst str addr at 0x%x\n", getPid(),
1072                                                     dyninstlib_str_addr);
1073   startup_printf("(%d) after copy, %d used\n", getPid(),
1074                                                scratchCodeBuffer.used());
1075
1076   // Now we have enough to fill in the do_dlopen_struct
1077   if (getAddressWidth() == sizeof(uint64_t)) {
1078      do_dlopen_struct.elf64.libname     = dyninstlib_str_addr;
1079      do_dlopen_struct.elf64.mode        = DLOPEN_MODE;
1080      do_dlopen_struct.elf64.result      = 0;
1081      do_dlopen_struct.elf64.caller_addr = dlopen_addr;
1082   }
1083   else {
1084      do_dlopen_struct.elf32.libname     = dyninstlib_str_addr;
1085      do_dlopen_struct.elf32.mode        = DLOPEN_MODE;
1086      do_dlopen_struct.elf32.result      = 0;
1087      do_dlopen_struct.elf32.caller_addr = dlopen_addr;
1088   }
1089
1090   // Need a register space                                           //aix.C
1091   // make sure this syncs with inst-power.C                          //aix.C
1092   registerSpace *dlopenRegSpace = registerSpace::savedRegSpace(this);//aix.C
1093   scratchCodeBuffer.setRegisterSpace(dlopenRegSpace);                //aix.C
1094
1095   // Now we place the do_dlopen_struct on the mutatee's stack
1096   //   Step 1.  getRegisters() to get copy of mutatee's stack frame pointer
1097   //   Step 2.  decrement our local copy of mutatee's stack frame pointer
1098   //   Step 3.  restoreRegisters() to update mutatee's stack frame pointer
1099   //   Step 4.  increment our local copy of mutatee's stack frame pointer
1100   //              back to its original value so that we properly restore
1101   //              the mutatee's registers after the RT library is loaded
1102   //   Step 5.  writeDataSpace() to the stack our do_dlopen_struct
1103
1104   //   Step 1.  getRegisters() to get copy of mutatee's stack frame pointer
1105   dyn_lwp *lwp_to_use = NULL;
1106   if(process::IndependentLwpControl() && getRepresentativeLWP() == NULL)
1107      lwp_to_use = getInitialThread()->get_lwp();
1108   else
1109      lwp_to_use = getRepresentativeLWP();
1110
1111   savedRegs = new dyn_saved_regs;
1112   bool status = lwp_to_use->getRegisters(savedRegs);
1113
1114   assert((status!=false) && (savedRegs!=(void *)-1));
1115    
1116   //   Step 2.  decrement our local copy of mutatee's stack frame pointer
1117   if (getAddressWidth() == sizeof(uint64_t))
1118      savedRegs->gprs.gpr[1] -= ALIGN_QUADWORD(STACKSKIP
1119                                               + sizeof(do_dlopen_struct.elf64));
1120   else
1121      savedRegs->gprs.gpr[1] -= ALIGN_QUADWORD(STACKSKIP
1122                                               + sizeof(do_dlopen_struct.elf32));
1123   do_dlopen_struct_addr = savedRegs->gprs.gpr[1];
1124
1125   //   Step 3.  restoreRegisters() to update mutatee's stack frame pointer
1126   lwp_to_use->restoreRegisters(*savedRegs);
1127
1128   //   Step 4.  increment our local copy of mutatee's stack frame pointer
1129   //              back to its original value so that we properly restore
1130   //              the mutatee's registers after the RT library is loaded
1131   if (getAddressWidth() == sizeof(uint64_t))
1132      savedRegs->gprs.gpr[1] += ALIGN_QUADWORD(STACKSKIP
1133                                               + sizeof(do_dlopen_struct.elf64));
1134   else
1135      savedRegs->gprs.gpr[1] += ALIGN_QUADWORD(STACKSKIP
1136                                               + sizeof(do_dlopen_struct.elf32));
1137
1138   //   Step 5.  writeDataSpace() to the stack our do_dlopen_struct
1139   if (getAddressWidth() == sizeof(uint64_t))
1140      writeDataSpace((void *)(do_dlopen_struct_addr),
1141                     sizeof(do_dlopen_struct.elf64), &do_dlopen_struct.elf64);
1142   else
1143      writeDataSpace((void *)(do_dlopen_struct_addr),
1144                     sizeof(do_dlopen_struct.elf32), &do_dlopen_struct.elf32);
1145
1146
1147   // Now back to generating code for the call to do_dlopen ...
1148
1149 #if defined(bug_syscall_changepc_rewind)
1150   // Reported by SGI, during attach to a process in a system call:
1151
1152   // Insert eight NOP instructions before the actual call to dlopen(). Loading
1153   // the runtime library when the mutatee was in a system call will sometimes
1154   // cause the process to (on IA32 anyway) execute the instruction four bytes
1155   // PREVIOUS to the PC we actually set here. No idea why. Prepending the
1156   // actual dlopen() call with eight NOP instructions insures this doesn't
1157   // really matter. Eight was selected rather than four because I don't know
1158   // if x86-64 does the same thing (and jumps eight bytes instead of four).
1159
1160   // We will put in <addr width> rather than always 8; this will be 4 on x86 and  // 32-bit AMD64, and 8 on 64-bit AMD64.
1161
1162   scratchCodeBuffer.fill(getAddressWidth(), codeGen::cgNOP);
1163
1164   // And since we apparently execute at (addr - <width>), shift dlopen_call_addr  // up past the NOPs.
1165 #endif
1166
1167   dlopen_call_addr = codeBase + scratchCodeBuffer.used();
1168
1169   pdvector<AstNodePtr> dlopenAstArgs(1);                         //aix.C
1170   AstNodePtr dlopenAst;                                          //aix.C
1171   dlopenAstArgs[0] = AstNode::operandNode(AstNode::Constant,     //aix.C
1172                                           (void*)do_dlopen_struct_addr);
1173   dlopenAst = AstNode::funcCallNode(dlopen_func, dlopenAstArgs); //aix.C
1174
1175   startup_printf("(%d): emitting call from 0x%x to 0x%x\n",
1176                  getPid(), codeBase + scratchCodeBuffer.used(), dlopen_addr);
1177
1178   // We need to push down the stack before we call this  //aix.C
1179   pushStack(scratchCodeBuffer);                          //aix.C
1180   dlopenAst->generateCode(scratchCodeBuffer, true);      //aix.C
1181   popStack(scratchCodeBuffer);                           //aix.C
1182
1183   // And the break point
1184   dyninstlib_brk_addr = codeBase + scratchCodeBuffer.used();
1185   insnCodeGen::generateTrap(scratchCodeBuffer);
1186
1187   startup_printf("(%d) dyninst lib string addr at 0x%x\n", getPid(),
1188                                                            dyninstlib_str_addr);
1189   startup_printf("(%d) dyninst lib call addr at 0x%x\n", getPid(),
1190                                                          dlopen_call_addr);
1191   startup_printf("(%d) break address is at %p\n", getPid(),
1192                                                   (void *)dyninstlib_brk_addr);
1193   startup_printf("(%d) writing %d bytes\n", getPid(), scratchCodeBuffer.used());
1194
1195   // savedCodeBuffer[BYTES_TO_SAVE] is declared in process.h
1196   // We can tighten this up if we record how much we saved
1197
1198   if (!readDataSpace((void *)codeBase, sizeof(savedCodeBuffer),
1199                      savedCodeBuffer, true))
1200          fprintf(stderr, "%s[%d]:  readDataSpace\n", __FILE__, __LINE__);
1201
1202   startup_printf("(%d) Writing from %p to %p\n", getPid(),
1203                  (char *)scratchCodeBuffer.start_ptr(), (char *)codeBase);
1204   writeDataSpace((void *)(codeBase), scratchCodeBuffer.used(),
1205                  scratchCodeBuffer.start_ptr());
1206
1207   Address destPC = dlopen_call_addr;
1208
1209   startup_printf("Changing PC to 0x%x\n", destPC);
1210   startup_printf("String at 0x%x\n", dyninstlib_str_addr);
1211
1212   if (! lwp_to_use->changePC(destPC,NULL))
1213     {
1214       logLine("WARNING: changePC failed in dlopenDYNINSTlib\n");
1215       assert(0);
1216     }
1217
1218   setBootstrapState(loadingRT_bs);
1219   return true;
1220 }
1221
1222
1223
1224 Frame process::preStackWalkInit(Frame startFrame)
1225 {
1226 #if 0  // Matt's DynStackwalker will replace this; "quick and dirty" for now
1227   /* Do a special check for the vsyscall page.  Silently drop
1228      the page if it exists. */
1229   calcVSyscallFrame( this );
1230
1231   Address next_pc = startFrame.getPC();
1232   if ((next_pc >= getVsyscallStart() && next_pc < getVsyscallEnd()) ||
1233       /* RH9 Hack */ (next_pc >= 0xffffe000 && next_pc < 0xfffff000)) {
1234      return startFrame.getCallerFrame();
1235   }
1236 #endif
1237   return startFrame;
1238 }
1239
1240
1241 // floor of inferior malloc address range within a single branch of x
1242 // for 32-bit ELF PowerPC mutatees
1243 Address region_lo(const Address x) {
1244    const Address floor = getpagesize();
1245
1246    assert(x >= floor);
1247
1248    if ((x > floor) && (x - floor > getMaxBranch()))
1249       return x - getMaxBranch();
1250
1251    return floor;
1252 }
1253
1254
1255 // floor of inferior malloc address range within a single branch of x
1256 // for 64-bit ELF PowerPC mutatees
1257 Address region_lo_64(const Address x) {
1258    const Address floor = getpagesize();
1259
1260    assert(x >= floor);
1261
1262    if ((x > floor) && (x - floor > getMaxBranch()))
1263       return x - getMaxBranch();
1264
1265    return floor;
1266 }
1267
1268
1269 // ceiling of inferior malloc address range within a single branch of x
1270 // for 32-bit ELF PowerPC mutatees
1271 Address region_hi(const Address x) {
1272    const Address ceiling = ~(Address)0 & 0xffffffff;
1273
1274    assert(x < ceiling);
1275
1276    if ((x < ceiling) && (ceiling - x > getMaxBranch()))
1277       return x + getMaxBranch();
1278
1279    return ceiling;
1280 }
1281
1282
1283 // ceiling of inferior malloc address range within a single branch of x
1284 // for 64-bit ELF PowerPC mutatees
1285 Address region_hi_64(const Address x) {
1286    const Address ceiling = ~(Address)0;
1287
1288    assert(x < ceiling);
1289
1290    if ((x < ceiling) && (ceiling - x > getMaxBranch()))
1291       return x + getMaxBranch();
1292
1293    return ceiling;
1294 }
1295