|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:14
|
This patch wires up the dwarf and stacktrace handling. Since userspace
is usually built without a backchain, we have to rely on the dwarf
information, which is alwas present in the eh_frame.
---
coregrind/m_debuginfo/d3basics.c | 3 +
coregrind/m_debuginfo/debuginfo.c | 50 ++++++++++++++++++++++
coregrind/m_debuginfo/priv_storage.h | 18 +++++++
coregrind/m_debuginfo/readdwarf.c | 64 +++++++++++++++++++++++++++-
coregrind/m_debuginfo/readelf.c | 7 +--
coregrind/m_debuginfo/storage.c | 8 +++
coregrind/m_stacktrace.c | 79 +++++++++++++++++++++++++++++++++++
coregrind/pub_core_debuginfo.h | 4 +
8 files changed, 227 insertions(+), 6 deletions(-)
--- valgrind-upstream.orig/coregrind/m_debuginfo/d3basics.c
+++ valgrind-upstream/coregrind/m_debuginfo/d3basics.c
@@ -409,6 +409,9 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr*
if (regno == 11) { *a = regs->fp; return True; }
# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
vg_assert(0); /* this function should never be called */
+# elif defined(VGP_s390x_linux)
+ if (regno == 15) { *a = regs->sp; return True; }
+ if (regno == 11) { *a = regs->fp; return True; }
# else
# error "Unknown platform"
# endif
--- valgrind-upstream.orig/coregrind/m_debuginfo/debuginfo.c
+++ valgrind-upstream/coregrind/m_debuginfo/debuginfo.c
@@ -703,6 +703,15 @@ ULong VG_(di_notify_mmap)( Addr a, Bool
2009 Aug 16: apply similar kludge to ppc32-linux.
See http://bugs.kde.org/show_bug.cgi?id=190820
+
+ there are two modes on s390x: with and without the noexec kernel
+ parameter. Together with some older kernels, this leads to several
+ variants:
+ executable: r and x
+ data: r and w and x
+ or
+ executable: r and x
+ data: r and w
*/
is_rx_map = False;
is_rw_map = False;
@@ -712,6 +721,9 @@ ULong VG_(di_notify_mmap)( Addr a, Bool
# elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_arm)
is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
is_rw_map = seg->hasR && seg->hasW && !seg->hasX;
+# elif defined(VGP_s390x_linux)
+ is_rx_map = seg->hasR && seg->hasX && !seg->hasW;
+ is_rw_map = seg->hasR && seg->hasW;
# else
# error "Unknown platform"
# endif
@@ -2000,6 +2012,11 @@ UWord evalCfiExpr ( XArray* exprs, Int i
case Creg_ARM_R14: return eec->uregs->r14;
case Creg_ARM_R13: return eec->uregs->r13;
case Creg_ARM_R12: return eec->uregs->r12;
+# elif defined(VGA_s390x)
+ case Creg_IA_IP: return eec->uregs->ia;
+ case Creg_IA_SP: return eec->uregs->sp;
+ case Creg_IA_BP: return eec->uregs->fp;
+ case Creg_S390_R14: return eec->uregs->lr;
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unsupported arch"
@@ -2210,6 +2227,24 @@ static Addr compute_cfa ( D3UnwindRegs*
case CFIC_ARM_R7REL:
cfa = cfsi->cfa_off + uregs->r7;
break;
+# elif defined(VGA_s390x)
+ case CFIC_IA_SPREL:
+ cfa = cfsi->cfa_off + uregs->sp;
+ break;
+ case CFIR_MEMCFAREL:
+ {
+ Addr a = uregs->sp + cfsi->cfa_off;
+ if (a < min_accessible || a > max_accessible-sizeof(Addr))
+ break;
+ cfa = *(Addr*)a;
+ break;
+ }
+ case CFIR_SAME:
+ cfa = uregs->fp;
+ break;
+ case CFIC_IA_BPREL:
+ cfa = cfsi->cfa_off + uregs->fp;
+ break;
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unsupported arch"
@@ -2262,6 +2297,15 @@ Addr ML_(get_CFA) ( Addr ip, Addr sp, Ad
return compute_cfa(&uregs,
min_accessible, max_accessible, di, cfsi);
}
+#elif defined(VGA_s390x)
+ { D3UnwindRegs uregs;
+ uregs.ia = ip;
+ uregs.sp = sp;
+ uregs.fp = fp;
+ return compute_cfa(&uregs,
+ min_accessible, max_accessible, di, cfsi);
+ }
+
# else
return 0; /* indicates failure */
# endif
@@ -2294,6 +2338,8 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindR
ipHere = uregsHere->xip;
# elif defined(VGA_arm)
ipHere = uregsHere->r15;
+# elif defined(VGA_s390x)
+ ipHere = uregsHere->ia;
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unknown arch"
@@ -2366,6 +2412,10 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindR
COMPUTE(uregsPrev.r12, uregsHere->r12, cfsi->r12_how, cfsi->r12_off);
COMPUTE(uregsPrev.r11, uregsHere->r11, cfsi->r11_how, cfsi->r11_off);
COMPUTE(uregsPrev.r7, uregsHere->r7, cfsi->r7_how, cfsi->r7_off);
+# elif defined(VGA_s390x)
+ COMPUTE(uregsPrev.ia, uregsHere->ia, cfsi->ra_how, cfsi->ra_off);
+ COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi->sp_how, cfsi->sp_off);
+ COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi->fp_how, cfsi->fp_off);
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unknown arch"
--- valgrind-upstream.orig/coregrind/m_debuginfo/priv_storage.h
+++ valgrind-upstream/coregrind/m_debuginfo/priv_storage.h
@@ -208,6 +208,21 @@ typedef
Int ra_off;
}
DiCfSI;
+#elif defined(VGA_s390x)
+typedef
+ struct {
+ Addr base;
+ UInt len;
+ UChar cfa_how; /* a CFIC_ value */
+ UChar sp_how; /* a CFIR_ value */
+ UChar ra_how; /* a CFIR_ value */
+ UChar fp_how; /* a CFIR_ value */
+ Int cfa_off;
+ Int sp_off;
+ Int ra_off;
+ Int fp_off;
+ }
+ DiCfSI;
#else
# error "Unknown arch"
#endif
@@ -230,7 +245,8 @@ typedef
Creg_ARM_R13,
Creg_ARM_R12,
Creg_ARM_R15,
- Creg_ARM_R14
+ Creg_ARM_R14,
+ Creg_S390_R14
}
CfiReg;
--- valgrind-upstream.orig/coregrind/m_debuginfo/readdwarf.c
+++ valgrind-upstream/coregrind/m_debuginfo/readdwarf.c
@@ -1832,6 +1832,10 @@ void ML_(read_debuginfo_dwarf1) (
# define FP_REG 6
# define SP_REG 7
# define RA_REG_DEFAULT 16
+#elif defined(VGP_s390x_linux)
+# define FP_REG 11 // sometimes s390 has a frame pointer in r11
+# define SP_REG 15 // stack is always r15
+# define RA_REG_DEFAULT 14 // the return address is in r14
#else
# error "Unknown platform"
#endif
@@ -2139,7 +2143,7 @@ static Bool summarise_context( /*OUT*/Di
else
if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
si->cfa_off = ctxs->cfa_off;
-# if defined(VGA_x86) || defined(VGA_amd64)
+# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x)
si->cfa_how = CFIC_IA_SPREL;
# elif defined(VGA_arm)
si->cfa_how = CFIC_ARM_R13REL;
@@ -2150,7 +2154,7 @@ static Bool summarise_context( /*OUT*/Di
else
if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
si->cfa_off = ctxs->cfa_off;
-# if defined(VGA_x86) || defined(VGA_amd64)
+# if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x)
si->cfa_how = CFIC_IA_BPREL;
# elif defined(VGA_arm)
si->cfa_how = CFIC_ARM_R12REL;
@@ -2303,6 +2307,55 @@ static Bool summarise_context( /*OUT*/Di
return True;
+# elif defined(VGA_s390x)
+
+ SUMMARISE_HOW(si->ra_how, si->ra_off,
+ ctxs->reg[ctx->ra_reg] );
+ SUMMARISE_HOW(si->fp_how, si->fp_off,
+ ctxs->reg[FP_REG] );
+ SUMMARISE_HOW(si->sp_how, si->sp_off,
+ ctxs->reg[SP_REG] );
+
+ /* change some defaults to consumable values */
+ if (si->sp_how == CFIR_UNKNOWN)
+ si->sp_how = CFIR_SAME;
+
+ if (si->fp_how == CFIR_UNKNOWN)
+ si->fp_how = CFIR_SAME;
+
+ if (si->cfa_how == CFIR_UNKNOWN) {
+ si->cfa_how = CFIC_IA_SPREL;
+ si->cfa_off = 160;
+ }
+ if (si->ra_how == CFIR_UNKNOWN) {
+ if (!debuginfo->cfsi_exprs)
+ debuginfo->cfsi_exprs = VG_(newXA)( ML_(dinfo_zalloc),
+ "di.ccCt.2a",
+ ML_(dinfo_free),
+ sizeof(CfiExpr) );
+ si->ra_how = CFIR_EXPR;
+ si->ra_off = ML_(CfiExpr_CfiReg)( debuginfo->cfsi_exprs,
+ Creg_S390_R14);
+ }
+
+ /* knock out some obviously stupid cases */
+ if (si->ra_how == CFIR_SAME)
+ { why = 3; goto failed; }
+
+ /* bogus looking range? Note, we require that the difference is
+ representable in 32 bits. */
+ if (loc_start >= ctx->loc)
+ { why = 4; goto failed; }
+ if (ctx->loc - loc_start > 10000000 /* let's say */)
+ { why = 5; goto failed; }
+
+ si->base = loc_start + ctx->initloc;
+ si->len = (UInt)(ctx->loc - loc_start);
+
+ return True;
+
+
+
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unknown arch"
@@ -2376,6 +2429,13 @@ static Int copy_convert_CfiExpr_tree ( X
return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R12 );
if (dwreg == srcuc->ra_reg)
return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM_R15 ); /* correct? */
+# elif defined(VGA_s390x)
+ if (dwreg == SP_REG)
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_SP );
+ if (dwreg == FP_REG)
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_BP );
+ if (dwreg == srcuc->ra_reg)
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP ); /* correct? */
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
# else
# error "Unknown arch"
--- valgrind-upstream.orig/coregrind/m_debuginfo/readelf.c
+++ valgrind-upstream/coregrind/m_debuginfo/readelf.c
@@ -1739,7 +1739,7 @@ Bool ML_(read_elf_debug_info) ( struct _
/* PLT is different on different platforms, it seems. */
# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
- || defined(VGP_arm_linux)
+ || defined(VGP_arm_linux) || defined (VGP_s390x_linux)
/* Accept .plt where mapped as rx (code) */
if (0 == VG_(strcmp)(name, ".plt")) {
if (inrx && size > 0 && !di->plt_present) {
@@ -2187,8 +2187,9 @@ Bool ML_(read_elf_debug_info) ( struct _
/* Read the stabs and/or dwarf2 debug information, if any. It
appears reading stabs stuff on amd64-linux doesn't work, so
- we ignore it. */
-# if !defined(VGP_amd64_linux)
+ we ignore it. On s390x stabs also doesnt work and we always
+ have the dwarf info in the eh_frame. */
+# if !defined(VGP_amd64_linux) && !defined(VGP_s390x_linux)
if (stab_img && stabstr_img) {
ML_(read_debuginfo_stabs) ( di, stab_img, stab_sz,
stabstr_img, stabstr_sz );
--- valgrind-upstream.orig/coregrind/m_debuginfo/storage.c
+++ valgrind-upstream/coregrind/m_debuginfo/storage.c
@@ -141,6 +141,9 @@ void ML_(ppDiCfSI) ( XArray* /* of CfiEx
case CFIC_ARM_R11REL:
VG_(printf)("let cfa=oldR11+%d", si->cfa_off);
break;
+ case CFIR_SAME:
+ VG_(printf)("let cfa=Same");
+ break;
case CFIC_ARM_R7REL:
VG_(printf)("let cfa=oldR7+%d", si->cfa_off);
break;
@@ -172,6 +175,11 @@ void ML_(ppDiCfSI) ( XArray* /* of CfiEx
VG_(printf)(" R7=");
SHOW_HOW(si->r7_how, si->r7_off);
# elif defined(VGA_ppc32) || defined(VGA_ppc64)
+# elif defined(VGA_s390x)
+ VG_(printf)(" SP=");
+ SHOW_HOW(si->sp_how, si->sp_off);
+ VG_(printf)(" FP=");
+ SHOW_HOW(si->fp_how, si->fp_off);
# else
# error "Unknown arch"
# endif
--- valgrind-upstream.orig/coregrind/m_stacktrace.c
+++ valgrind-upstream/coregrind/m_stacktrace.c
@@ -670,6 +670,85 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId
#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 ---*/
--- valgrind-upstream.orig/coregrind/pub_core_debuginfo.h
+++ valgrind-upstream/coregrind/pub_core_debuginfo.h
@@ -123,6 +123,10 @@ typedef
typedef
UChar /* should be void, but gcc complains at use points */
D3UnwindRegs;
+#elif defined(VGA_s390x)
+typedef
+ struct { Addr ia; Addr sp; Addr fp; Addr lr;}
+ D3UnwindRegs;
#else
# error "Unsupported arch"
#endif
|