Update Examples in dataflowAPI (#700)
[dyninst.git] / stackwalk / src / dbginfo-stepper.C
1 /*
2  * See the dyninst/COPYRIGHT file for copyright information.
3  *
4  * We provide the Paradyn Tools (below described as "Paradyn")
5  * on an AS IS basis, and do not warrant its validity or performance.
6  * We reserve the right to update, modify, or discontinue this
7  * software at any time.  We shall have no obligation to supply such
8  * updates or modifications or any other form of support to you.
9  *
10  * By your use of Paradyn, you understand and agree that we (or any
11  * other person or entity with proprietary rights in Paradyn) are
12  * under no obligation to provide either maintenance services,
13  * update services, notices of latent defects, or correction of
14  * defects for Paradyn.
15  *
16  * This library is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU Lesser General Public
18  * License as published by the Free Software Foundation; either
19  * version 2.1 of the License, or (at your option) any later version.
20  *
21  * This library is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24  * Lesser General Public License for more details.
25  *
26  * You should have received a copy of the GNU Lesser General Public
27  * License along with this library; if not, write to the Free Software
28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29  */
30
31 #include "stackwalk/h/framestepper.h"
32 #include "stackwalk/h/frame.h"
33 #include "stackwalk/h/procstate.h"
34 #include "stackwalk/h/swk_errors.h"
35 #include "stackwalk/h/steppergroup.h"
36 #include "stackwalk/h/walker.h"
37 #include "stackwalk/src/dbgstepper-impl.h"
38 #include "stackwalk/src/linuxbsd-swk.h"
39 #include "stackwalk/src/libstate.h"
40 #include "common/h/dyntypes.h"
41 #include "common/h/VariableLocation.h"
42 #include "common/src/Types.h"
43 #include "dwarfFrameParser.h"
44 #include "dwarfHandle.h"
45
46 #if defined(WITH_SYMTAB_API)
47 #include "symtabAPI/h/Symtab.h"
48 #endif
49
50 using namespace Dyninst;
51 using namespace Stackwalker;
52 using namespace DwarfDyninst;
53
54 static std::map<std::string, DwarfFrameParser::Ptr> dwarf_info;
55
56 #include <sys/ucontext.h>
57 #include <stdarg.h>
58 #include "dwarf.h"
59 #include "elfutils/libdw.h"
60 #include "Elf_X.h"
61
62 static DwarfFrameParser::Ptr getAuxDwarfInfo(std::string s)
63 {
64    static std::map<std::string, DwarfFrameParser::Ptr > dwarf_aux_info;
65
66    std::map<std::string, DwarfFrameParser::Ptr >::iterator i = dwarf_aux_info.find(s);
67    if (i != dwarf_aux_info.end())
68       return i->second;
69
70    SymReader *orig_reader = LibraryWrapper::getLibrary(s);
71    if (!orig_reader) {
72       sw_printf("[%s:%u] - Error.  Could not find elf handle for %s\n",
73                 FILE__, __LINE__, s.c_str());
74       return DwarfFrameParser::Ptr();
75    }
76    Elf_X *orig_elf = (Elf_X *) orig_reader->getElfHandle();
77    if (!orig_elf) {
78       sw_printf("[%s:%u] - Error. Could not find elf handle for file %s\n",
79                 FILE__, __LINE__, s.c_str());
80       dwarf_aux_info[s] = DwarfFrameParser::Ptr();
81       return DwarfFrameParser::Ptr();
82    }
83
84    DwarfHandle::ptr dwarf = DwarfHandle::createDwarfHandle(s, orig_elf);
85    assert(dwarf);
86    sw_printf("[%s:%u] - Separate debug file used: %s\n",
87            FILE__, __LINE__, dwarf->getDebugFilename().c_str());
88
89    // MJMTODO - Need to check whether this is supposed to work or not
90    // FIXME for ppc, if we ever support debug walking on ppc
91    Architecture arch;
92 #if defined(arch_x86) || defined(arch_x86_64)
93    if (orig_elf->wordSize() == 4)
94       arch = Dyninst::Arch_x86;
95    else
96       arch = Dyninst::Arch_x86_64;
97 #elif defined(arch_aarch64)
98     arch = Dyninst::Arch_aarch64;
99 #endif
100
101    DwarfFrameParser::Ptr dresult = DwarfFrameParser::create(*dwarf->frame_dbg(), dwarf->origFile()->e_elfp(), arch);
102    if(!dresult) return NULL;
103    dwarf_aux_info[s] = dresult;
104    return dresult;
105 }
106
107
108 DebugStepperImpl::DebugStepperImpl(Walker *w, DebugStepper *parent) :
109    FrameStepper(w),
110    last_addr_read(0),
111    last_val_read(0),
112    addr_width(0),
113    parent_stepper(parent),
114    cur_frame(NULL),
115    depth_frame(NULL)
116 {
117 }
118
119 bool DebugStepperImpl::ReadMem(Address addr, void *buffer, unsigned size)
120 {
121    bool result = getProcessState()->readMem(buffer, addr, size);
122
123    last_addr_read = 0;
124    if (!result)
125       return false;
126    if (size != addr_width)
127       return false;
128
129    last_addr_read = addr;
130    if (addr_width == 4) {
131       uint32_t v = *((uint32_t *) buffer);
132       last_val_read = v;
133    }
134    else if (addr_width == 8) {
135       uint64_t v = *((uint64_t *) buffer);
136       last_val_read = v;
137    }
138    else {
139       assert(0); //Unknown size
140    }
141
142    return true;
143 }
144
145 location_t DebugStepperImpl::getLastComputedLocation(unsigned long value)
146 {
147    location_t loc;
148    if (last_addr_read && last_val_read == value) {
149       loc.val.addr = last_addr_read;
150       loc.location = loc_address;
151    }
152    else {
153       loc.val.addr = 0;
154       loc.location = loc_unknown;
155    }
156    last_addr_read = 0;
157    last_val_read = 0;
158    return loc;
159 }
160
161 bool DebugStepperImpl::GetReg(MachRegister reg, MachRegisterVal &val)
162 {
163    sw_printf("[%s:%u] Attempt to get value for reg %s\n", FILE__, __LINE__, reg.name().c_str());
164    if (reg.isFramePointer()) {
165       val = static_cast<MachRegisterVal>(depth_frame->getFP());
166       return true;
167    }
168
169    if (reg.isStackPointer()) {
170       val = static_cast<MachRegisterVal>(depth_frame->getSP());
171       return true;
172    }
173
174    if (reg.isPC()) {
175       val = static_cast<MachRegisterVal>(depth_frame->getRA());
176       return true;
177    }
178
179    bool result = false;
180    const Frame *prevDepthFrame = depth_frame;
181    depth_frame = depth_frame->getPrevFrame();
182    if (!depth_frame)
183    {
184       result = getProcessState()->getRegValue(reg, cur_frame->getThread(), val);
185    }
186 #if defined(WITH_SYMTAB_API)
187    else
188    {
189       Offset offset;
190       void *symtab_v = NULL;
191       std::string lib;
192       depth_frame->getLibOffset(lib, offset, symtab_v);
193       SymtabAPI::Symtab *symtab = (SymtabAPI::Symtab*) symtab_v;
194       if (symtab)
195       {
196          result = symtab->getRegValueAtFrame(offset, reg, val, this);
197       }
198 #if defined(arch_aarch64)
199       if (!result) {
200           sw_printf("Cast framestepper %p for frame %p to SigHandlerStepper at address %lx\n", prevDepthFrame->getStepper(), prevDepthFrame, prevDepthFrame->getRA());
201
202           SigHandlerStepper * ss = dynamic_cast<SigHandlerStepper*> (prevDepthFrame->getStepper());
203           if (ss != NULL) {
204               sw_printf("[%s:%u] - Not the first frame, cannot find dbg information, and previous frame is a signal trampoline frame. Try to get x30 from ucontext as RA\n",
205                 FILE__, __LINE__);
206               static     ucontext_t dummy_context;
207               static int lr_offset = (char*)&(dummy_context.uc_mcontext.regs[30]) - (char*)&dummy_context;
208               // This assumes that a ucontext_t is at the following offset from the top of the signal handler's stack.
209               static int ucontext_offset = 128;
210               const Frame * signal_frame = depth_frame;
211               if (signal_frame != NULL) {
212                   int addr_size = 8;
213                   Address lr_addr = signal_frame->getSP() + ucontext_offset + lr_offset;
214                   result = getProcessState()->readMem(&val, lr_addr, addr_size);
215               sw_printf("[%s:%u] - readMem results %d, get %lx as RA\n",
216                 FILE__, __LINE__, result, val);
217
218               } else {
219               sw_printf("[%s:%u] - the signal trampoline frame does not have a parent frame\n",
220                 FILE__, __LINE__);
221               }
222           } else {
223               sw_printf("Cannot cast framestepper to SigHandlerStepper\n");
224           }
225        }
226 #endif      
227    }
228 #endif
229
230    depth_frame = prevDepthFrame;
231    return result;
232 }
233
234 gcframe_ret_t DebugStepperImpl::getCallerFrame(const Frame &in, Frame &out)
235 {
236    LibAddrPair lib;
237    bool result;
238
239    if (lookupInCache(in, out)) {
240        result = getProcessState()->getLibraryTracker()->getLibraryAtAddr(out.getRA(), lib);
241        if (result) {
242            // Hit, and valid RA found
243            return gcf_success;
244        }
245    }
246
247    // This error check is duplicated in BottomOfStackStepper.
248    // We should always call BOSStepper first; however, we need the
249    // library for the debug stepper as well. If this becomes
250    // a performance problem we can cache the library info in
251    // the input frame.
252    result = getProcessState()->getLibraryTracker()->getLibraryAtAddr(in.getRA(), lib);
253    if (!result) {
254       sw_printf("[%s:%u] - Stackwalking with PC at %lx, which is not found in any known libraries\n",
255                 FILE__, __LINE__, in.getRA());
256       return gcf_not_me;
257    }
258    Address pc = in.getRA() - lib.second;
259    sw_printf("[%s:%u] Dwarf-based stackwalking, using local address 0x%lx from 0x%lx - 0x%lx\n",
260              FILE__, __LINE__, pc, in.getRA(), lib.second);
261    if (in.getRALocation().location != loc_register && !in.nonCall()) {
262       /**
263        * If we're here, then our in.getRA() should be pointed at the
264        * instruction following a call.  We could either use the
265        * call instruction's debug info (pc - 1) or the following
266        * instruction's debug info (pc) to continue the stackwalk.
267        *
268        * In most cases it doesn't matter.  Because of how DWARF debug
269        * info is defined, the stack doesn't change between these two points.
270        *
271        * However, if the call is a non-returning call (e.g, a call to exit)
272        * then the next instruction may not exist or may be part of a separate
273        * block with different debug info.  In these cases we want to use the
274        * debug info associated with the call.  So, we subtract 1 from the
275        * pc to get at the call instruction.
276        **/
277       pc = pc - 1;
278    }
279
280    /**
281     * Some system libraries on some systems have their debug info split
282     * into separate files, usually in /usr/lib/debug/.  Check these
283     * for DWARF debug info
284     **/
285    DwarfFrameParser::Ptr dauxinfo = getAuxDwarfInfo(lib.first);
286    if (!dauxinfo || !dauxinfo->hasFrameDebugInfo()) {
287       sw_printf("[%s:%u] - Library %s does not have stackwalking debug info\n",
288                  FILE__, __LINE__, lib.first.c_str());
289       return gcf_not_me;
290    }
291
292    bool isVsyscallPage = false;
293 #if defined(os_linux)
294    sw_printf("ARM-debug: dump lib========================\n");
295    sw_printf("%s\n", lib.first.c_str());
296    sw_printf("ARM-debug: dump lib========================\n");
297    isVsyscallPage = (strstr(lib.first.c_str(), "[vsyscall-") != NULL);
298 #endif
299
300    sw_printf("[%s:%u] - Using DWARF debug file info for %s\n",
301                    FILE__, __LINE__, lib.first.c_str());
302    cur_frame = &in;
303    gcframe_ret_t gcresult = getCallerFrameArch(pc, in, out, dauxinfo, isVsyscallPage);
304    cur_frame = NULL;
305
306    result = getProcessState()->getLibraryTracker()->getLibraryAtAddr(out.getRA(), lib);
307    if (!result) return gcf_not_me;
308
309    if (gcresult == gcf_success) {
310       sw_printf("[%s:%u] - Success walking with DWARF aux file\n",
311                 FILE__, __LINE__);
312       return gcf_success;
313    }
314
315    return gcresult;
316 }
317
318 void DebugStepperImpl::registerStepperGroup(StepperGroup *group)
319 {
320    addr_width = group->getWalker()->getProcessState()->getAddressWidth();
321    if (addr_width == 4)
322       group->addStepper(parent_stepper, 0, 0xffffffff);
323 #if defined(arch_64bit)
324    else if (addr_width == 8)
325       group->addStepper(parent_stepper, 0, 0xffffffffffffffff);
326 #endif
327    else
328       assert(0 && "Unknown architecture word size");
329 }
330
331 unsigned DebugStepperImpl::getPriority() const
332 {
333    return debugstepper_priority;
334 }
335
336 DebugStepperImpl::~DebugStepperImpl()
337 {
338 }
339
340 #if defined(arch_x86) || defined(arch_x86_64)
341 gcframe_ret_t DebugStepperImpl::getCallerFrameArch(Address pc, const Frame &in,
342                                                    Frame &out, DwarfFrameParser::Ptr dinfo,
343                                                    bool isVsyscallPage)
344 {
345    MachRegisterVal frame_value, stack_value, ret_value;
346    bool result;
347    FrameErrors_t frame_error = FE_No_Error;
348
349    addr_width = getProcessState()->getAddressWidth();
350
351    depth_frame = cur_frame;
352
353    result = dinfo->getRegValueAtFrame(pc, Dyninst::ReturnAddr,
354                                       ret_value, this, frame_error);
355
356    if (!result && frame_error == FE_No_Frame_Entry && isVsyscallPage) {
357       //Work-around kernel bug.  The vsyscall page location was randomized, but
358       // the debug info still has addresses from the old, pre-randomized days.
359       // See if we get any hits by assuming the address corresponds to the
360       // old PC.
361       pc += 0xffffe000;
362       result = dinfo->getRegValueAtFrame(pc, Dyninst::ReturnAddr,
363                                          ret_value, this, frame_error);
364    }
365    if (!result) {
366       sw_printf("[%s:%u] - Couldn't get return debug info at %lx, error: %u\n",
367                 FILE__, __LINE__, in.getRA(), frame_error);
368       return gcf_not_me;
369    }
370    location_t ra_loc = getLastComputedLocation(ret_value);
371
372    Dyninst::MachRegister frame_reg;
373    if (addr_width == 4)
374       frame_reg = x86::ebp;
375    else
376       frame_reg = x86_64::rbp;
377
378    result = dinfo->getRegValueAtFrame(pc, frame_reg,
379                                       frame_value, this, frame_error);
380    if (!result) {
381       sw_printf("[%s:%u] - Couldn't get frame debug info at %lx\n",
382                  FILE__, __LINE__, in.getRA());
383       return gcf_not_me;
384    }
385    location_t fp_loc = getLastComputedLocation(frame_value);
386
387    result = dinfo->getRegValueAtFrame(pc, Dyninst::FrameBase,
388                                       stack_value, this, frame_error);
389    if (!result) {
390       sw_printf("[%s:%u] - Couldn't get stack debug info at %lx\n",
391                  FILE__, __LINE__, in.getRA());
392       return gcf_not_me;
393    }
394    location_t sp_loc = getLastComputedLocation(stack_value);
395
396    if (isVsyscallPage) {
397       // RHEL6 has broken DWARF in the vsyscallpage; it has
398       // a double deref for the stack pointer. We detect this
399       // (as much as we can...) and ignore it
400       if (stack_value < in.getSP()) {
401          stack_value = 0;
402          sp_loc.location = loc_unknown;
403       }
404    }
405
406    Address MAX_ADDR;
407    if (addr_width == 4) {
408        MAX_ADDR = 0xffffffff;
409    }
410 #if defined(arch_64bit)
411    else if (addr_width == 8){
412        MAX_ADDR = 0xffffffffffffffff;
413    }
414 #endif
415    else {
416        assert(0 && "Unknown architecture word size");
417    }
418
419    if(ra_loc.val.addr > MAX_ADDR || fp_loc.val.addr > MAX_ADDR || sp_loc.val.addr > MAX_ADDR) return gcf_not_me;
420
421    out.setRA(ret_value);
422    out.setFP(frame_value);
423    out.setSP(stack_value);
424    out.setRALocation(ra_loc);
425    out.setFPLocation(fp_loc);
426    out.setSPLocation(sp_loc);
427
428    addToCache(in, out);
429
430    return gcf_success;
431 }
432
433 void DebugStepperImpl::addToCache(const Frame &cur, const Frame &caller) {
434   const location_t &calRA = caller.getRALocation();
435
436   const location_t &calFP = caller.getFPLocation();
437
438   unsigned raDelta = (unsigned) -1;
439   unsigned fpDelta = (unsigned) -1;
440   unsigned spDelta = (unsigned) -1;
441
442   if (calRA.location == loc_address) {
443     raDelta = calRA.val.addr - cur.getSP();
444   }
445
446   if (calFP.location == loc_address) {
447     fpDelta = calFP.val.addr - cur.getSP();
448   }
449
450   spDelta = caller.getSP() - cur.getSP();
451
452   cache_[cur.getRA()] = cache_t(raDelta, fpDelta, spDelta);
453 }
454
455 bool DebugStepperImpl::lookupInCache(const Frame &cur, Frame &caller) {
456   dyn_hash_map<Address,cache_t>::iterator iter = cache_.find(cur.getRA());
457   if (iter == cache_.end()) {
458       return false;
459   }
460
461   addr_width = getProcessState()->getAddressWidth();
462
463   if (iter->second.ra_delta == (unsigned) -1) {
464       return false;
465   }
466   if (iter->second.fp_delta == (unsigned) -1) {
467     return false;
468   }
469   assert(iter->second.sp_delta != (unsigned) -1);
470
471   Address MAX_ADDR;
472    if (addr_width == 4) {
473        MAX_ADDR = 0xffffffff;
474    }
475 #if defined(arch_64bit)
476    else if (addr_width == 8){
477        MAX_ADDR = 0xffffffffffffffff;
478    }
479 #endif
480    else {
481        assert(0 && "Unknown architecture word size");
482        return false;
483    }
484
485   location_t RA;
486   RA.location = loc_address;
487   RA.val.addr = cur.getSP() + iter->second.ra_delta;
488   RA.val.addr %= MAX_ADDR;
489
490   location_t FP;
491   FP.location = loc_address;
492   FP.val.addr = cur.getSP() + iter->second.fp_delta;
493
494   FP.val.addr %= MAX_ADDR;
495   int buffer[10];
496
497   caller.setRALocation(RA);
498   ReadMem(RA.val.addr, buffer, addr_width);
499   caller.setRA(last_val_read);
500
501   caller.setFPLocation(FP);
502   ReadMem(FP.val.addr, buffer, addr_width);
503   caller.setFP(last_val_read);
504
505   caller.setSP(cur.getSP() + iter->second.sp_delta);
506
507   return true;
508 }
509
510 #endif
511
512 // for aarch64 architecure specifically
513 #if defined(arch_aarch64)
514 gcframe_ret_t DebugStepperImpl::getCallerFrameArch(Address pc, const Frame &in,
515                                                    Frame &out, DwarfFrameParser::Ptr dinfo,
516                                                    bool isVsyscallPage)
517 {
518    MachRegisterVal frame_value, stack_value, ret_value;
519    bool result;
520    FrameErrors_t frame_error = FE_No_Error;
521
522    addr_width = getProcessState()->getAddressWidth();
523
524    depth_frame = cur_frame;
525
526    sw_printf("\nDebugStepperImpl::getCallerFrameArch() calls getRegValueAtFrame()\n");
527    result = dinfo->getRegValueAtFrame(pc, Dyninst::ReturnAddr,
528    //result = dinfo->getRegValueAtFrame(pc, Dyninst::aarch64::x30,
529                                       ret_value, this, frame_error);
530
531    if (!result && frame_error == FE_No_Frame_Entry && isVsyscallPage) {
532       //Work-around kernel bug.  The vsyscall page location was randomized, but
533       // the debug info still has addresses from the old, pre-randomized days.
534       // See if we get any hits by assuming the address corresponds to the
535       // old PC.
536       pc += 0xffffe000;
537       result = dinfo->getRegValueAtFrame(pc, Dyninst::ReturnAddr,
538                                          ret_value, this, frame_error);
539    }
540    if (!result) {
541       sw_printf("[%s:%u] - Couldn't get return debug info at %lx, error: %u\n",
542                 FILE__, __LINE__, in.getRA(), frame_error);
543       return gcf_not_me;
544    }
545    location_t ra_loc = getLastComputedLocation(ret_value);
546
547    Dyninst::MachRegister frame_reg;
548    frame_reg = Dyninst::aarch64::x29;
549
550    sw_printf("\nDebugStepperImpl::getCallerFrameArch() calls getRegValueAtFrame()\n");
551    result = dinfo->getRegValueAtFrame(pc, frame_reg,
552                                       frame_value, this, frame_error);
553    if (!result) {
554       sw_printf("[%s:%u] - Couldn't get frame debug info at %lx\n",
555                  FILE__, __LINE__, in.getRA());
556       return gcf_not_me;
557    }
558    location_t fp_loc = getLastComputedLocation(frame_value);
559
560    sw_printf("\nDebugStepperImpl::getCallerFrameArch() calls getRegValueAtFrame()\n");
561    result = dinfo->getRegValueAtFrame(pc, Dyninst::FrameBase,
562                                       stack_value, this, frame_error);
563    if (!result) {
564       sw_printf("[%s:%u] - Couldn't get stack debug info at %lx\n",
565                  FILE__, __LINE__, in.getRA());
566       return gcf_not_me;
567    }
568    location_t sp_loc = getLastComputedLocation(stack_value);
569
570    if (isVsyscallPage) {
571       // RHEL6 has broken DWARF in the vsyscallpage; it has
572       // a double deref for the stack pointer. We detect this
573       // (as much as we can...) and ignore it
574       if (stack_value < in.getSP()) {
575          stack_value = 0;
576          sp_loc.location = loc_unknown;
577       }
578    }
579
580    Address MAX_ADDR;
581    if (addr_width == 4) {
582        MAX_ADDR = 0xffffffff;
583    }
584    else if (addr_width == 8){
585        MAX_ADDR = 0xffffffffffffffff;
586    }
587    else {
588        assert(0 && "Unknown architecture word size");
589    }
590
591    if(ra_loc.val.addr > MAX_ADDR || fp_loc.val.addr > MAX_ADDR || sp_loc.val.addr > MAX_ADDR) return gcf_not_me;
592
593    out.setRA(ret_value);
594    out.setFP(frame_value);
595    out.setSP(stack_value);
596    out.setRALocation(ra_loc);
597    out.setFPLocation(fp_loc);
598    out.setSPLocation(sp_loc);
599
600    addToCache(in, out);
601
602    return gcf_success;
603 }
604
605 void DebugStepperImpl::addToCache(const Frame &cur, const Frame &caller) {
606   const location_t &calRA = caller.getRALocation();
607
608   const location_t &calFP = caller.getFPLocation();
609
610   unsigned raDelta = (unsigned) -1;
611   unsigned fpDelta = (unsigned) -1;
612   unsigned spDelta = (unsigned) -1;
613
614   if (calRA.location == loc_address) {
615     raDelta = calRA.val.addr - cur.getSP();
616   }
617
618   if (calFP.location == loc_address) {
619     fpDelta = calFP.val.addr - cur.getSP();
620   }
621
622   spDelta = caller.getSP() - cur.getSP();
623
624   cache_[cur.getRA()] = cache_t(raDelta, fpDelta, spDelta);
625 }
626
627 bool DebugStepperImpl::lookupInCache(const Frame &cur, Frame &caller) {
628   dyn_hash_map<Address,cache_t>::iterator iter = cache_.find(cur.getRA());
629   if (iter == cache_.end()) {
630       return false;
631   }
632
633   addr_width = getProcessState()->getAddressWidth();
634
635   if (iter->second.ra_delta == (unsigned) -1) {
636       return false;
637   }
638   if (iter->second.fp_delta == (unsigned) -1) {
639     return false;
640   }
641   assert(iter->second.sp_delta != (unsigned) -1);
642
643   Address MAX_ADDR;
644    if (addr_width == 4) {
645        assert(0);
646        MAX_ADDR = 0xffffffff;
647    }
648    else if (addr_width == 8){
649        MAX_ADDR = 0xffffffffffffffff;
650    }
651    else {
652        assert(0 && "Unknown architecture word size");
653        return false;
654    }
655
656   location_t RA;
657   RA.location = loc_address;
658   RA.val.addr = cur.getSP() + iter->second.ra_delta;
659   RA.val.addr %= MAX_ADDR;
660
661   location_t FP;
662   FP.location = loc_address;
663   FP.val.addr = cur.getSP() + iter->second.fp_delta;
664
665   FP.val.addr %= MAX_ADDR;
666   int buffer[10];
667
668   caller.setRALocation(RA);
669   ReadMem(RA.val.addr, buffer, addr_width);
670   caller.setRA(last_val_read);
671
672   caller.setFPLocation(FP);
673   ReadMem(FP.val.addr, buffer, addr_width);
674   caller.setFP(last_val_read);
675
676   caller.setSP(cur.getSP() + iter->second.sp_delta);
677
678   return true;
679 }
680 #endif
681 //end if defined aarch64
682