diff options
Diffstat (limited to 'coregrind/m_stacktrace.c')
-rw-r--r-- | coregrind/m_stacktrace.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index 489f6d71..707b470d 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -670,6 +670,85 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, #endif +/* ------------------------ s390x ------------------------- */ +#if defined(VGP_s390x_linux) +UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known, + /*OUT*/Addr* ips, UInt max_n_ips, + /*OUT*/Addr* sps, /*OUT*/Addr* fps, + UnwindStartRegs* startRegs, + Addr fp_max_orig ) +{ + Bool debug = False; + Int i; + Addr fp_max; + UInt n_found = 0; + + vg_assert(sizeof(Addr) == sizeof(UWord)); + vg_assert(sizeof(Addr) == sizeof(void*)); + + D3UnwindRegs uregs; + uregs.ia = startRegs->r_pc; + uregs.sp = startRegs->r_sp; + Addr fp_min = uregs.sp; + uregs.fp = startRegs->misc.S390X.r_fp; + uregs.lr = startRegs->misc.S390X.r_lr; + + fp_max = VG_PGROUNDUP(fp_max_orig); + if (fp_max >= sizeof(Addr)) + fp_max -= sizeof(Addr); + + if (debug) + VG_(printf)("max_n_ips=%d fp_min=0x%lx fp_max_orig=0x%lx, " + "fp_max=0x%lx IA=0x%lx SP=0x%lx FP=0x%lx\n", + max_n_ips, fp_min, fp_max_orig, fp_max, + uregs.ia, uregs.sp,uregs.fp); + + /* The first frame is pretty obvious */ + ips[0] = uregs.ia; + if (sps) sps[0] = uregs.sp; + if (fps) fps[0] = uregs.fp; + i = 1; + + /* for everything else we have to rely on the eh_frame. gcc defaults to + not create a backchain and all the other tools (like gdb) also have + to use the CFI. */ + while (True) { + if (i >= max_n_ips) + break; + + if (VG_(use_CF_info)( &uregs, fp_min, fp_max )) { + if (sps) sps[i] = uregs.sp; + if (fps) fps[i] = uregs.fp; + ips[i++] = uregs.ia - 1; + uregs.ia = uregs.ia - 1; + continue; + } + /* A problem on the first frame? Lets assume it was a bad jump. + We will use the link register and the current stack and frame + pointers and see if we can use the CFI in the next round. */ + if (i == 1) { + if (sps) { + sps[i] = sps[0]; + uregs.sp = sps[0]; + } + if (fps) { + fps[i] = fps[0]; + uregs.fp = fps[0]; + } + uregs.ia = uregs.lr - 1; + ips[i++] = uregs.lr - 1; + continue; + } + + /* No luck. We have to give up. */ + break; + } + + n_found = i; + return n_found; +} +#endif + /*------------------------------------------------------------*/ /*--- ---*/ /*--- END platform-dependent unwinder worker functions ---*/ |