|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:14
|
This patch set tries to make the s390x port of valgrind (https://bugs.kde.org/show_bug.cgi?id=243404) more consumable for review by splitting the big patch into functional parts. (patch 12 is some kind of dumping ground for the bits that I did not know to split properly, but the size is still reviewable). Feedback and comments are very welcome. Christian PS: I do not yet know how to make a VEX review for s390x since the VEX code is huge (we support more than 500 instructions) |
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:13
|
This patch implements the normal, the profiling and the noredir dispatcher. --- coregrind/m_dispatch/dispatch-s390x-linux.S | 401 ++++++++++++++++++++++++++++ 1 file changed, 401 insertions(+) --- /dev/null +++ valgrind-upstream/coregrind/m_dispatch/dispatch-s390x-linux.S @@ -0,0 +1,401 @@ + +/*--------------------------------------------------------------------*/ +/*--- The core dispatch loop, for jumping to a code address. ---*/ +/*--- dispatch-s390x-linux.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright IBM Corp. 2010 + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +/* Contributed by Florian Krohm and Christian Borntraeger */ + +#include "pub_core_basics_asm.h" +#include "pub_core_dispatch_asm.h" +#include "pub_core_transtab_asm.h" +#include "libvex_guest_offsets.h" +#include "libvex_s390x.h" + +#if defined(VGA_s390x) + +/*------------------------------------------------------------*/ +/*--- ---*/ +/*--- The dispatch loop. VG_(run_innerloop) is used to ---*/ +/*--- run all translations except no-redir ones. ---*/ +/*--- ---*/ +/*------------------------------------------------------------*/ + +/* Convenience definitions for readability */ +#undef SP +#define SP S390_REGNO_STACK_POINTER + +#undef LR +#define LR S390_REGNO_LINK_REGISTER + +/* Location of valgrind's saved FPC register */ +#define S390_LOC_SAVED_FPC_V S390_OFFSET_SAVED_FPC_V(SP) + +/* Location of saved guest state pointer */ +#define S390_LOC_SAVED_GSP S390_OFFSET_SAVED_GSP(SP) + +/*----------------------------------------------------*/ +/*--- Preamble (set everything up) ---*/ +/*----------------------------------------------------*/ + +/* signature: +UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling ); +*/ + +.text +.align 4 +.globl VG_(run_innerloop) +VG_(run_innerloop): + /* r2 holds address of guest_state */ + /* r3 holds do_profiling (a flag) */ + + /* Save gprs ABI: r6...r13 and r15 */ + stmg %r6,%r15,48(SP) + + /* New stack frame */ + aghi SP,-S390_INNERLOOP_FRAME_SIZE + + /* Save fprs: ABI: f8...f15 */ + std %f8,160+0(SP) + std %f9,160+8(SP) + std %f10,160+16(SP) + std %f11,160+24(SP) + std %f12,160+32(SP) + std %f13,160+40(SP) + std %f14,160+48(SP) + std %f15,160+56(SP) + + /* Load address of guest state into guest state register (r13) */ + lgr %r13,%r2 + + /* Store address of guest state pointer on stack. + It will be needed later because upon return from a VEX translation + r13 may contain a special value. So the old value will be used to + determine whether r13 contains a special value. */ + stg %r13,S390_LOC_SAVED_GSP + + /* Save valgrind's FPC on stack so run_innerloop_exit can restore + it later . */ + stfpc S390_LOC_SAVED_FPC_V + + /* Load the FPC the way the client code wants it. I.e. pull the + value from the guest state. + lfpc OFFSET_s390x_fpc(%r13) + + /* Get the IA from the guest state */ + lg %r2,OFFSET_s390x_IA(%r13) + + /* Get VG_(dispatch_ctr) -- a 32-bit value -- and store it in a reg */ + larl %r6,VG_(dispatch_ctr) + l S390_REGNO_DISPATCH_CTR,0(%r6) + + /* Fall into main loop (the right one) */ + + /* r3 = 1 --> do_profiling. We may trash r3 later on. That's OK, + because it's a volatile register (does not need to be preserved). */ + ltgr %r3,%r3 + je run_innerloop__dispatch_unprofiled + j run_innerloop__dispatch_profiled + +/*----------------------------------------------------*/ +/*--- NO-PROFILING (standard) dispatcher ---*/ +/*----------------------------------------------------*/ + +run_innerloop__dispatch_unprofiled: + /* This is the story: + + r2 = IA = next guest address + r12 = VG_(dispatch_ctr) + r13 = guest state pointer or (upon return from guest code) some + special value + r15 = stack pointer (as usual) + */ + + /* Has the guest state pointer been messed with? If yes, exit. */ + cg %r13,S390_LOC_SAVED_GSP /* r13 = actual guest state pointer */ + larl %r8, VG_(tt_fast) + jne gsp_changed + + /* Save the jump address in the guest state */ + stg %r2,OFFSET_s390x_IA(%r13) + + + /* Try a fast lookup in the translation cache */ + lgr %r7, %r2 /* next guest addr */ + + /* Compute offset (not index) into VT_(tt_fast): + + offset = VG_TT_FAST_HASH(addr) * sizeof(FastCacheEntry) + + with VG_TT_FAST_HASH(addr) == (addr >> 1) & VG_TT_FAST_MASK + and sizeof(FastCacheEntry) == 16 + + offset = ((addr >> 1) & VG_TT_FAST_MASK) << 4 + */ + srlg %r7,%r7,1 + lghi %r5,VG_TT_FAST_MASK + ngr %r7,%r5 + sllg %r7,%r7,4 + + /* Set the return address to the beginning of the loop here to + have some instruction between setting r7 and using it as an + address */ + larl LR,run_innerloop__dispatch_unprofiled + + /* Are we out of timeslice? If yes, defer to scheduler. */ + ahi S390_REGNO_DISPATCH_CTR,-1 + jz counter_is_zero + + + lg %r10, 0(%r8,%r7) /* .guest */ + lg %r11, 8(%r8,%r7) /* .host */ + cgr %r2, %r10 + jne fast_lookup_failed + + /* Found a match. Call .host. + r11 is an address. There we will find the instrumented client code. + That code may modify the guest state register r13. The client code + will return to the beginning of this loop start by issuing br LR. + We can simply branch to the host code */ + br %r11 + + +/*----------------------------------------------------*/ +/*--- PROFILING dispatcher (can be much slower) ---*/ +/*----------------------------------------------------*/ + +run_innerloop__dispatch_profiled: + + /* Has the guest state pointer been messed with? If yes, exit. */ + cg %r13,S390_LOC_SAVED_GSP /* r13 = actual guest state pointer */ + larl %r8, VG_(tt_fast) + jne gsp_changed + + /* Save the jump address in the guest state */ + stg %r2,OFFSET_s390x_IA(%r13) + + /* Try a fast lookup in the translation cache */ + lgr %r7,%r2 /* next guest addr */ + + /* Compute offset (not index) into VT_(tt_fast): + + offset = VG_TT_FAST_HASH(addr) * sizeof(FastCacheEntry) + + with VG_TT_FAST_HASH(addr) == (addr >> 1) & VG_TT_FAST_MASK + and sizeof(FastCacheEntry) == 16 + + offset = ((addr >> 1) & VG_TT_FAST_MASK) << 4 + */ + srlg %r7,%r7,1 + lghi %r5,VG_TT_FAST_MASK + ngr %r7,%r5 + sllg %r7,%r7,4 + + /* Set the return address to the beginning of the loop here to + have some instruction between setting r7 and using it as an + address */ + larl LR,run_innerloop__dispatch_profiled + + /* Are we out of timeslice? If yes, defer to scheduler. */ + ahi S390_REGNO_DISPATCH_CTR,-1 + jz counter_is_zero + + lg %r10, 0(%r8,%r7) /* .guest */ + lg %r11, 8(%r8,%r7) /* .host */ + cgr %r2, %r10 + jne fast_lookup_failed + + /* sizeof(FastCacheEntry) == 16, sizeof(*UInt)==8 */ + srlg %r7,%r7,1 + + /* we got a hit: VG_(tt_fastN) is guaranteed to point to count */ + larl %r8, VG_(tt_fastN) + + /* increment bb profile counter */ + lg %r9,0(%r8,%r7) + l %r10,0(%r9) + ahi %r10,1 + st %r10,0(%r9) + + /* Found a match. Call .host. + r11 is an address. There we will find the instrumented client code. + That code may modify the guest state register r13. The client code + will return to the beginning of this loop start by issuing br LR. + We can simply branch to the host code */ + br %r11 + +/*----------------------------------------------------*/ +/*--- exit points ---*/ +/*----------------------------------------------------*/ + +gsp_changed: + /* Someone messed with the gsp (in r13). Have to + defer to scheduler to resolve this. The register + holding VG_(dispatch_ctr) is not yet decremented, + so no need to increment. */ + + /* Update the IA in the guest state */ + lg %r6,S390_LOC_SAVED_GSP /* r6 = original guest state pointer */ + stg %r2,OFFSET_s390x_IA(%r6) + + /* Return the special guest state pointer value */ + lgr %r2, %r13 + j run_innerloop_exit + + +counter_is_zero: + /* IA is up to date */ + + /* Back out decrement of the dispatch counter */ + ahi S390_REGNO_DISPATCH_CTR,1 + + /* Set return value for the scheduler */ + lghi %r2,VG_TRC_INNER_COUNTERZERO + j run_innerloop_exit + + +fast_lookup_failed: + /* IA is up to date */ + + /* Back out decrement of the dispatch counter */ + ahi S390_REGNO_DISPATCH_CTR,1 + + /* Set return value for the scheduler */ + lghi %r2,VG_TRC_INNER_FASTMISS + j run_innerloop_exit + + + /* All exits from the dispatcher go through here. + When we come here r2 holds the return value. */ +run_innerloop_exit: + + /* Restore valgrind's FPC, as client code may have changed it. */ + lfpc S390_LOC_SAVED_FPC_V + + /* Write ctr to VG_(dispatch_ctr) (=32bit value) */ + larl %r6,VG_(dispatch_ctr) + st S390_REGNO_DISPATCH_CTR,0(%r6) + + /* Restore callee-saved registers... */ + + /* Floating-point regs */ + ld %f8,160+0(SP) + ld %f9,160+8(SP) + ld %f10,160+16(SP) + ld %f11,160+24(SP) + ld %f12,160+32(SP) + ld %f13,160+40(SP) + ld %f14,160+48(SP) + ld %f15,160+56(SP) + + /* Remove atack frame */ + aghi SP,S390_INNERLOOP_FRAME_SIZE + + /* General-purpose regs. This also restores the original link + register (r14) and stack pointer (r15). */ + lmg %r6,%r15,48(SP) + + /* Return */ + br LR + +/*------------------------------------------------------------*/ +/*--- ---*/ +/*--- A special dispatcher, for running no-redir ---*/ +/*--- translations. Just runs the given translation once. ---*/ +/*--- ---*/ +/*------------------------------------------------------------*/ + +/* signature: +void VG_(run_a_noredir_translation) ( UWord* argblock ); +*/ + +/* Run a no-redir translation. argblock points to 4 UWords, 2 to carry args + and 2 to carry results: + 0: input: ptr to translation + 1: input: ptr to guest state + 2: output: next guest PC + 3: output: guest state pointer afterwards (== thread return code) +*/ +.text +.align 4 +.globl VG_(run_a_noredir_translation) +VG_(run_a_noredir_translation): + stmg %r6,%r15,48(SP) + aghi SP,-S390_INNERLOOP_FRAME_SIZE + std %f8,160+0(SP) + std %f9,160+8(SP) + std %f10,160+16(SP) + std %f11,160+24(SP) + std %f12,160+32(SP) + std %f13,160+40(SP) + std %f14,160+48(SP) + std %f15,160+56(SP) + + /* Load address of guest state into guest state register (r13) */ + lg %r13,8(%r2) + + /* Get the IA */ + lg %r11,0(%r2) + + /* save r2 (argblock) as it is clobbered */ + stg %r2,160+64(SP) + + /* the call itself */ + basr LR,%r11 + + /* restore argblock */ + lg %r1,160+64(SP) + /* save the next guest PC */ + stg %r2,16(%r1) + + /* save the guest state */ + stg %r13,24(%r1) + + /* Restore Floating-point regs */ + ld %f8,160+0(SP) + ld %f9,160+8(SP) + ld %f10,160+16(SP) + ld %f11,160+24(SP) + ld %f12,160+32(SP) + ld %f13,160+40(SP) + ld %f14,160+48(SP) + ld %f15,160+56(SP) + + aghi SP,S390_INNERLOOP_FRAME_SIZE + + lmg %r6,%r15,48(SP) + br %r14 + + +/* Let the linker know we don't need an executable stack */ +.section .note.GNU-stack,"",@progbits + +#endif /* VGA_s390x */ + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ |
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:13
|
This patch is a straight forward implementation of the debugger
and corefile support.
---
coregrind/m_coredump/coredump-elf.c | 20 ++++++++++
coregrind/m_debugger.c | 70 ++++++++++++++++++++++++++++++++++++
2 files changed, 90 insertions(+)
--- valgrind-upstream.orig/coregrind/m_coredump/coredump-elf.c
+++ valgrind-upstream/coregrind/m_coredump/coredump-elf.c
@@ -233,9 +233,14 @@ static void fill_prstatus(const ThreadSt
prs->pr_pgrp = VG_(getpgrp)();
prs->pr_sid = VG_(getpgrp)();
+#ifdef VGP_s390x_linux
+ /* prs->pr_reg has struct type. Need to take address. */
+ regs = (struct vki_user_regs_struct *)&(prs->pr_reg);
+#else
regs = (struct vki_user_regs_struct *)prs->pr_reg;
vg_assert(sizeof(*regs) == sizeof(prs->pr_reg));
+#endif
#if defined(VGP_x86_linux)
regs->eflags = LibVEX_GuestX86_get_eflags( &arch->vex );
@@ -343,6 +348,16 @@ static void fill_prstatus(const ThreadSt
regs->ARM_pc = arch->vex.guest_R15T;
regs->ARM_cpsr = LibVEX_GuestARM_get_cpsr( &((ThreadArchState*)arch)->vex );
+#elif defined(VGP_s390x_linux)
+# define DO(n) regs->gprs[n] = arch->vex.guest_r##n
+ DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
+ DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+# undef DO
+# define DO(n) regs->acrs[n] = arch->vex.guest_a##n
+ DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
+ DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+# undef DO
+ regs->orig_gpr2 = arch->vex.guest_r2;
#else
# error Unknown ELF platform
#endif
@@ -415,6 +430,11 @@ static void fill_fpu(const ThreadState *
#elif defined(VGP_arm_linux)
// umm ...
+#elif defined(VGP_s390x_linux)
+# define DO(n) fpu->fprs[n].ui = arch->vex.guest_f##n
+ DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
+ DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
+# undef DO
#else
# error Unknown ELF platform
#endif
--- valgrind-upstream.orig/coregrind/m_debugger.c
+++ valgrind-upstream/coregrind/m_debugger.c
@@ -242,6 +242,76 @@ static Int ptrace_setregs(Int pid, VexGu
#elif defined(VGP_amd64_darwin)
I_die_here;
+#elif defined(VGP_s390x_linux)
+ struct vki_user_regs_struct regs;
+ vki_ptrace_area pa;
+
+ /* we dont set the psw mask and start at offset 8 */
+ pa.vki_len = 8*32+8; //sizeof(regs);
+ pa.vki_process_addr = (unsigned long) ®s + 8 ;
+ pa.vki_kernel_addr = 8;
+
+ VG_(memset)(®s, 0, sizeof(regs));
+ regs.psw.addr = vex->guest_IA;
+
+ /* we dont set the mask */
+ regs.gprs[0] = vex->guest_r0;
+ regs.gprs[1] = vex->guest_r1;
+ regs.gprs[2] = vex->guest_r2;
+ regs.gprs[3] = vex->guest_r3;
+ regs.gprs[4] = vex->guest_r4;
+ regs.gprs[5] = vex->guest_r5;
+ regs.gprs[6] = vex->guest_r6;
+ regs.gprs[7] = vex->guest_r7;
+ regs.gprs[8] = vex->guest_r8;
+ regs.gprs[9] = vex->guest_r9;
+ regs.gprs[10] = vex->guest_r10;
+ regs.gprs[11] = vex->guest_r11;
+ regs.gprs[12] = vex->guest_r12;
+ regs.gprs[13] = vex->guest_r13;
+ regs.gprs[14] = vex->guest_r14;
+ regs.gprs[15] = vex->guest_r15;
+
+ regs.acrs[0] = vex->guest_a0;
+ regs.acrs[1] = vex->guest_a1;
+ regs.acrs[2] = vex->guest_a2;
+ regs.acrs[3] = vex->guest_a3;
+ regs.acrs[4] = vex->guest_a4;
+ regs.acrs[5] = vex->guest_a5;
+ regs.acrs[6] = vex->guest_a6;
+ regs.acrs[7] = vex->guest_a7;
+ regs.acrs[8] = vex->guest_a8;
+ regs.acrs[9] = vex->guest_a9;
+ regs.acrs[10] = vex->guest_a10;
+ regs.acrs[11] = vex->guest_a11;
+ regs.acrs[12] = vex->guest_a12;
+ regs.acrs[13] = vex->guest_a13;
+ regs.acrs[14] = vex->guest_a14;
+ regs.acrs[15] = vex->guest_a15;
+
+ /* only used for system call restart and friends, just use r2 */
+ regs.orig_gpr2 = vex->guest_r2;
+
+ regs.fp_regs.fprs[0].ui = vex->guest_f0;
+ regs.fp_regs.fprs[1].ui = vex->guest_f1;
+ regs.fp_regs.fprs[2].ui = vex->guest_f2;
+ regs.fp_regs.fprs[3].ui = vex->guest_f3;
+ regs.fp_regs.fprs[4].ui = vex->guest_f4;
+ regs.fp_regs.fprs[5].ui = vex->guest_f5;
+ regs.fp_regs.fprs[6].ui = vex->guest_f6;
+ regs.fp_regs.fprs[7].ui = vex->guest_f7;
+ regs.fp_regs.fprs[8].ui = vex->guest_f8;
+ regs.fp_regs.fprs[9].ui = vex->guest_f9;
+ regs.fp_regs.fprs[10].ui = vex->guest_f10;
+ regs.fp_regs.fprs[11].ui = vex->guest_f11;
+ regs.fp_regs.fprs[12].ui = vex->guest_f12;
+ regs.fp_regs.fprs[13].ui = vex->guest_f13;
+ regs.fp_regs.fprs[14].ui = vex->guest_f14;
+ regs.fp_regs.fprs[15].ui = vex->guest_f15;
+ regs.fp_regs.fpc = vex->guest_fpc;
+
+ return VG_(ptrace)(VKI_PTRACE_POKEUSR_AREA, pid, &pa, NULL);
+
#else
# error Unknown arch
#endif
|
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:15
|
This patch implements the autoconf/Makefile magic for s390x.
---
Makefile.all.am | 6 ++++++
Makefile.tool.am | 11 +++++++++++
Makefile.vex.am | 32 +++++++++++++++++++++++++++++---
cachegrind/Makefile.am | 3 ++-
callgrind/Makefile.am | 3 ++-
configure.in | 29 +++++++++++++++++++++++++++--
coregrind/Makefile.am | 12 ++++++++----
include/Makefile.am | 9 ++++++---
8 files changed, 91 insertions(+), 14 deletions(-)
--- valgrind-upstream.orig/Makefile.all.am
+++ valgrind-upstream/Makefile.all.am
@@ -178,6 +178,11 @@ AM_CFLAGS_AMD64_DARWIN = $(WERROR) -
-mmacosx-version-min=10.5 -fno-stack-protector
AM_CCASFLAGS_AMD64_DARWIN = $(AM_CPPFLAGS_AMD64_DARWIN) -arch x86_64 -g
+AM_FLAG_M3264_S390X_LINUX = @FLAG_M64@
+AM_CFLAGS_S390X_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
+AM_CCASFLAGS_S390X_LINUX = $(AM_CPPFLAGS_S390X_LINUX) -mzarch -march=z900 \
+ @FLAG_M64@ -g
+
# Flags for the primary target. These must be used to build the
# regtests and performance tests. In fact, these must be used to
# build anything which is built only once on a dual-arch build.
@@ -209,4 +214,5 @@ PRELOAD_LDFLAGS_PPC32_AIX5 = $(PRELOAD
PRELOAD_LDFLAGS_PPC64_AIX5 = $(PRELOAD_LDFLAGS_COMMON_AIX5) @FLAG_MAIX64@
PRELOAD_LDFLAGS_X86_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch i386
PRELOAD_LDFLAGS_AMD64_DARWIN = $(PRELOAD_LDFLAGS_COMMON_DARWIN) -arch x86_64
+PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
--- valgrind-upstream.orig/Makefile.tool.am
+++ valgrind-upstream/Makefile.tool.am
@@ -52,6 +52,9 @@ TOOL_LDFLAGS_PPC64_LINUX = \
TOOL_LDFLAGS_ARM_LINUX = \
$(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M32@
+TOOL_LDFLAGS_S390X_LINUX = \
+ $(TOOL_LDFLAGS_COMMON_LINUX) @FLAG_M64@
+
TOOL_LDFLAGS_PPC32_AIX5 = \
$(TOOL_LDFLAGS_COMMON_AIX5) @FLAG_MAIX32@
@@ -104,6 +107,9 @@ LIBREPLACEMALLOC_X86_DARWIN = \
LIBREPLACEMALLOC_AMD64_DARWIN = \
$(top_builddir)/coregrind/libreplacemalloc_toolpreload-amd64-darwin.a
+LIBREPLACEMALLOC_S390X_LINUX = \
+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-s390x-linux.a
+
LIBREPLACEMALLOC_LDFLAGS_X86_LINUX = \
-Wl,--whole-archive \
@@ -142,6 +148,11 @@ LIBREPLACEMALLOC_LDFLAGS_X86_DARWIN = \
LIBREPLACEMALLOC_LDFLAGS_AMD64_DARWIN = \
$(LIBREPLACEMALLOC_AMD64_DARWIN)
+LIBREPLACEMALLOC_LDFLAGS_S390X_LINUX = \
+ -Wl,--whole-archive \
+ $(LIBREPLACEMALLOC_S390X_LINUX) \
+ -Wl,--no-whole-archive
+
#----------------------------------------------------------------------------
# General stuff
#----------------------------------------------------------------------------
--- valgrind-upstream.orig/Makefile.vex.am
+++ valgrind-upstream/Makefile.vex.am
@@ -24,6 +24,7 @@ pkginclude_HEADERS = \
pub/libvex_guest_ppc32.h \
pub/libvex_guest_ppc64.h \
pub/libvex_guest_arm.h \
+ pub/libvex_guest_s390x.h \
pub/libvex_ir.h \
pub/libvex_trc_values.h
@@ -38,13 +39,23 @@ noinst_HEADERS = \
priv/guest_amd64_defs.h \
priv/guest_ppc_defs.h \
priv/guest_arm_defs.h \
+ priv/guest_s390_defs.h \
+ priv/guest_s390_cc.h \
+ priv/guest_s390_priv.h \
priv/host_generic_regs.h \
priv/host_generic_simd64.h \
priv/host_generic_simd128.h \
priv/host_x86_defs.h \
priv/host_amd64_defs.h \
priv/host_ppc_defs.h \
- priv/host_arm_defs.h
+ priv/host_arm_defs.h \
+ priv/host_s390_defs.h \
+ priv/host_s390_amode.h \
+ priv/host_s390_disasm.h \
+ priv/host_s390_emit.h \
+ priv/host_s390_hreg.h \
+ priv/host_s390_insn.h \
+ priv/host_s390_isel.h
BUILT_SOURCES = pub/libvex_guest_offsets.h
CLEANFILES = pub/libvex_guest_offsets.h
@@ -58,7 +69,8 @@ pub/libvex_guest_offsets.h: auxprogs/gen
pub/libvex_guest_amd64.h \
pub/libvex_guest_ppc32.h \
pub/libvex_guest_ppc64.h \
- pub/libvex_guest_arm.h
+ pub/libvex_guest_arm.h \
+ pub/libvex_guest_s390x.h
rm -f auxprogs/genoffsets.s
$(CC) $(LIBVEX_CFLAGS) \
$(AM_CFLAGS_@VGCONF_PLATFORM_PRI_CAPS@) \
@@ -97,6 +109,12 @@ LIBVEX_SOURCES_COMMON = \
priv/guest_ppc_toIR.c \
priv/guest_arm_helpers.c \
priv/guest_arm_toIR.c \
+ priv/guest_s390_helpers.c \
+ priv/guest_s390_spechelper.c \
+ priv/guest_s390_toIR.c \
+ priv/guest_s390_cc.c \
+ priv/guest_s390_decoder.c \
+ priv/guest_s390_irgen.c \
priv/host_generic_regs.c \
priv/host_generic_simd64.c \
priv/host_generic_simd128.c \
@@ -108,7 +126,15 @@ LIBVEX_SOURCES_COMMON = \
priv/host_ppc_defs.c \
priv/host_ppc_isel.c \
priv/host_arm_defs.c \
- priv/host_arm_isel.c
+ priv/host_arm_isel.c \
+ priv/host_s390_defs.c \
+ priv/host_s390_isel.c \
+ priv/host_s390_amode.c \
+ priv/host_s390_disasm.c \
+ priv/host_s390_emit.c \
+ priv/host_s390_hreg.c \
+ priv/host_s390_insn.c \
+ priv/host_s390_wrapper.c
LIBVEX_CFLAGS = \
-Wbad-function-cast \
--- valgrind-upstream.orig/cachegrind/Makefile.am
+++ valgrind-upstream/cachegrind/Makefile.am
@@ -44,7 +44,8 @@ CACHEGRIND_SOURCES_COMMON = \
cg-x86-amd64.c \
cg-ppc32.c \
cg-ppc64.c \
- cg-arm.c
+ cg-arm.c \
+ cg-s390x.c
cachegrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_SOURCES = \
$(CACHEGRIND_SOURCES_COMMON)
--- valgrind-upstream.orig/callgrind/Makefile.am
+++ valgrind-upstream/callgrind/Makefile.am
@@ -49,7 +49,8 @@ CALLGRIND_SOURCES_COMMON = \
../cachegrind/cg-x86-amd64.c \
../cachegrind/cg-ppc32.c \
../cachegrind/cg-ppc64.c \
- ../cachegrind/cg-arm.c
+ ../cachegrind/cg-arm.c \
+ ../cachegrind/cg-s390x.c
CALLGRIND_CFLAGS_COMMON = -I$(top_srcdir)/cachegrind
--- valgrind-upstream.orig/configure.in
+++ valgrind-upstream/configure.in
@@ -158,6 +158,11 @@ case "${host_cpu}" in
esac
;;
+ s390x)
+ AC_MSG_RESULT([ok (${host_cpu})])
+ ARCH_MAX="s390x"
+ ;;
+
armv7*)
AC_MSG_RESULT([ok (${host_cpu})])
ARCH_MAX="arm"
@@ -519,6 +524,18 @@ case "$ARCH_MAX-$VGCONF_OS" in
valt_load_address_sec_inner="0xUNSET"
AC_MSG_RESULT([ok (${host_cpu}-${host_os})])
;;
+ s390x-linux)
+ VGCONF_ARCH_PRI="s390x"
+ VGCONF_ARCH_SEC=""
+ VGCONF_PLATFORM_PRI_CAPS="S390X_LINUX"
+ VGCONF_PLATFORM_SEC_CAPS=""
+ # we want to have the generated code close to the dispatcher
+ valt_load_address_pri_norml="0x401000000"
+ valt_load_address_pri_inner="0x410000000"
+ valt_load_address_sec_norml="0xUNSET"
+ valt_load_address_sec_inner="0xUNSET"
+ AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})])
+ ;;
*)
VGCONF_ARCH_PRI="unknown"
VGCONF_ARCH_SEC="unknown"
@@ -555,6 +572,8 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_PPC6
-o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_AIX5 )
AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_ARM,
test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX )
+AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_S390X,
+ test x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX )
# Set up VGCONF_PLATFORMS_INCLUDE_<platform>. Either one or two of these
# become defined.
@@ -570,6 +589,9 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_
test x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX)
AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_ARM_LINUX,
test x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX)
+AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_S390X_LINUX,
+ test x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
+ -o x$VGCONF_PLATFORM_SEC_CAPS = xS390X_LINUX)
AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_PPC32_AIX5,
test x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_AIX5 \
@@ -592,7 +614,8 @@ AM_CONDITIONAL(VGCONF_OS_IS_LINUX,
-o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \
-o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX \
-o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX )
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM_LINUX \
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX)
AM_CONDITIONAL(VGCONF_OS_IS_AIX5,
test x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_AIX5 \
-o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_AIX5)
@@ -1585,7 +1608,8 @@ if test x$VGCONF_PLATFORM_PRI_CAPS = xX8
-o x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_LINUX ; then
mflag_primary=$FLAG_M32
elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX ; then
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX ; then
mflag_primary=$FLAG_M64
elif test x$VGCONF_PLATFORM_PRI_CAPS = xPPC32_AIX5 ; then
mflag_primary=-q32
@@ -1832,6 +1856,7 @@ AC_CONFIG_FILES([
none/tests/ppc64/Makefile
none/tests/x86/Makefile
none/tests/arm/Makefile
+ none/tests/s390x/Makefile
none/tests/linux/Makefile
none/tests/darwin/Makefile
none/tests/x86-linux/Makefile
--- valgrind-upstream.orig/coregrind/Makefile.am
+++ valgrind-upstream/coregrind/Makefile.am
@@ -289,7 +289,8 @@ COREGRIND_SOURCES_COMMON = \
m_dispatch/dispatch-amd64-linux.S \
m_dispatch/dispatch-ppc32-linux.S \
m_dispatch/dispatch-ppc64-linux.S \
- m_dispatch/dispatch-arm-linux.S \
+ m_dispatch/dispatch-arm-linux.S \
+ m_dispatch/dispatch-s390x-linux.S \
m_dispatch/dispatch-ppc32-aix5.S \
m_dispatch/dispatch-ppc64-aix5.S \
m_dispatch/dispatch-x86-darwin.S \
@@ -309,7 +310,8 @@ COREGRIND_SOURCES_COMMON = \
m_sigframe/sigframe-amd64-linux.c \
m_sigframe/sigframe-ppc32-linux.c \
m_sigframe/sigframe-ppc64-linux.c \
- m_sigframe/sigframe-arm-linux.c \
+ m_sigframe/sigframe-arm-linux.c \
+ m_sigframe/sigframe-s390x-linux.c \
m_sigframe/sigframe-ppc32-aix5.c \
m_sigframe/sigframe-ppc64-aix5.c \
m_sigframe/sigframe-x86-darwin.c \
@@ -318,7 +320,8 @@ COREGRIND_SOURCES_COMMON = \
m_syswrap/syscall-amd64-linux.S \
m_syswrap/syscall-ppc32-linux.S \
m_syswrap/syscall-ppc64-linux.S \
- m_syswrap/syscall-arm-linux.S \
+ m_syswrap/syscall-arm-linux.S \
+ m_syswrap/syscall-s390x-linux.S \
m_syswrap/syscall-ppc32-aix5.S \
m_syswrap/syscall-ppc64-aix5.S \
m_syswrap/syscall-x86-darwin.S \
@@ -333,7 +336,8 @@ COREGRIND_SOURCES_COMMON = \
m_syswrap/syswrap-amd64-linux.c \
m_syswrap/syswrap-ppc32-linux.c \
m_syswrap/syswrap-ppc64-linux.c \
- m_syswrap/syswrap-arm-linux.c \
+ m_syswrap/syswrap-arm-linux.c \
+ m_syswrap/syswrap-s390x-linux.c \
m_syswrap/syswrap-ppc32-aix5.c \
m_syswrap/syswrap-ppc64-aix5.c \
m_syswrap/syswrap-x86-darwin.c \
--- valgrind-upstream.orig/include/Makefile.am
+++ valgrind-upstream/include/Makefile.am
@@ -43,17 +43,20 @@ nobase_pkginclude_HEADERS = \
vki/vki-posixtypes-ppc32-linux.h \
vki/vki-posixtypes-ppc64-linux.h \
vki/vki-posixtypes-x86-linux.h \
- vki/vki-posixtypes-arm-linux.h \
+ vki/vki-posixtypes-arm-linux.h \
+ vki/vki-posixtypes-s390x-linux.h \
vki/vki-amd64-linux.h \
vki/vki-ppc32-linux.h \
vki/vki-ppc64-linux.h \
vki/vki-x86-linux.h \
- vki/vki-arm-linux.h \
+ vki/vki-arm-linux.h \
+ vki/vki-s390x-linux.h \
vki/vki-scnums-amd64-linux.h \
vki/vki-scnums-ppc32-linux.h \
vki/vki-scnums-ppc64-linux.h \
vki/vki-scnums-x86-linux.h \
- vki/vki-scnums-arm-linux.h \
+ vki/vki-scnums-arm-linux.h \
+ vki/vki-scnums-s390x-linux.h \
vki/vki-scnums-darwin.h
noinst_HEADERS = \
|
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:14
|
This patch implements the vki bits for s390x.
---
include/pub_tool_vkiscnums_asm.h | 3
include/vki/vki-linux.h | 4
include/vki/vki-posixtypes-s390x-linux.h | 77 ++
include/vki/vki-s390x-linux.h | 941 +++++++++++++++++++++++++++++++
include/vki/vki-scnums-s390x-linux.h | 447 ++++++++++++++
5 files changed, 1472 insertions(+)
--- valgrind-upstream.orig/include/pub_tool_vkiscnums_asm.h
+++ valgrind-upstream/include/pub_tool_vkiscnums_asm.h
@@ -45,6 +45,9 @@
#elif defined(VGP_ppc64_linux)
# include "vki/vki-scnums-ppc64-linux.h"
+#elif defined(VGP_s390x_linux)
+# include "vki/vki-scnums-s390x-linux.h"
+
#elif defined(VGP_arm_linux)
# include "vki/vki-scnums-arm-linux.h"
--- valgrind-upstream.orig/include/vki/vki-linux.h
+++ valgrind-upstream/include/vki/vki-linux.h
@@ -89,6 +89,8 @@
# include "vki-posixtypes-ppc64-linux.h"
#elif defined(VGA_arm)
# include "vki-posixtypes-arm-linux.h"
+#elif defined(VGA_s390x)
+# include "vki-posixtypes-s390x-linux.h"
#else
# error Unknown platform
#endif
@@ -201,6 +203,8 @@ typedef unsigned int vki_uint;
# include "vki-ppc64-linux.h"
#elif defined(VGA_arm)
# include "vki-arm-linux.h"
+#elif defined(VGA_s390x)
+# include "vki-s390x-linux.h"
#else
# error Unknown platform
#endif
--- /dev/null
+++ valgrind-upstream/include/vki/vki-posixtypes-s390x-linux.h
@@ -0,0 +1,77 @@
+
+/*--------------------------------------------------------------------*/
+/*--- s390x/Linux-specific kernel interface: posix types. ---*/
+/*--- vki-posixtypes-s390x-linux.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright IBM Corp. 2010
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Florian Krohm and Volker Sameske */
+
+#ifndef __VKI_POSIXTYPES_S390X_LINUX_H
+#define __VKI_POSIXTYPES_S390X_LINUX_H
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/posix_types.h
+//----------------------------------------------------------------------
+
+typedef long __vki_kernel_off_t;
+typedef int __vki_kernel_pid_t;
+typedef unsigned long __vki_kernel_size_t;
+typedef long __vki_kernel_time_t;
+typedef long __vki_kernel_suseconds_t;
+typedef long __vki_kernel_clock_t;
+typedef int __vki_kernel_timer_t;
+typedef int __vki_kernel_clockid_t;
+typedef int __vki_kernel_daddr_t;
+typedef char * __vki_kernel_caddr_t;
+typedef unsigned short __vki_kernel_uid16_t;
+typedef unsigned short __vki_kernel_gid16_t;
+typedef long long __vki_kernel_loff_t;
+
+typedef unsigned int __vki_kernel_ino_t;
+typedef unsigned int __vki_kernel_mode_t;
+typedef unsigned int __vki_kernel_nlink_t;
+typedef int __vki_kernel_ipc_pid_t;
+typedef unsigned int __vki_kernel_uid_t;
+typedef unsigned int __vki_kernel_gid_t;
+typedef long __vki_kernel_ssize_t;
+typedef long __vki_kernel_ptrdiff_t;
+typedef unsigned long __vki_kernel_sigset_t; /* at least 32 bits */
+typedef __vki_kernel_uid_t __vki_kernel_old_uid_t;
+typedef __vki_kernel_gid_t __vki_kernel_old_gid_t;
+typedef __vki_kernel_uid_t __vki_kernel_uid32_t;
+typedef __vki_kernel_gid_t __vki_kernel_gid32_t;
+typedef unsigned short __vki_kernel_old_dev_t;
+
+typedef struct {
+ int val[2];
+} __vki_kernel_fsid_t;
+
+#endif // __VKI_POSIXTYPES_S390X_LINUX_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+++ valgrind-upstream/include/vki/vki-s390x-linux.h
@@ -0,0 +1,941 @@
+
+/*--------------------------------------------------------------------*/
+/*--- s390x/Linux-specific kernel interface. vki-s390x-linux.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright IBM Corp. 2010
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Florian Krohm and Volker Sameske */
+
+#ifndef __VKI_S390X_LINUX_H
+#define __VKI_S390X_LINUX_H
+
+#define __force
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/types.h
+//----------------------------------------------------------------------
+
+typedef __signed__ char __vki_s8;
+typedef unsigned char __vki_u8;
+
+typedef __signed__ short __vki_s16;
+typedef unsigned short __vki_u16;
+
+typedef __signed__ int __vki_s32;
+typedef unsigned int __vki_u32;
+
+typedef __signed__ long __vki_s64;
+typedef unsigned long __vki_u64;
+
+typedef unsigned short vki_u16;
+
+typedef unsigned int vki_u32;
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/page.h
+//----------------------------------------------------------------------
+
+/* PAGE_SHIFT determines the page size */
+#define VKI_PAGE_SHIFT 12
+#define VKI_PAGE_SIZE (1UL << VKI_PAGE_SHIFT)
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/siginfo.h
+//----------------------------------------------------------------------
+
+/* We need that to ensure that sizeof(siginfo) == 128. */
+#ifdef __s390x__
+#define __VKI_ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+#endif
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/sigcontext.h
+//----------------------------------------------------------------------
+
+#define __VKI_NUM_GPRS 16
+#define __VKI_NUM_FPRS 16
+#define __VKI_NUM_ACRS 16
+
+#ifndef VGA_s390x
+
+/* Has to be at least _NSIG_WORDS from asm/signal.h */
+#define _VKI_SIGCONTEXT_NSIG 64
+#define _VKI_SIGCONTEXT_NSIG_BPW 32
+/* Size of stack frame allocated when calling signal handler. */
+#define __VKI_SIGNAL_FRAMESIZE 96
+
+#else /* VGA_s390x */
+
+/* Has to be at least _NSIG_WORDS from asm/signal.h */
+#define _VKI_SIGCONTEXT_NSIG 64
+#define _VKI_SIGCONTEXT_NSIG_BPW 64
+/* Size of stack frame allocated when calling signal handler. */
+#define __VKI_SIGNAL_FRAMESIZE 160
+
+#endif /* VGA_s390x */
+
+
+#define _VKI_SIGCONTEXT_NSIG_WORDS (_VKI_SIGCONTEXT_NSIG / _VKI_SIGCONTEXT_NSIG_BPW)
+#define _VKI_SIGMASK_COPY_SIZE (sizeof(unsigned long)*_VKI_SIGCONTEXT_NSIG_WORDS)
+
+typedef struct
+{
+ unsigned long mask;
+ unsigned long addr;
+} __attribute__ ((aligned(8))) _vki_psw_t;
+
+typedef struct
+{
+ _vki_psw_t psw;
+ unsigned long gprs[__VKI_NUM_GPRS];
+ unsigned int acrs[__VKI_NUM_ACRS];
+} _vki_s390_regs_common;
+
+typedef struct
+{
+ unsigned int fpc;
+ double fprs[__VKI_NUM_FPRS];
+} _vki_s390_fp_regs;
+
+typedef struct
+{
+ _vki_s390_regs_common regs;
+ _vki_s390_fp_regs fpregs;
+} _vki_sigregs;
+
+
+struct vki_sigcontext
+{
+ unsigned long oldmask[_VKI_SIGCONTEXT_NSIG_WORDS];
+ _vki_sigregs __user *sregs;
+};
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/signal.h
+//----------------------------------------------------------------------
+
+#define _VKI_NSIG _VKI_SIGCONTEXT_NSIG
+#define _VKI_NSIG_BPW _VKI_SIGCONTEXT_NSIG_BPW
+#define _VKI_NSIG_WORDS _VKI_SIGCONTEXT_NSIG_WORDS
+
+typedef unsigned long vki_old_sigset_t;
+
+typedef struct {
+ unsigned long sig[_VKI_NSIG_WORDS];
+} vki_sigset_t;
+
+#define VKI_SIGHUP 1
+#define VKI_SIGINT 2
+#define VKI_SIGQUIT 3
+#define VKI_SIGILL 4
+#define VKI_SIGTRAP 5
+#define VKI_SIGABRT 6
+#define VKI_SIGIOT 6
+#define VKI_SIGBUS 7
+#define VKI_SIGFPE 8
+#define VKI_SIGKILL 9
+#define VKI_SIGUSR1 10
+#define VKI_SIGSEGV 11
+#define VKI_SIGUSR2 12
+#define VKI_SIGPIPE 13
+#define VKI_SIGALRM 14
+#define VKI_SIGTERM 15
+#define VKI_SIGSTKFLT 16
+#define VKI_SIGCHLD 17
+#define VKI_SIGCONT 18
+#define VKI_SIGSTOP 19
+#define VKI_SIGTSTP 20
+#define VKI_SIGTTIN 21
+#define VKI_SIGTTOU 22
+#define VKI_SIGURG 23
+#define VKI_SIGXCPU 24
+#define VKI_SIGXFSZ 25
+#define VKI_SIGVTALRM 26
+#define VKI_SIGPROF 27
+#define VKI_SIGWINCH 28
+#define VKI_SIGIO 29
+#define VKI_SIGPOLL VKI_SIGIO
+/*
+#define VKI_SIGLOST 29
+*/
+#define VKI_SIGPWR 30
+#define VKI_SIGSYS 31
+#define VKI_SIGUNUSED 31
+
+/* These should not be considered constants from userland. */
+#define VKI_SIGRTMIN 32
+#define VKI_SIGRTMAX _VKI_NSIG
+
+/*
+ * SA_FLAGS values:
+ *
+ * SA_ONSTACK indicates that a registered stack_t will be used.
+ * SA_INTERRUPT is a no-op, but left due to historical reasons. Use the
+ * SA_RESTART flag to get restarting signals (which were the default long ago)
+ * SA_NOCLDSTOP flag to turn off SIGCHLD when children stop.
+ * SA_RESETHAND clears the handler when the signal is delivered.
+ * SA_NOCLDWAIT flag on SIGCHLD to inhibit zombies.
+ * SA_NODEFER prevents the current signal from being masked in the handler.
+ *
+ * SA_ONESHOT and SA_NOMASK are the historical Linux names for the Single
+ * Unix names RESETHAND and NODEFER respectively.
+ */
+#define VKI_SA_NOCLDSTOP 0x00000001
+#define VKI_SA_NOCLDWAIT 0x00000002
+#define VKI_SA_SIGINFO 0x00000004
+#define VKI_SA_ONSTACK 0x08000000
+#define VKI_SA_RESTART 0x10000000
+#define VKI_SA_NODEFER 0x40000000
+#define VKI_SA_RESETHAND 0x80000000
+
+#define VKI_SA_NOMASK VKI_SA_NODEFER
+#define VKI_SA_ONESHOT VKI_SA_RESETHAND
+#define VKI_SA_INTERRUPT 0x20000000 /* dummy -- ignored */
+
+#define VKI_SA_RESTORER 0x04000000
+
+/*
+ * sigaltstack controls
+ */
+#define VKI_SS_ONSTACK 1
+#define VKI_SS_DISABLE 2
+
+#define VKI_MINSIGSTKSZ 2048
+#define VKI_SIGSTKSZ 8192
+
+
+/* Next lines asm-generic/signal.h */
+#define VKI_SIG_BLOCK 0 /* for blocking signals */
+#define VKI_SIG_UNBLOCK 1 /* for unblocking signals */
+#define VKI_SIG_SETMASK 2 /* for setting the signal mask */
+
+typedef void __vki_signalfn_t(int);
+typedef __vki_signalfn_t __user *__vki_sighandler_t;
+
+/* default signal handling */
+#define VKI_SIG_DFL ((__force __vki_sighandler_t)0)
+/* ignore signal */
+#define VKI_SIG_IGN ((__force __vki_sighandler_t)1)
+/* error return from signal */
+#define VKI_SIG_ERR ((__force __vki_sighandler_t)-1)
+/* Back to asm-s390/signal.h */
+
+struct vki_old_sigaction {
+ // [[Nb: a 'k' prefix is added to "sa_handler" because
+ // bits/sigaction.h (which gets dragged in somehow via signal.h)
+ // #defines it as something else. Since that is done for glibc's
+ // purposes, which we don't care about here, we use our own name.]]
+ __vki_sighandler_t ksa_handler;
+ vki_old_sigset_t sa_mask;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+};
+
+struct vki_sigaction {
+ // [[See comment about extra 'k' above]]
+ __vki_sighandler_t ksa_handler;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ vki_sigset_t sa_mask; /* mask last for extensibility */
+};
+
+struct vki_k_sigaction {
+ struct vki_sigaction sa;
+};
+
+
+/* On Linux we use the same type for passing sigactions to
+ and from the kernel. Hence: */
+typedef struct vki_sigaction vki_sigaction_toK_t;
+typedef struct vki_sigaction vki_sigaction_fromK_t;
+
+
+typedef struct vki_sigaltstack {
+ void __user *ss_sp;
+ int ss_flags;
+ vki_size_t ss_size;
+} vki_stack_t;
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/mman.h
+//----------------------------------------------------------------------
+
+#define VKI_PROT_NONE 0x0 /* No page permissions */
+#define VKI_PROT_READ 0x1 /* page can be read */
+#define VKI_PROT_WRITE 0x2 /* page can be written */
+#define VKI_PROT_EXEC 0x4 /* page can be executed */
+#define VKI_PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend
+ change to start of
+ growsdown vma */
+#define VKI_PROT_GROWSUP 0x02000000 /* mprotect flag:
+ extend change to end
+ of growsup vma */
+
+#define VKI_MAP_PRIVATE 0x0002 /* */
+#define VKI_MAP_FIXED 0x0010 /* */
+#define VKI_MAP_ANONYMOUS 0x0020 /* */
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/fcntl.h
+//----------------------------------------------------------------------
+
+#define VKI_O_RDONLY 00000000
+#define VKI_O_WRONLY 00000001
+#define VKI_O_RDWR 00000002
+#define VKI_O_ACCMODE 00000003
+#define VKI_O_CREAT 00000100 /* not fcntl */
+#define VKI_O_EXCL 00000200 /* not fcntl */
+#define VKI_O_NOCTTY 00000400 /* not fcntl */
+#define VKI_O_TRUNC 00001000 /* not fcntl */
+#define VKI_O_APPEND 00002000
+
+#define VKI_AT_FDCWD -100
+
+#define VKI_F_DUPFD 0 /* dup */
+#define VKI_F_GETFD 1 /* get close_on_exec */
+#define VKI_F_SETFD 2 /* set/clear close_on_exec */
+#define VKI_F_GETFL 3 /* get file->f_flags */
+#define VKI_F_SETFL 4 /* set file->f_flags */
+#define VKI_F_GETLK 5
+#define VKI_F_SETLK 6
+#define VKI_F_SETLKW 7
+#define VKI_F_SETOWN 8 /* for sockets. */
+#define VKI_F_GETOWN 9 /* for sockets. */
+#define VKI_F_SETSIG 10 /* for sockets. */
+#define VKI_F_GETSIG 11 /* for sockets. */
+
+#define VKI_FD_CLOEXEC 1 /* actually anything with low bit set goes */
+
+#define VKI_F_LINUX_SPECIFIC_BASE 1024
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390x/resource.h
+//----------------------------------------------------------------------
+
+// which just does #include <asm-generic/resource.h>
+
+#define VKI_RLIMIT_DATA 2 /* max data size */
+#define VKI_RLIMIT_STACK 3 /* max stack size */
+#define VKI_RLIMIT_CORE 4 /* max core file size */
+#define VKI_RLIMIT_NOFILE 7 /* max number of open files */
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/socket.h
+//----------------------------------------------------------------------
+
+#define VKI_SOL_SOCKET 1
+
+#define VKI_SO_TYPE 3
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/sockios.h
+//----------------------------------------------------------------------
+
+#define VKI_SIOCSPGRP 0x8902
+#define VKI_SIOCGPGRP 0x8904
+#define VKI_SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
+/* since 2.6.22 */
+#define VKI_SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/stat.h
+//----------------------------------------------------------------------
+
+#ifndef VGA_s390x
+struct vki_stat {
+ unsigned short st_dev;
+ unsigned short __pad1;
+ unsigned long st_ino;
+ unsigned short st_mode;
+ unsigned short st_nlink;
+ unsigned short st_uid;
+ unsigned short st_gid;
+ unsigned short st_rdev;
+ unsigned short __pad2;
+ unsigned long st_size;
+ unsigned long st_blksize;
+ unsigned long st_blocks;
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+/* This matches struct stat64 in glibc2.1, hence the absolutely
+ * insane amounts of padding around dev_t's.
+ */
+struct vki_stat64 {
+ unsigned long long st_dev;
+ unsigned int __pad1;
+ unsigned long __st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ unsigned long st_uid;
+ unsigned long st_gid;
+ unsigned long long st_rdev;
+ unsigned int __pad3;
+ long long st_size;
+ unsigned long st_blksize;
+ unsigned char __pad4[4];
+ unsigned long __pad5; /* future possible st_blocks high bits */
+ unsigned long st_blocks; /* Number 512-byte blocks allocated. */
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec; /* will be high 32 bits of ctime someday */
+ unsigned long long st_ino;
+};
+
+#else
+
+struct vki_stat {
+ unsigned long st_dev;
+ unsigned long st_ino;
+ unsigned long st_nlink;
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int __pad1;
+ unsigned long st_rdev;
+ unsigned long st_size;
+ unsigned long st_atime;
+ unsigned long st_atime_nsec;
+ unsigned long st_mtime;
+ unsigned long st_mtime_nsec;
+ unsigned long st_ctime;
+ unsigned long st_ctime_nsec;
+ unsigned long st_blksize;
+ long st_blocks;
+ unsigned long __unused[3];
+};
+
+#endif /* VGA_s390x */
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/statfs.h
+//----------------------------------------------------------------------
+
+struct vki_statfs {
+ int f_type;
+ int f_bsize;
+ long f_blocks;
+ long f_bfree;
+ long f_bavail;
+ long f_files;
+ long f_ffree;
+ __vki_kernel_fsid_t f_fsid;
+ int f_namelen;
+ int f_frsize;
+ int f_spare[5];
+};
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/termios.h
+//----------------------------------------------------------------------
+
+struct vki_winsize {
+ unsigned short ws_row;
+ unsigned short ws_col;
+ unsigned short ws_xpixel;
+ unsigned short ws_ypixel;
+};
+
+#define VKI_NCC 8
+struct vki_termio {
+ unsigned short c_iflag; /* input mode flags */
+ unsigned short c_oflag; /* output mode flags */
+ unsigned short c_cflag; /* control mode flags */
+ unsigned short c_lflag; /* local mode flags */
+ unsigned char c_line; /* line discipline */
+ unsigned char c_cc[VKI_NCC]; /* control characters */
+};
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/termbits.h
+//----------------------------------------------------------------------
+
+typedef unsigned char vki_cc_t;
+typedef unsigned int vki_tcflag_t;
+
+#define VKI_NCCS 19
+struct vki_termios {
+ vki_tcflag_t c_iflag; /* input mode flags */
+ vki_tcflag_t c_oflag; /* output mode flags */
+ vki_tcflag_t c_cflag; /* control mode flags */
+ vki_tcflag_t c_lflag; /* local mode flags */
+ vki_cc_t c_line; /* line discipline */
+ vki_cc_t c_cc[VKI_NCCS]; /* control characters */
+};
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/ioctl.h
+//----------------------------------------------------------------------
+
+#define _VKI_IOC_NRBITS 8
+#define _VKI_IOC_TYPEBITS 8
+#define _VKI_IOC_SIZEBITS 14
+#define _VKI_IOC_DIRBITS 2
+
+#define _VKI_IOC_NRMASK ((1 << _VKI_IOC_NRBITS)-1)
+#define _VKI_IOC_TYPEMASK ((1 << _VKI_IOC_TYPEBITS)-1)
+#define _VKI_IOC_SIZEMASK ((1 << _VKI_IOC_SIZEBITS)-1)
+#define _VKI_IOC_DIRMASK ((1 << _VKI_IOC_DIRBITS)-1)
+
+#define _VKI_IOC_NRSHIFT 0
+#define _VKI_IOC_TYPESHIFT (_VKI_IOC_NRSHIFT+_VKI_IOC_NRBITS)
+#define _VKI_IOC_SIZESHIFT (_VKI_IOC_TYPESHIFT+_VKI_IOC_TYPEBITS)
+#define _VKI_IOC_DIRSHIFT (_VKI_IOC_SIZESHIFT+_VKI_IOC_SIZEBITS)
+
+#define _VKI_IOC_NONE 0U
+#define _VKI_IOC_WRITE 1U
+#define _VKI_IOC_READ 2U
+
+#define _VKI_IOC(dir,type,nr,size) \
+ (((dir) << _VKI_IOC_DIRSHIFT) | \
+ ((type) << _VKI_IOC_TYPESHIFT) | \
+ ((nr) << _VKI_IOC_NRSHIFT) | \
+ ((size) << _VKI_IOC_SIZESHIFT))
+
+/* used to create numbers */
+#define _VKI_IO(type,nr) _VKI_IOC(_VKI_IOC_NONE,(type),(nr),0)
+#define _VKI_IOR(type,nr,size) _VKI_IOC(_VKI_IOC_READ,(type),(nr),(_VKI_IOC_TYPECHECK(size)))
+#define _VKI_IOW(type,nr,size) _VKI_IOC(_VKI_IOC_WRITE,(type),(nr),(_VKI_IOC_TYPECHECK(size)))
+#define _VKI_IOWR(type,nr,size) _VKI_IOC(_VKI_IOC_READ|_VKI_IOC_WRITE,(type),(nr),(_VKI_IOC_TYPECHECK(size)))
+
+/* used to decode ioctl numbers.. */
+#define _VKI_IOC_DIR(nr) (((nr) >> _VKI_IOC_DIRSHIFT) & _VKI_IOC_DIRMASK)
+#define _VKI_IOC_TYPE(nr) (((nr) >> _VKI_IOC_TYPESHIFT) & _VKI_IOC_TYPEMASK)
+#define _VKI_IOC_NR(nr) (((nr) >> _VKI_IOC_NRSHIFT) & _VKI_IOC_NRMASK)
+#define _VKI_IOC_SIZE(nr) (((nr) >> _VKI_IOC_SIZESHIFT) & _VKI_IOC_SIZEMASK)
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/ioctls.h
+//----------------------------------------------------------------------
+
+/* 0x54 is just a magic number to make these relatively unique ('T') */
+
+#define VKI_TCGETS 0x5401
+#define VKI_TCSETS 0x5402
+#define VKI_TCSETSW 0x5403
+#define VKI_TCSETSF 0x5404
+#define VKI_TCGETA 0x5405
+#define VKI_TCSETA 0x5406
+#define VKI_TCSETAW 0x5407
+#define VKI_TCSETAF 0x5408
+#define VKI_TCSBRK 0x5409
+#define VKI_TCXONC 0x540A
+#define VKI_TCFLSH 0x540B
+
+#define VKI_TIOCSCTTY 0x540E
+#define VKI_TIOCGPGRP 0x540F
+#define VKI_TIOCSPGRP 0x5410
+#define VKI_TIOCOUTQ 0x5411
+
+#define VKI_TIOCGWINSZ 0x5413
+#define VKI_TIOCSWINSZ 0x5414
+#define VKI_TIOCMGET 0x5415
+#define VKI_TIOCMBIS 0x5416
+#define VKI_TIOCMBIC 0x5417
+#define VKI_TIOCMSET 0x5418
+
+#define VKI_FIONREAD 0x541B
+#define VKI_TIOCLINUX 0x541C
+
+#define VKI_FIONBIO 0x5421
+
+#define VKI_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
+
+#define VKI_TIOCGPTN _VKI_IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
+#define VKI_TIOCSPTLCK _VKI_IOW('T',0x31, int) /* Lock/unlock Pty */
+
+#define VKI_FIOASYNC 0x5452
+
+#define VKI_TIOCSERGETLSR 0x5459 /* Get line status register */
+
+#define VKI_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/poll.h
+//----------------------------------------------------------------------
+
+struct vki_pollfd {
+ int fd;
+ short events;
+ short revents;
+};
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/ptrace.h
+//----------------------------------------------------------------------
+#define VKI_NUM_GPRS 16
+#define VKI_NUM_FPRS 16
+#define VKI_NUM_CRS 16
+#define VKI_NUM_ACRS 16
+
+typedef union
+{
+ float f;
+ double d;
+ __vki_u64 ui;
+ struct
+ {
+ __vki_u32 hi;
+ __vki_u32 lo;
+ } fp;
+} vki_freg_t;
+
+typedef struct
+{
+ __vki_u32 fpc;
+ vki_freg_t fprs[VKI_NUM_FPRS];
+} vki_s390_fp_regs;
+
+typedef struct
+{
+ unsigned long mask;
+ unsigned long addr;
+} __attribute__ ((aligned(8))) vki_psw_t;
+
+typedef struct
+{
+ vki_psw_t psw;
+ unsigned long gprs[VKI_NUM_GPRS];
+ unsigned int acrs[VKI_NUM_ACRS];
+ unsigned long orig_gpr2;
+} vki_s390_regs;
+
+/*
+ * Now for the program event recording (trace) definitions.
+ */
+typedef struct
+{
+ unsigned long cr[3];
+} vki_per_cr_words;
+
+typedef struct
+{
+#ifdef VGA_s390x
+ unsigned : 32;
+#endif /* VGA_s390x */
+ unsigned em_branching : 1;
+ unsigned em_instruction_fetch : 1;
+ /*
+ * Switching on storage alteration automatically fixes
+ * the storage alteration event bit in the users std.
+ */
+ unsigned em_storage_alteration : 1;
+ unsigned em_gpr_alt_unused : 1;
+ unsigned em_store_real_address : 1;
+ unsigned : 3;
+ unsigned branch_addr_ctl : 1;
+ unsigned : 1;
+ unsigned storage_alt_space_ctl : 1;
+ unsigned : 21;
+ unsigned long starting_addr;
+ unsigned long ending_addr;
+} vki_per_cr_bits;
+
+typedef struct
+{
+ unsigned short perc_atmid;
+ unsigned long address;
+ unsigned char access_id;
+} vki_per_lowcore_words;
+
+typedef struct
+{
+ unsigned perc_branching : 1;
+ unsigned perc_instruction_fetch : 1;
+ unsigned perc_storage_alteration : 1;
+ unsigned perc_gpr_alt_unused : 1;
+ unsigned perc_store_real_address : 1;
+ unsigned : 3;
+ unsigned atmid_psw_bit_31 : 1;
+ unsigned atmid_validity_bit : 1;
+ unsigned atmid_psw_bit_32 : 1;
+ unsigned atmid_psw_bit_5 : 1;
+ unsigned atmid_psw_bit_16 : 1;
+ unsigned atmid_psw_bit_17 : 1;
+ unsigned si : 2;
+ unsigned long address;
+ unsigned : 4;
+ unsigned access_id : 4;
+} vki_per_lowcore_bits;
+
+typedef struct
+{
+ union {
+ vki_per_cr_words words;
+ vki_per_cr_bits bits;
+ } control_regs;
+ /*
+ * Use these flags instead of setting em_instruction_fetch
+ * directly they are used so that single stepping can be
+ * switched on & off while not affecting other tracing
+ */
+ unsigned single_step : 1;
+ unsigned instruction_fetch : 1;
+ unsigned : 30;
+ /*
+ * These addresses are copied into cr10 & cr11 if single
+ * stepping is switched off
+ */
+ unsigned long starting_addr;
+ unsigned long ending_addr;
+ union {
+ vki_per_lowcore_words words;
+ vki_per_lowcore_bits bits;
+ } lowcore;
+} vki_per_struct;
+
+/*
+ * The user_regs_struct defines the way the user registers are
+ * store on the stack for signal handling.
+ */
+struct vki_user_regs_struct
+{
+ vki_psw_t psw;
+ unsigned long gprs[VKI_NUM_GPRS];
+ unsigned int acrs[VKI_NUM_ACRS];
+ unsigned long orig_gpr2;
+ vki_s390_fp_regs fp_regs;
+ /*
+ * These per registers are in here so that gdb can modify them
+ * itself as there is no "official" ptrace interface for hardware
+ * watchpoints. This is the way intel does it.
+ */
+ vki_per_struct per_info;
+ unsigned long ieee_instruction_pointer;
+ /* Used to give failing instruction back to user for ieee exceptions */
+};
+
+typedef struct
+{
+ unsigned int vki_len;
+ unsigned long vki_kernel_addr;
+ unsigned long vki_process_addr;
+} vki_ptrace_area;
+
+/*
+ * S/390 specific non posix ptrace requests
+ */
+#define VKI_PTRACE_PEEKUSR_AREA 0x5000
+#define VKI_PTRACE_POKEUSR_AREA 0x5001
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/elf.h
+//----------------------------------------------------------------------
+
+typedef vki_s390_fp_regs vki_elf_fpregset_t;
+typedef vki_s390_regs vki_elf_gregset_t;
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/ucontext.h
+//----------------------------------------------------------------------
+
+struct vki_ucontext {
+ unsigned long uc_flags;
+ struct vki_ucontext *uc_link;
+ vki_stack_t uc_stack;
+ _vki_sigregs uc_mcontext;
+ vki_sigset_t uc_sigmask; /* mask last for extensibility */
+};
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/ipcbuf.h
+//----------------------------------------------------------------------
+
+struct vki_ipc64_perm
+{
+ __vki_kernel_key_t key;
+ __vki_kernel_uid32_t uid;
+ __vki_kernel_gid32_t gid;
+ __vki_kernel_uid32_t cuid;
+ __vki_kernel_gid32_t cgid;
+ __vki_kernel_mode_t mode;
+ unsigned short __pad1;
+ unsigned short seq;
+#ifndef VGA_s390x
+ unsigned short __pad2;
+#endif /* ! VGA_s390x */
+ unsigned long __unused1;
+ unsigned long __unused2;
+};
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/sembuf.h
+//----------------------------------------------------------------------
+
+struct vki_semid64_ds {
+ struct vki_ipc64_perm sem_perm; /* permissions .. see ipc.h */
+ __vki_kernel_time_t sem_otime; /* last semop time */
+#ifndef VGA_s390x
+ unsigned long __unused1;
+#endif /* ! VGA_s390x */
+ __vki_kernel_time_t sem_ctime; /* last change time */
+#ifndef VGA_s390x
+ unsigned long __unused2;
+#endif /* ! VGA_s390x */
+ unsigned long sem_nsems; /* no. of semaphores in array */
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/msgbuf.h
+//----------------------------------------------------------------------
+
+struct vki_msqid64_ds {
+ struct vki_ipc64_perm msg_perm;
+ __vki_kernel_time_t msg_stime; /* last msgsnd time */
+#ifndef VGA_s390x
+ unsigned long __unused1;
+#endif /* ! VGA_s390x */
+ __vki_kernel_time_t msg_rtime; /* last msgrcv time */
+#ifndef VGA_s390x
+ unsigned long __unused2;
+#endif /* ! VGA_s390x */
+ __vki_kernel_time_t msg_ctime; /* last change time */
+#ifndef VGA_s390x
+ unsigned long __unused3;
+#endif /* ! VGA_s390x */
+ unsigned long msg_cbytes; /* current number of bytes on queue */
+ unsigned long msg_qnum; /* number of messages in queue */
+ unsigned long msg_qbytes; /* max number of bytes on queue */
+ __vki_kernel_pid_t msg_lspid; /* pid of last msgsnd */
+ __vki_kernel_pid_t msg_lrpid; /* last receive pid */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/ipc.h
+//----------------------------------------------------------------------
+
+struct vki_ipc_kludge {
+ struct vki_msgbuf __user *msgp;
+ long msgtyp;
+};
+
+#define VKI_SEMOP 1
+#define VKI_SEMGET 2
+#define VKI_SEMCTL 3
+#define VKI_SEMTIMEDOP 4
+#define VKI_MSGSND 11
+#define VKI_MSGRCV 12
+#define VKI_MSGGET 13
+#define VKI_MSGCTL 14
+#define VKI_SHMAT 21
+#define VKI_SHMDT 22
+#define VKI_SHMGET 23
+#define VKI_SHMCTL 24
+
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/shmbuf.h
+//----------------------------------------------------------------------
+
+struct vki_shmid64_ds {
+ struct vki_ipc64_perm shm_perm; /* operation perms */
+ vki_size_t shm_segsz; /* size of segment (bytes) */
+ __vki_kernel_time_t shm_atime; /* last attach time */
+#ifndef VGA_s390x
+ unsigned long __unused1;
+#endif /* ! VGA_s390x */
+ __vki_kernel_time_t shm_dtime; /* last detach time */
+#ifndef VGA_s390x
+ unsigned long __unused2;
+#endif /* ! VGA_s390x */
+ __vki_kernel_time_t shm_ctime; /* last change time */
+#ifndef VGA_s390x
+ unsigned long __unused3;
+#endif /* ! VGA_s390x */
+ __vki_kernel_pid_t shm_cpid; /* pid of creator */
+ __vki_kernel_pid_t shm_lpid; /* pid of last operator */
+ unsigned long shm_nattch; /* no. of current attaches */
+ unsigned long __unused4;
+ unsigned long __unused5;
+};
+
+struct vki_shminfo64 {
+ unsigned long shmmax;
+ unsigned long shmmin;
+ unsigned long shmmni;
+ unsigned long shmseg;
+ unsigned long shmall;
+ unsigned long __unused1;
+ unsigned long __unused2;
+ unsigned long __unused3;
+ unsigned long __unused4;
+};
+
+
+//----------------------------------------------------------------------
+// The following are defined in the VKI namespace but are nowhere found
+// in the linux headers.
+//----------------------------------------------------------------------
+#define VKI_BIG_ENDIAN 1
+#define VKI_MAX_PAGE_SHIFT VKI_PAGE_SHIFT
+#define VKI_MAX_PAGE_SIZE VKI_PAGE_SIZE
+
+//----------------------------------------------------------------------
+// From linux-2.6.35.4/arch/s390x/include/asm/shmparam.h
+//----------------------------------------------------------------------
+
+#define VKI_SHMLBA VKI_PAGE_SIZE
+
+/* If a system call returns a value >= VKI_MAX_ERRNO then that is considered
+ an error condition. I.e. the system call failed. */
+#define VKI_MAX_ERRNO -125
+
+#endif // __VKI_S390X_LINUX_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+++ valgrind-upstream/include/vki/vki-scnums-s390x-linux.h
@@ -0,0 +1,447 @@
+
+/*--------------------------------------------------------------------*/
+/*--- System call numbers for s390x-linux. ---*/
+/*--- vki-scnums-s390x-linux.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright IBM Corp. 2010
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Florian Krohm and Christian Borntraeger. */
+
+#ifndef __VKI_SCNUMS_S390X_LINUX_H
+#define __VKI_SCNUMS_S390X_LINUX_H
+
+//----------------------------------------------------------------------
+// From linux-2.6.16.60/include/asm-s390/unistd.h
+//----------------------------------------------------------------------
+
+
+#define __NR_exit 1
+#define __NR_fork 2
+#define __NR_read 3
+#define __NR_write 4
+#define __NR_open 5
+#define __NR_close 6
+#define __NR_restart_syscall 7
+#define __NR_creat 8
+#define __NR_link 9
+#define __NR_unlink 10
+#define __NR_execve 11
+#define __NR_chdir 12
+#define __NR_time 13
+#define __NR_mknod 14
+#define __NR_chmod 15
+#define __NR_lchown 16
+#define __NR_lseek 19
+#define __NR_getpid 20
+#define __NR_mount 21
+#define __NR_umount 22
+#define __NR_setuid 23
+#define __NR_getuid 24
+#define __NR_stime 25
+#define __NR_ptrace 26
+#define __NR_alarm 27
+#define __NR_pause 29
+#define __NR_utime 30
+#define __NR_access 33
+#define __NR_nice 34
+#define __NR_sync 36
+#define __NR_kill 37
+#define __NR_rename 38
+#define __NR_mkdir 39
+#define __NR_rmdir 40
+#define __NR_dup 41
+#define __NR_pipe 42
+#define __NR_times 43
+#define __NR_brk 45
+#define __NR_setgid 46
+#define __NR_getgid 47
+#define __NR_signal 48
+#define __NR_geteuid 49
+#define __NR_getegid 50
+#define __NR_acct 51
+#define __NR_umount2 52
+#define __NR_ioctl 54
+#define __NR_fcntl 55
+#define __NR_setpgid 57
+#define __NR_umask 60
+#define __NR_chroot 61
+#define __NR_ustat 62
+#define __NR_dup2 63
+#define __NR_getppid 64
+#define __NR_getpgrp 65
+#define __NR_setsid 66
+#define __NR_sigaction 67
+#define __NR_setreuid 70
+#define __NR_setregid 71
+#define __NR_sigsuspend 72
+#define __NR_sigpending 73
+#define __NR_sethostname 74
+#define __NR_setrlimit 75
+#define __NR_getrlimit 76
+#define __NR_getrusage 77
+#define __NR_gettimeofday 78
+#define __NR_settimeofday 79
+#define __NR_getgroups 80
+#define __NR_setgroups 81
+#define __NR_symlink 83
+#define __NR_readlink 85
+#define __NR_uselib 86
+#define __NR_swapon 87
+#define __NR_reboot 88
+#define __NR_readdir 89
+#define __NR_mmap 90
+#define __NR_munmap 91
+#define __NR_truncate 92
+#define __NR_ftruncate 93
+#define __NR_fchmod 94
+#define __NR_fchown 95
+#define __NR_getpriority 96
+#define __NR_setpriority 97
+#define __NR_statfs 99
+#define __NR_fstatfs 100
+#define __NR_ioperm 101
+#define __NR_socketcall 102
+#define __NR_syslog 103
+#define __NR_setitimer 104
+#define __NR_getitimer 105
+#define __NR_stat 106
+#define __NR_lstat 107
+#define __NR_fstat 108
+#define __NR_lookup_dcookie 110
+#define __NR_vhangup 111
+#define __NR_idle 112
+#define __NR_wait4 114
+#define __NR_swapoff 115
+#define __NR_sysinfo 116
+#define __NR_ipc 117
+#define __NR_fsync 118
+#define __NR_sigreturn 119
+#define __NR_clone 120
+#define __NR_setdomainname 121
+#define __NR_uname 122
+#define __NR_adjtimex 124
+#define __NR_mprotect 125
+#define __NR_sigprocmask 126
+#define __NR_create_module 127
+#define __NR_init_module 128
+#define __NR_delete_module 129
+#define __NR_get_kernel_syms 130
+#define __NR_quotactl 131
+#define __NR_getpgid 132
+#define __NR_fchdir 133
+#define __NR_bdflush 134
+#define __NR_sysfs 135
+#define __NR_personality 136
+#define __NR_afs_syscall 137 /* Syscall for Andrew File System */
+#define __NR_setfsuid 138
+#define __NR_setfsgid 139
+#define __NR__llseek 140
+#define __NR_getdents 141
+#define __NR__newselect 142
+#define __NR_flock 143
+#define __NR_msync 144
+#define __NR_readv 145
+#define __NR_writev 146
+#define __NR_getsid 147
+#define __NR_fdatasync 148
+#define __NR__sysctl 149
+#define __NR_mlock 150
+#define __NR_munlock 151
+#define __NR_mlockall 152
+#define __NR_munlockall 153
+#define __NR_sched_setparam 154
+#define __NR_sched_getparam 155
+#define __NR_sched_setscheduler 156
+#define __NR_sched_getscheduler 157
+#define __NR_sched_yield 158
+#define __NR_sched_get_priority_max 159
+#define __NR_sched_get_priority_min 160
+#define __NR_sched_rr_get_interval 161
+#define __NR_nanosleep 162
+#define __NR_mremap 163
+#define __NR_setresuid 164
+#define __NR_getresuid 165
+#define __NR_query_module 167
+#define __NR_poll 168
+#define __NR_nfsservctl 169
+#define __NR_setresgid 170
+#define __NR_getresgid 171
+#define __NR_prctl 172
+#define __NR_rt_sigreturn 173
+#define __NR_rt_sigaction 174
+#define __NR_rt_sigprocmask 175
+#define __NR_rt_sigpending 176
+#define __NR_rt_sigtimedwait 177
+#define __NR_rt_sigqueueinfo 178
+#define __NR_rt_sigsuspend 179
+#define __NR_pread64 180
+#define __NR_pwrite64 181
+#define __NR_chown 182
+#define __NR_getcwd 183
+#define __NR_capget 184
+#define __NR_capset 185
+#define __NR_sigaltstack 186
+#define __NR_sendfile 187
+#define __NR_getpmsg 188
+#define __NR_putpmsg 189
+#define __NR_vfork 190
+#define __NR_ugetrlimit 191 /* SuS compliant getrlimit */
+#define __NR_mmap2 192
+#define __NR_truncate64 193
+#define __NR_ftruncate64 194
+#define __NR_stat64 195
+#define __NR_lstat64 196
+#define __NR_fstat64 197
+#define __NR_lchown32 198
+#define __NR_getuid32 199
+#define __NR_getgid32 200
+#define __NR_geteuid32 201
+#define __NR_getegid32 202
+#define __NR_setreuid32 203
+#define __NR_setregid32 204
+#define __NR_getgroups32 205
+#define __NR_setgroups32 206
+#define __NR_fchown32 207
+#define __NR_setresuid32 208
+#define __NR_getresuid32 209
+#define __NR_setresgid32 210
+#define __NR_getresgid32 211
+#define __NR_chown32 212
+#define __NR_setuid32 213
+#define __NR_setgid32 214
+#define __NR_setfsuid32 215
+#define __NR_setfsgid32 216
+#define __NR_pivot_root 217
+#define __NR_mincore 218
+#define __NR_madvise 219
+#define __NR_getdents64 220
+#define __NR_fcntl64 221
+#define __NR_readahead 222
+#define __NR_sendfile64 223
+#define __NR_setxattr 224
+#define __NR_lsetxattr 225
+#define __NR_fsetxattr 226
+#define __NR_getxattr 227
+#define __NR_lgetxattr 228
+#define __NR_fgetxattr 229
+#define __NR_listxattr 230
+#define __NR_llistxattr 231
+#define __NR_flistxattr 232
+#define __NR_removexattr 233
+#define __NR_lremovexattr 234
+#define __NR_fremovexattr 235
+#define __NR_gettid 236
+#define __NR_tkill 237
+#define __NR_futex 238
+#define __NR_sched_setaffinity 239
+#define __NR_sched_getaffinity 240
+#define __NR_tgkill 241
+/* Number 242 is reserved for tux */
+#define __NR_io_setup 243
+#define __NR_io_destroy 244
+#define __NR_io_getevents 245
+#define __NR_io_submit 246
+#define __NR_io_cancel 247
+#define __NR_exit_group 248
+#define __NR_epoll_create 249
+#define __NR_epoll_ctl 250
+#define __NR_epoll_wait 251
+#define __NR_set_tid_address 252
+#define __NR_fadvise64 253
+#define __NR_timer_create 254
+#define __NR_timer_settime (__NR_timer_create+1)
+#define __NR_timer_gettime (__NR_timer_create+2)
+#define __NR_timer_getoverrun (__NR_timer_create+3)
+#define __NR_timer_delete (__NR_timer_create+4)
+#define __NR_clock_settime (__NR_timer_create+5)
+#define __NR_clock_gettime (__NR_timer_create+6)
+#define __NR_clock_getres (__NR_timer_create+7)
+#define __NR_clock_nanosleep (__NR_timer_create+8)
+/* Number 263 is reserved for vserver */
+#define __NR_fadvise64_64 264
+#define __NR_statfs64 265
+#define __NR_fstatfs64 266
+#define __NR_remap_file_pages 267
+/* Number 268 is reserved for new sys_mbind */
+/* Number 269 is reserved for new sys_get_mempolicy */
+/* Number 270 is reserved for new sys_set_mempolicy */
+#define __NR_mq_open 271
+#define __NR_mq_unlink 272
+#define __NR_mq_timedsend 273
+#define __NR_mq_timedreceive 274
+#define __NR_mq_notify 275
+#define __NR_mq_getsetattr 276
+#define __NR_kexec_load 277
+#define __NR_add_key 278
+#define __NR_request_key 279
+#define __NR_keyctl 280
+#define __NR_waitid 281
+#define __NR_ioprio_set 282
+#define __NR_ioprio_get 283
+#define __NR_inotify_init 284
+#define __NR_inotify_add_watch 285
+#define __NR_inotify_rm_watch 286
+/* Number 287 is reserved for new sys_migrate_pages */
+#define __NR_openat 288
+#define __NR_mkdirat 289
+#define __NR_mknodat 290
+#define __NR_fchownat 291
+#define __NR_futimesat 292
+#define __NR_fstatat64 293
+#define __NR_unlinkat 294
+#define __NR_renameat 295
+#define __NR_linkat 296
+#define __NR_symlinkat 297
+#define __NR_readlinkat 298
+#define __NR_fchmodat 299
+#define __NR_faccessat 300
+#define __NR_pselect6 301
+#define __NR_ppoll 302
+#define __NR_unshare 303
+/* the following system calls from 2.6.32 unistd.h*/
+#define __NR_set_robust_list 304
+#define __NR_get_robust_list 305
+#define __NR_splice 306
+#define __NR_sync_file_range 307
+#define __NR_tee 308
+#define __NR_vmsplice 309
+/* Number 310 is reserved for new sys_move_pages */
+#define __NR_getcpu 311
+#define __NR_epoll_pwait 312
+#define __NR_utimes 313
+#define __NR_fallocate 314
+#define __NR_utimensat 315
+#define __NR_signalfd 316
+#define __NR_timerfd 317
+#define __NR_eventfd 318
+#define __NR_timerfd_create 319
+#define __NR_timerfd_settime 320
+#define __NR_timerfd_gettime 321
+#define __NR_signalfd4 322
+#define __NR_eventfd2 323
+#define __NR_inotify_init1 324
+#define __NR_pipe2 325
+#define __NR_dup3 326
+#define __NR_epoll_create1 327
+#define __NR_preadv 328
+#define __NR_pwritev 329
+#define __NR_rt_tgsigqueueinfo 330
+#define __NR_perf_event_open 331
+
+#define NR_syscalls 332
+
+/*
+ * There are some system calls that are not present on 64 bit, some
+ * have a different name although they do the same (e.g. __NR_chown32
+ * is __NR_chown on 64 bit).
+ */
+#ifdef VGA_s390x
+#undef __NR_time
+#undef __NR_lchown
+#undef __NR_setuid
+#undef __NR_getuid
+#undef __NR_stime
+#undef __NR_setgid
+#undef __NR_getgid
+#undef __NR_geteuid
+#undef __NR_getegid
+#undef __NR_setreuid
+#undef __NR_setregid
+#undef __NR_getrlimit
+#undef __NR_getgroups
+#undef __NR_setgroups
+#undef __NR_fchown
+#undef __NR_ioperm
+#undef __NR_setfsuid
+#undef __NR_setfsgid
+#undef __NR__llseek
+#undef __NR__newselect
+#undef __NR_setresuid
+#undef __NR_getresuid
+#undef __NR_setresgid
+#undef __NR_getresgid
+#undef __NR_chown
+#undef __NR_ugetrlimit
+#undef __NR_mmap2
+#undef __NR_truncate64
+#undef __NR_ftruncate64
+#undef __NR_stat64
+#undef __NR_lstat64
+#undef __NR_fstat64
+#undef __NR_lchown32
+#undef __NR_getuid32
+#undef __NR_getgid32
+#undef __NR_geteuid32
+#undef __NR_getegid32
+#undef __NR_setreuid32
+#undef __NR_setregid32
+#undef __NR_getgroups32
+#undef __NR_setgroups32
+#undef __NR_fchown32
+#undef __NR_setresuid32
+#undef __NR_getresuid32
+#undef __NR_setresgid32
+#undef __NR_getresgid32
+#undef __NR_chown32
+#undef __NR_setuid32
+#undef __NR_setgid32
+#undef __NR_setfsuid32
+#undef __NR_setfsgid32
+#undef __NR_fcntl64
+#undef __NR_sendfile64
+#undef __NR_fadvise64_64
+#undef __NR_fstatat64
+
+#define __NR_select 142
+#define __NR_getrlimit 191 /* SuS compliant getrlimit */
+#define __NR_lchown 198
+#define __NR_getuid 199
+#define __NR_getgid 200
+#define __NR_geteuid 201
+#define __NR_getegid 202
+#define __NR_setreuid 203
+#define __NR_setregid 204
+#define __NR_getgroups 205
+#define __NR_setgroups 206
+#define __NR_fchown 207
+#define __NR_setresuid 208
+#define __NR_getresuid 209
+#define __NR_setresgid 210
+#define __NR_getresgid 211
+#define __NR_chown 212
+#define __NR_setuid 213
+#define __NR_setgid 214
+#define __NR_setfsuid 215
+#define __NR_setfsgid 216
+#define __NR_newfstatat 293
+
+#endif
+
+#endif /* __VKI_SCNUMS_S390X_LINUX_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
|
|
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
|
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:16
|
This patch implements the initial image, debug logging,
trampoline, functionality and header files that was not
covered by the other patches.
---
coregrind/launcher-linux.c | 7 +
coregrind/m_debuglog.c | 48 +++++++++++++
coregrind/m_initimg/initimg-linux.c | 16 ++++
coregrind/m_libcassert.c | 16 ++++
coregrind/m_machine.c | 128 +++++++++++++++++++++++++++++++++++-
coregrind/m_main.c | 45 ++++++++++++
coregrind/m_redir.c | 3
coregrind/m_scheduler/scheduler.c | 7 +
coregrind/m_signals.c | 25 +++++++
coregrind/m_trampoline.S | 34 +++++++++
coregrind/pub_core_basics.h | 6 +
coregrind/pub_core_machine.h | 9 ++
coregrind/pub_core_threadstate.h | 2
coregrind/pub_core_trampoline.h | 5 +
coregrind/pub_core_transtab_asm.h | 7 +
include/pub_tool_machine.h | 6 +
16 files changed, 359 insertions(+), 5 deletions(-)
--- valgrind-upstream.orig/coregrind/launcher-linux.c
+++ valgrind-upstream/coregrind/launcher-linux.c
@@ -205,6 +205,10 @@ static const char *select_platform(const
(ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
platform = "ppc64-linux";
+ } else if (ehdr->e_machine == EM_S390 &&
+ (ehdr->e_ident[EI_OSABI] == ELFOSABI_SYSV ||
+ ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
+ platform = "s390x-linux";
}
}
}
@@ -278,7 +282,8 @@ int main(int argc, char** argv, char** e
(0==strcmp(VG_PLATFORM,"amd64-linux")) ||
(0==strcmp(VG_PLATFORM,"ppc32-linux")) ||
(0==strcmp(VG_PLATFORM,"ppc64-linux")) ||
- (0==strcmp(VG_PLATFORM,"arm-linux")))
+ (0==strcmp(VG_PLATFORM,"arm-linux")) ||
+ (0==strcmp(VG_PLATFORM,"s390x-linux")))
default_platform = VG_PLATFORM;
else
barf("Unknown VG_PLATFORM '%s'", VG_PLATFORM);
--- valgrind-upstream.orig/coregrind/m_debuglog.c
+++ valgrind-upstream/coregrind/m_debuglog.c
@@ -516,6 +516,54 @@ static UInt local_sys_getpid ( void )
return __res;
}
+#elif defined(VGP_s390x_linux)
+static UInt local_sys_write_stderr ( HChar* buf, Int n )
+{
+ register Int r2 asm("2") = 2; /* file descriptor STDERR */
+ register HChar* r3 asm("3") = buf;
+ register ULong r4 asm("4") = n;
+ register ULong r2_res asm("2");
+ ULong __res;
+
+ __asm__ __volatile__ (
+ " svc %b1\n"
+ : "=d" (r2_res)
+ : "i" (__NR_write),
+ "0" (r2),
+ "d" (r3),
+ "d" (r4)
+ : "cc", "memory");
+
+ __res = r2_res;
+
+ if (__res >= (ULong)(-125))
+ {
+ __res = -1;
+ }
+ return (UInt)(__res);
+}
+
+static UInt local_sys_getpid ( void )
+{
+ register ULong r2 asm("2");
+ ULong __res;
+
+ __asm__ __volatile__ (
+ " svc %b1\n"
+ : "=d" (r2)
+ : "i" (__NR_getpid)
+ : "cc", "memory");
+
+ __res = r2;
+
+ if (__res >= (ULong)(-125))
+ {
+ __res = -1;
+ }
+ return (UInt)(__res);
+}
+
+
#else
# error Unknown platform
#endif
--- valgrind-upstream.orig/coregrind/m_initimg/initimg-linux.c
+++ valgrind-upstream/coregrind/m_initimg/initimg-linux.c
@@ -1040,6 +1040,22 @@ void VG_(ii_finalise_image)( IIFinaliseI
// FIXME jrs: what's this for?
arch->vex.guest_R1 = iifii.initial_client_SP;
+# elif defined(VGP_s390x_linux)
+ vg_assert(0 == sizeof(VexGuestS390XState) % 16);
+ vg_assert(0 == sizeof(VexGuestS390XState) % VexGuestS390XStateAlignment);
+
+ /* Zero out the initial state. This also sets the guest_fpc to 0, which
+ is also done by the kernel for the fpc during execve. */
+ LibVEX_GuestS390X_initialise(&arch->vex);
+
+ /* Zero out the shadow area. */
+ VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestS390XState));
+ VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestS390XState));
+
+ /* Put essential stuff into the new state. */
+ arch->vex.guest_SP = iifii.initial_client_SP;
+ arch->vex.guest_IA = iifii.initial_client_IP;
+
# else
# error Unknown platform
# endif
--- valgrind-upstream.orig/coregrind/m_libcassert.c
+++ valgrind-upstream/coregrind/m_libcassert.c
@@ -135,6 +135,22 @@
(srP)->misc.ARM.r11 = block[4]; \
(srP)->misc.ARM.r7 = block[5]; \
}
+#elif defined(VGP_s390x_linux)
+# define GET_STARTREGS(srP) \
+ { ULong ia, sp, fp, lr; \
+ __asm__ __volatile__( \
+ "bras %0,0f;" \
+ "0: lgr %1,15;" \
+ "lgr %2,11;" \
+ "lgr %3,14;" \
+ : "=r" (ia), "=r" (sp),"=r" (fp),"=r" (lr) \
+ /* no read & clobber */ \
+ ); \
+ (srP)->r_pc = ia; \
+ (srP)->r_sp = sp; \
+ (srP)->misc.S390X.r_fp = fp; \
+ (srP)->misc.S390X.r_lr = lr; \
+ }
#else
# error Unknown platform
#endif
--- valgrind-upstream.orig/coregrind/m_machine.c
+++ valgrind-upstream/coregrind/m_machine.c
@@ -94,6 +94,13 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/U
= VG_(threads)[tid].arch.vex.guest_R11;
regs->misc.ARM.r7
= VG_(threads)[tid].arch.vex.guest_R7;
+# elif defined(VGA_s390x)
+ regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_IA;
+ regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_SP;
+ regs->misc.S390X.r_fp
+ = VG_(threads)[tid].arch.vex.guest_r11;
+ regs->misc.S390X.r_lr
+ = VG_(threads)[tid].arch.vex.guest_r14;
# else
# error "Unknown arch"
# endif
@@ -125,6 +132,9 @@ void VG_(set_syscall_return_shadows) ( T
VG_(threads)[tid].arch.vex_shadow2.guest_GPR4 = s2err;
# elif defined(VGO_darwin)
// GrP fixme darwin syscalls may return more values (2 registers plus error)
+# elif defined(VGP_s390x_linux)
+ VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
+ VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
# else
# error "Unknown plat"
# endif
@@ -257,6 +267,23 @@ static void apply_to_GPs_of_tid(VexGuest
(*f)(vex->guest_R12);
(*f)(vex->guest_R13);
(*f)(vex->guest_R14);
+#elif defined(VGA_s390x)
+ (*f)(vex->guest_r0);
+ (*f)(vex->guest_r1);
+ (*f)(vex->guest_r2);
+ (*f)(vex->guest_r3);
+ (*f)(vex->guest_r4);
+ (*f)(vex->guest_r5);
+ (*f)(vex->guest_r6);
+ (*f)(vex->guest_r7);
+ (*f)(vex->guest_r8);
+ (*f)(vex->guest_r9);
+ (*f)(vex->guest_r10);
+ (*f)(vex->guest_r11);
+ (*f)(vex->guest_r12);
+ (*f)(vex->guest_r13);
+ (*f)(vex->guest_r14);
+ (*f)(vex->guest_r15);
#else
# error Unknown arch
#endif
@@ -357,6 +384,11 @@ SizeT VG_(thread_get_altstack_size)(Thre
then safe to use VG_(machine_get_VexArchInfo)
and VG_(machine_ppc64_has_VMX)
+ -------------
+ s390x: initially: call VG_(machine_get_hwcaps)
+
+ then safe to use VG_(machine_get_VexArchInfo)
+
VG_(machine_get_hwcaps) may use signals (although it attempts to
leave signal state unchanged) and therefore should only be
called before m_main sets up the client's signal state.
@@ -383,10 +415,11 @@ ULong VG_(machine_ppc64_has_VMX) = 0;
Int VG_(machine_arm_archlevel) = 4;
#endif
+/* fixs390: anything for s390x here ? */
/* For hwcaps detection on ppc32/64 and arm we'll need to do SIGILL
testing, so we need a jmp_buf. */
-#if defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_arm)
+#if defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_arm) || defined(VGA_s390x)
#include <setjmp.h> // For jmp_buf
static jmp_buf env_unsup_insn;
static void handler_unsup_insn ( Int x ) { __builtin_longjmp(env_unsup_insn,1); }
@@ -835,6 +868,96 @@ Bool VG_(machine_get_hwcaps)( void )
return True;
}
+#elif defined(VGA_s390x)
+ {
+ /* Instruction set detection code borrowed from ppc above. */
+ vki_sigset_t saved_set, tmp_set;
+ vki_sigaction_fromK_t saved_sigill_act;
+ vki_sigaction_toK_t tmp_sigill_act;
+
+ volatile Bool have_LDISP, have_EIMM, have_GIE, have_DFP;
+ Int r;
+
+ /* Unblock SIGILL and stash away the old action for that signal */
+ VG_(sigemptyset)(&tmp_set);
+ VG_(sigaddset)(&tmp_set, VKI_SIGILL);
+
+ r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
+ vg_assert(r == 0);
+
+ r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
+ vg_assert(r == 0);
+ tmp_sigill_act = saved_sigill_act;
+
+ /* NODEFER: signal handler does not return (from the kernel's point of
+ view), hence if it is to successfully catch a signal more than once,
+ we need the NODEFER flag. */
+ tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
+ tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
+ tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
+ tmp_sigill_act.ksa_handler = handler_unsup_insn;
+ VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
+
+ /* Determine hwcaps. Note, we cannot use the stfle insn because it
+ is not supported on z900. */
+
+ have_LDISP = True;
+ if (__builtin_setjmp(env_unsup_insn)) {
+ have_LDISP = False;
+ } else {
+ /* BASR loads the address of the next insn into r1. Needed to avoid
+ a segfault in XY. */
+ __asm__ __volatile__("basr %%r1,%%r0\n\t"
+ ".long 0xe3001000\n\t" /* XY 0,0(%r1) */
+ ".short 0x0057" : : : "r0", "r1", "cc", "memory");
+ }
+
+ have_EIMM = True;
+ if (__builtin_setjmp(env_unsup_insn)) {
+ have_EIMM = False;
+ } else {
+ __asm__ __volatile__(".long 0xc0090000\n\t" /* iilf r0,0 */
+ ".short 0x0000" : : : "r0", "memory");
+ }
+
+ have_GIE = True;
+ if (__builtin_setjmp(env_unsup_insn)) {
+ have_GIE = False;
+ } else {
+ __asm__ __volatile__(".long 0xc2010000\n\t" /* msfi r0,0 */
+ ".short 0x0000" : : : "r0", "memory");
+ }
+
+ have_DFP = True;
+ if (__builtin_setjmp(env_unsup_insn)) {
+ have_DFP = False;
+ } else {
+ __asm__ __volatile__(".long 0xb3d20000"
+ : : : "r0", "cc", "memory"); /* adtr r0,r0,r0 */
+ }
+
+ /* Restore signals */
+ r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
+ vg_assert(r == 0);
+ r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
+ vg_assert(r == 0);
+ VG_(debugLog)(1, "machine", "LDISP %d EIMM %d GIE %d DFP %d\n",
+ have_LDISP, have_EIMM, have_GIE, have_DFP);
+
+ /* Check for long displacement facility which is required */
+ if (! have_LDISP) return False;
+
+ va = VexArchS390X;
+
+ vai.hwcaps = 0;
+ if (have_LDISP) vai.hwcaps |= VEX_HWCAPS_S390X_LDISP;
+ if (have_EIMM) vai.hwcaps |= VEX_HWCAPS_S390X_EIMM;
+ if (have_GIE) vai.hwcaps |= VEX_HWCAPS_S390X_GIE;
+ if (have_DFP) vai.hwcaps |= VEX_HWCAPS_S390X_DFP;
+
+ return True;
+ }
+
#elif defined(VGA_arm)
{
/* Same instruction set detection algorithm as for ppc32. */
@@ -1017,7 +1140,8 @@ void* VG_(fnptr_to_fnentry)( void* f )
{
#if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
|| defined(VGP_arm_linux) \
- || defined(VGP_ppc32_linux) || defined(VGO_darwin)
+ || defined(VGP_ppc32_linux) || defined(VGO_darwin) \
+ || defined(VGP_s390x_linux)
return f;
#elif defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
|| defined(VGP_ppc64_aix5)
--- valgrind-upstream.orig/coregrind/m_main.c
+++ valgrind-upstream/coregrind/m_main.c
@@ -1626,6 +1626,7 @@ Int valgrind_main ( Int argc, HChar **ar
"AMD Athlon or above)\n");
VG_(printf)(" * AMD Athlon64/Opteron\n");
VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
+ VG_(printf)(" * s390 (z900 and up with long displacement facility)\n");
VG_(printf)("\n");
VG_(exit)(1);
}
@@ -1937,6 +1938,8 @@ Int valgrind_main ( Int argc, HChar **ar
iters = 5;
# elif defined(VGP_arm_linux)
iters = 1;
+# elif defined(VGP_s390x_linux)
+ iters = 10;
# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
iters = 4;
# elif defined(VGO_darwin)
@@ -2079,7 +2082,6 @@ Int valgrind_main ( Int argc, HChar **ar
= VG_(am_change_ownership_v_to_c)( co_start, co_endPlus - co_start );
vg_assert(change_ownership_v_c_OK);
}
-
//--------------------------------------------------------------
// Initialise the scheduler (phase 1) [generates tid_main]
// p: none, afaics
@@ -2777,6 +2779,47 @@ asm("\n"
"\tnop\n"
"\ttrap\n"
);
+#elif defined(VGP_s390x_linux)
+/*
+ This is the canonical entry point, usually the first thing in the text
+ segment. Most registers' values are unspecified, except for:
+
+ %r14 Contains a function pointer to be registered with `atexit'.
+ This is how the dynamic linker arranges to have DT_FINI
+ functions called for shared libraries that have been loaded
+ before this code runs.
+
+ %r15 The stack contains the arguments and environment:
+ 0(%r15) argc
+ 8(%r15) argv[0]
+ ...
+ (8*argc)(%r15) NULL
+ (8*(argc+1))(%r15) envp[0]
+ ...
+ NULL
+*/
+asm("\n\t"
+ ".text\n\t"
+ ".globl _start\n\t"
+ ".type _start,@function\n\t"
+ "_start:\n\t"
+ /* set up the new stack in %r1 */
+ "larl %r1, vgPlain_interim_stack\n\t"
+ "larl %r5, 1f\n\t"
+ "ag %r1, 0(%r5)\n\t"
+ "ag %r1, 2f-1f(%r5)\n\t"
+ "nill %r1, 0xFFF0\n\t"
+ /* install it, and collect the original one */
+ "lgr %r2, %r15\n\t"
+ "lgr %r15, %r1\n\t"
+ /* call _start_in_C_linux, passing it the startup %r15 */
+ "brasl %r14, _start_in_C_linux\n\t"
+ /* trigger execution of an invalid opcode -> halt machine */
+ "j .+2\n\t"
+ "1: .quad "VG_STRINGIFY(VG_STACK_GUARD_SZB)"\n\t"
+ "2: .quad "VG_STRINGIFY(VG_STACK_ACTIVE_SZB)"\n\t"
+ ".previous\n"
+);
#elif defined(VGP_arm_linux)
asm("\n"
"\t.align 2\n"
--- valgrind-upstream.orig/coregrind/m_redir.c
+++ valgrind-upstream/coregrind/m_redir.c
@@ -1065,6 +1065,9 @@ void VG_(redir_initialise) ( void )
(Addr)&VG_(amd64_darwin_REDIR_FOR_arc4random), NULL);
}
+# elif defined(VGP_s390x_linux)
+ /* nothing so far */
+
# else
# error Unknown platform
# endif
--- valgrind-upstream.orig/coregrind/m_scheduler/scheduler.c
+++ valgrind-upstream/coregrind/m_scheduler/scheduler.c
@@ -677,6 +677,10 @@ static void do_pre_run_checks ( ThreadSt
vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow1.guest_D1));
vg_assert(VG_IS_8_ALIGNED(& tst->arch.vex_shadow2.guest_D1));
# endif
+
+# if defined(VGA_s390x)
+ vg_assert(sz_vex % VexGuestS390XStateAlignment == 0);
+# endif
}
@@ -1310,6 +1314,9 @@ void VG_(nuke_all_threads_except) ( Thre
#elif defined(VGA_arm)
# define VG_CLREQ_ARGS guest_R4
# define VG_CLREQ_RET guest_R3
+#elif defined (VGA_s390x)
+# define VG_CLREQ_ARGS guest_r2
+# define VG_CLREQ_RET guest_r3
#else
# error Unknown arch
#endif
--- valgrind-upstream.orig/coregrind/m_signals.c
+++ valgrind-upstream/coregrind/m_signals.c
@@ -523,6 +523,23 @@ typedef struct SigQueue {
I_die_here;
}
+#elif defined(VGP_s390x_linux)
+
+# define VG_UCONTEXT_INSTR_PTR(uc) ((uc)->uc_mcontext.regs.psw.addr)
+# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.regs.gprs[15])
+# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.regs.gprs[11])
+# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
+ VG_(mk_SysRes_s390x_linux)((uc)->uc_mcontext.regs.gprs[2])
+# define VG_UCONTEXT_LINK_REG(uc) ((uc)->uc_mcontext.regs.gprs[14])
+
+# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \
+ { (srP)->r_pc = (ULong)((uc)->uc_mcontext.regs.psw.addr); \
+ (srP)->r_sp = (ULong)((uc)->uc_mcontext.regs.gprs[15]); \
+ (srP)->misc.S390X.r_fp = (uc)->uc_mcontext.regs.gprs[11]; \
+ (srP)->misc.S390X.r_lr = (uc)->uc_mcontext.regs.gprs[14]; \
+ }
+
+
#else
# error Unknown platform
#endif
@@ -852,6 +869,13 @@ extern void my_sigreturn(void);
"my_sigreturn:\n" \
"ud2\n"
+#elif defined(VGP_s390x_linux)
+# define _MY_SIGRETURN(name) \
+ ".text\n" \
+ "my_sigreturn:\n" \
+ " svc " #name "\n" \
+ ".previous\n"
+
#else
# error Unknown platform
#endif
@@ -1862,6 +1886,7 @@ void VG_(synth_sigtrap)(ThreadId tid)
uc.uc_mcontext->__es.__err = 0;
# endif
+ /* fixs390: do we need to do anything here for s390 ? */
resume_scheduler(tid);
deliver_signal(tid, &info, &uc);
}
--- valgrind-upstream.orig/coregrind/m_trampoline.S
+++ valgrind-upstream/coregrind/m_trampoline.S
@@ -1214,6 +1214,39 @@ VG_(trampoline_stuff_end):
.fill 2048, 2, 0x0b0f /* `ud2` */
+/*---------------- s390x-linux ----------------*/
+#else
+#if defined(VGP_s390x_linux)
+
+ /* a leading page of unexecutable code */
+ .fill 2048, 2, 0x0000
+
+.global VG_(trampoline_stuff_start)
+VG_(trampoline_stuff_start):
+
+.global VG_(s390x_linux_SUBST_FOR_sigreturn)
+VG_(s390x_linux_SUBST_FOR_sigreturn):
+ svc __NR_sigreturn
+ .short 0
+
+.global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
+VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
+ /* old gcc unwinding code checks for a sig(_rt)_return svc and then
+ for ra = cfa to decide if it is a sig_rt_frame or not. Since we
+ set ra to this trampoline, but the cfa is still in the stack,
+ the unwinder thinks, that this is a non-rt frame and causes a
+ crash in the gcc unwinder - which is used by the thread library
+ and others. Therefore we add a lr 1,1 nop, to let the gcc
+ unwinder bail out gracefully. This might also affect unwinding
+ across the signal frame - tough luck. fixs390 */
+ lr 1,1
+ svc __NR_rt_sigreturn
+ .short 0
+
+.globl VG_(trampoline_stuff_end)
+VG_(trampoline_stuff_end):
+ .fill 2048, 2, 0x0000
+
/*---------------- unknown ----------------*/
#else
# error Unknown platform
@@ -1221,6 +1254,7 @@ VG_(trampoline_stuff_end):
#endif
#endif
#endif
+#endif
#endif
#endif
#endif
--- valgrind-upstream.orig/coregrind/pub_core_basics.h
+++ valgrind-upstream/coregrind/pub_core_basics.h
@@ -58,6 +58,8 @@
# include "libvex_guest_ppc64.h"
#elif defined(VGA_arm)
# include "libvex_guest_arm.h"
+#elif defined(VGA_s390x)
+# include "libvex_guest_s390x.h"
#else
# error Unknown arch
#endif
@@ -105,6 +107,10 @@ typedef
UInt r11;
UInt r7;
} ARM;
+ struct {
+ ULong r_fp;
+ ULong r_lr;
+ } S390X;
} misc;
}
UnwindStartRegs;
--- valgrind-upstream.orig/coregrind/pub_core_machine.h
+++ valgrind-upstream/coregrind/pub_core_machine.h
@@ -75,6 +75,11 @@
# undef VG_ELF_MACHINE
# undef VG_ELF_CLASS
# undef VG_PLAT_USES_PPCTOC
+#elif defined(VGP_s390x_linux)
+# define VG_ELF_DATA2XXX ELFDATA2MSB
+# define VG_ELF_MACHINE EM_S390
+# define VG_ELF_CLASS ELFCLASS64
+# undef VG_PLAT_USES_PPCTOC
#else
# error Unknown platform
#endif
@@ -99,6 +104,10 @@
# define VG_INSTR_PTR guest_R15T
# define VG_STACK_PTR guest_R13
# define VG_FRAME_PTR guest_R11
+#elif defined(VGA_s390x)
+# define VG_INSTR_PTR guest_IA
+# define VG_STACK_PTR guest_SP
+# define VG_FRAME_PTR guest_FP
#else
# error Unknown arch
#endif
--- valgrind-upstream.orig/coregrind/pub_core_threadstate.h
+++ valgrind-upstream/coregrind/pub_core_threadstate.h
@@ -85,6 +85,8 @@ typedef
typedef VexGuestPPC64State VexGuestArchState;
#elif defined(VGA_arm)
typedef VexGuestARMState VexGuestArchState;
+#elif defined(VGA_s390x)
+ typedef VexGuestS390XState VexGuestArchState;
#else
# error Unknown architecture
#endif
--- valgrind-upstream.orig/coregrind/pub_core_trampoline.h
+++ valgrind-upstream/coregrind/pub_core_trampoline.h
@@ -140,6 +140,11 @@ extern SizeT VG_(amd64_darwin_REDIR_FOR_
extern UInt VG_(amd64_darwin_REDIR_FOR_arc4random)( void );
#endif
+#if defined(VGP_s390x_linux)
+extern void VG_(s390x_linux_SUBST_FOR_sigreturn);
+extern void VG_(s390x_linux_SUBST_FOR_rt_sigreturn);
+#endif
+
#endif // __PUB_CORE_TRAMPOLINE_H
/*--------------------------------------------------------------------*/
--- valgrind-upstream.orig/coregrind/pub_core_transtab_asm.h
+++ valgrind-upstream/coregrind/pub_core_transtab_asm.h
@@ -43,7 +43,10 @@
2)[VG_TT_FAST_BITS-1 : 0]' on those targets.
On ARM we do like ppc32/ppc64, although that will have to be
- revisited when we come to implement Thumb. */
+ revisited when we come to implement Thumb.
+
+ On s390x the rightmost bit of an instruction address is zero.
+ For best table utilization shift the address to the right by 1 bit. */
#define VG_TT_FAST_BITS 15
#define VG_TT_FAST_SIZE (1 << VG_TT_FAST_BITS)
@@ -55,6 +58,8 @@
# define VG_TT_FAST_HASH(_addr) ((((UWord)(_addr)) ) & VG_TT_FAST_MASK)
#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_arm)
# define VG_TT_FAST_HASH(_addr) ((((UWord)(_addr)) >> 2) & VG_TT_FAST_MASK)
+#elif defined(VGA_s390x)
+# define VG_TT_FAST_HASH(_addr) ((((UWord)(_addr)) >> 1) & VG_TT_FAST_MASK)
#else
# error "VG_TT_FAST_HASH: unknown platform"
#endif
--- valgrind-upstream.orig/include/pub_tool_machine.h
+++ valgrind-upstream/include/pub_tool_machine.h
@@ -81,6 +81,12 @@
# define VG_CLREQ_SZB 20
# define VG_STACK_REDZONE_SZB 288 // is this right?
+#elif defined(VGP_s390x_linux)
+# define VG_MIN_INSTR_SZB 2
+# define VG_MAX_INSTR_SZB 6
+# define VG_CLREQ_SZB 10
+# define VG_STACK_REDZONE_SZB 0 // s390 has no redzone
+
#elif defined(VGP_x86_darwin)
# define VG_MIN_INSTR_SZB 1 // min length of native instruction
# define VG_MAX_INSTR_SZB 16 // max length of native instruction
|
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:14
|
This patch implements the wrapper in valgrind.h
---
include/valgrind.h | 552 +++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 552 insertions(+)
--- valgrind-upstream.orig/include/valgrind.h
+++ valgrind-upstream/include/valgrind.h
@@ -118,6 +118,8 @@
#undef PLAT_ppc32_linux
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
+#undef PLAT_s390x_linux
+
#if defined(_AIX) && defined(__64BIT__)
# define PLAT_ppc64_aix5 1
@@ -139,6 +141,8 @@
# define PLAT_ppc64_linux 1
#elif defined(__linux__) && defined(__arm__)
# define PLAT_arm_linux 1
+#elif defined(__linux__) && defined(__s390__) && defined(__s390x__)
+# define PLAT_s390x_linux 1
#else
/* If we're not compiling for our target platform, don't generate
any inline asms. */
@@ -695,6 +699,75 @@ typedef
#endif /* PLAT_ppc64_aix5 */
+/* ------------------------ s390x-linux ------------------------ */
+
+#if defined(PLAT_s390x_linux)
+
+typedef
+ struct {
+ unsigned long long int nraddr; /* where's the code? */
+ }
+ OrigFn;
+
+/* __SPECIAL_INSTRUCTION_PREAMBLE will be used to identify Valgrind specific
+ * code. This detection is implemented in platform specific toIR.c
+ * (e.g. VEX/priv/guest_s390_decoder.c).
+ */
+#define __SPECIAL_INSTRUCTION_PREAMBLE \
+ "lr 15,15\n\t" \
+ "lr 1,1\n\t" \
+ "lr 2,2\n\t" \
+ "lr 3,3\n\t"
+
+#define __CLIENT_REQUEST_CODE "lr 2,2\n\t"
+#define __GET_NR_CONTEXT_CODE "lr 3,3\n\t"
+#define __CALL_NO_REDIR_CODE "lr 4,4\n\t"
+
+#define VALGRIND_DO_CLIENT_REQUEST( \
+ _zzq_rlval, _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ { volatile unsigned long long int _zzq_args[6]; \
+ volatile unsigned long long int _zzq_result; \
+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ __asm__ volatile(/* r2 = args */ \
+ "lgr 2,%1\n\t" \
+ /* r3 = default */ \
+ "lgr 3,%2\n\t" \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ __CLIENT_REQUEST_CODE \
+ /* results = r3 */ \
+ "lgr %0, 3\n\t" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "2", "3", "memory" \
+ ); \
+ _zzq_rlval = _zzq_result; \
+ }
+
+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
+ { volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
+ volatile unsigned long long int __addr; \
+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
+ __GET_NR_CONTEXT_CODE \
+ "lgr %0, 3\n\t" \
+ : "=a" (__addr) \
+ : \
+ : "cc", "3", "memory" \
+ ); \
+ _zzq_orig->nraddr = __addr; \
+ }
+
+#define VALGRIND_CALL_NOREDIR_R1 \
+ __SPECIAL_INSTRUCTION_PREAMBLE \
+ __CALL_NO_REDIR_CODE
+
+#endif /* PLAT_s390x_linux */
+
/* Insert assembly code for other platforms here... */
#endif /* NVALGRIND */
@@ -4248,6 +4321,484 @@ typedef
#endif /* PLAT_ppc64_aix5 */
+/* ------------------------- s390x-linux ------------------------- */
+
+#if defined(PLAT_s390x_linux)
+
+/* Similar craziness as x86 (see above), but we use r11 as frame
+ pointer and save the old r11 in r7. r11 might be used for
+ argvec, therefore we copy argvec in r1 since r1 is clobbered
+ after the call anyway. */
+#if defined(__GNUC__) && defined(__GCC_HAVE_DWARF2_CFI_ASM)
+# define __FRAME_POINTER \
+ ,"d"(__builtin_dwarf_cfa())
+# define VALGRIND_CFI_PROLOGUE \
+ ".cfi_remember_state\n\t" \
+ "lgr 1,%1\n\t" /* copy the argvec pointer in r1 */ \
+ "lgr 7,11\n\t" \
+ "lgr 11,%2\n\t" \
+ ".cfi_def_cfa r11, 0\n\t"
+# define VALGRIND_CFI_EPILOGUE \
+ "lgr 11, 7\n\t" \
+ ".cfi_restore_state\n\t"
+#else
+# define __FRAME_POINTER
+# define VALGRIND_CFI_PROLOGUE \
+ "lgr 1,%1\n\t"
+# define VALGRIND_CFI_EPILOGUE
+#endif
+
+
+
+
+/* These regs are trashed by the hidden call. Note that we overwrite
+ r14 in s390_irgen_noredir (VEX/priv/guest_s390_irgen.c) to give the
+ function a proper return address. All others are ABI defined call
+ clobbers. */
+#define __CALLER_SAVED_REGS "0","1","2","3","4","5","14", \
+ "f0","f1","f2","f3","f4","f5","f6","f7"
+
+
+#define CALL_FN_W_v(lval, orig) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[1]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 1, 0(1)\n\t" /* target->r1 */ \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "d" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+/* The call abi has the arguments in r2-r6 and stack */
+#define CALL_FN_W_W(lval, orig, arg1) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[2]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[3]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[4]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[5]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[6]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-160\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,160\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[7]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-168\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,168\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[8]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-176\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,176\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[9]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-184\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,184\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8, arg9) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[10]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-192\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "mvc 184(8,15), 72(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,192\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8, arg9, arg10) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[11]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-200\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "mvc 184(8,15), 72(1)\n\t" \
+ "mvc 192(8,15), 80(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,200\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8, arg9, arg10, arg11) \
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[12]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-208\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "mvc 184(8,15), 72(1)\n\t" \
+ "mvc 192(8,15), 80(1)\n\t" \
+ "mvc 200(8,15), 88(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,208\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
+ arg6, arg7 ,arg8, arg9, arg10, arg11, arg12)\
+ do { \
+ volatile OrigFn _orig = (orig); \
+ volatile unsigned long _argvec[13]; \
+ volatile unsigned long _res; \
+ _argvec[0] = (unsigned long)_orig.nraddr; \
+ _argvec[1] = (unsigned long)arg1; \
+ _argvec[2] = (unsigned long)arg2; \
+ _argvec[3] = (unsigned long)arg3; \
+ _argvec[4] = (unsigned long)arg4; \
+ _argvec[5] = (unsigned long)arg5; \
+ _argvec[6] = (unsigned long)arg6; \
+ _argvec[7] = (unsigned long)arg7; \
+ _argvec[8] = (unsigned long)arg8; \
+ _argvec[9] = (unsigned long)arg9; \
+ _argvec[10] = (unsigned long)arg10; \
+ _argvec[11] = (unsigned long)arg11; \
+ _argvec[12] = (unsigned long)arg12; \
+ __asm__ volatile( \
+ VALGRIND_CFI_PROLOGUE \
+ "aghi 15,-216\n\t" \
+ "lg 2, 8(1)\n\t" \
+ "lg 3,16(1)\n\t" \
+ "lg 4,24(1)\n\t" \
+ "lg 5,32(1)\n\t" \
+ "lg 6,40(1)\n\t" \
+ "mvc 160(8,15), 48(1)\n\t" \
+ "mvc 168(8,15), 56(1)\n\t" \
+ "mvc 176(8,15), 64(1)\n\t" \
+ "mvc 184(8,15), 72(1)\n\t" \
+ "mvc 192(8,15), 80(1)\n\t" \
+ "mvc 200(8,15), 88(1)\n\t" \
+ "mvc 208(8,15), 96(1)\n\t" \
+ "lg 1, 0(1)\n\t" \
+ VALGRIND_CALL_NOREDIR_R1 \
+ "lgr %0, 2\n\t" \
+ "aghi 15,216\n\t" \
+ VALGRIND_CFI_EPILOGUE \
+ : /*out*/ "=d" (_res) \
+ : /*in*/ "a" (&_argvec[0]) __FRAME_POINTER \
+ : /*trash*/ "cc", "memory", __CALLER_SAVED_REGS,"6","7" \
+ ); \
+ lval = (__typeof__(lval)) _res; \
+ } while (0)
+
+
+#endif /* PLAT_s390x_linux */
+
/* ------------------------------------------------------------------ */
/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
@@ -4786,6 +5337,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *fo
#undef PLAT_ppc32_linux
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
+#undef PLAT_s390x_linux
#undef PLAT_ppc32_aix5
#undef PLAT_ppc64_aix5
|
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:15
|
This patch wires up memcheck, cachgrind and drd to work with s390x.
exp-ptrcheck is disabled. lackey, none, dhat, helgrind work without
any change.
---
cachegrind/cg-s390x.c | 73 +++++++++++++++++++++++++++++++++++++++++++++
cachegrind/cg_branchpred.c | 2 +
drd/drd_bitmap.h | 2 -
drd/drd_load_store.c | 2 +
exp-ptrcheck/h_main.c | 24 ++++++++++++++
exp-ptrcheck/pc_main.c | 4 ++
memcheck/mc_machine.c | 58 +++++++++++++++++++++++++++++++++++
7 files changed, 163 insertions(+), 2 deletions(-)
--- /dev/null
+++ valgrind-upstream/cachegrind/cg-s390x.c
@@ -0,0 +1,73 @@
+
+/*--------------------------------------------------------------------*/
+/*--- s390x-specific definitions. cg-s390x.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Cachegrind, a Valgrind tool for cache
+ profiling programs.
+
+ Copyright IBM Corp. 2010
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Christian Borntraeger */
+
+#if defined(VGA_s390x)
+
+#include "pub_tool_basics.h"
+#include "pub_tool_libcbase.h"
+#include "pub_tool_libcassert.h"
+#include "pub_tool_libcprint.h"
+
+#include "cg_arch.h"
+
+void VG_(configure_caches)(cache_t* I1c, cache_t* D1c, cache_t* L2c,
+ Bool all_caches_clo_defined)
+{
+ // Set caches to z10 default.
+ // See IBM Journal of Research and Development
+ // Issue Date: Jan. 2009
+ // Volume: 53 Issue:1
+ // fixs390: have a table for all available models and check /proc/cpuinfo
+ *I1c = (cache_t) { 65536, 4, 256 };
+ *D1c = (cache_t) { 131072, 8, 256 };
+ *L2c = (cache_t) { 3145728, 12, 256 };
+
+ // Warn if config not completely specified from cmd line. Note that
+ // this message is slightly different from the one we give on x86/AMD64
+ // when auto-detection fails; this lets us filter out this one (which is
+ // not important) in the regression test suite without filtering the
+ // x86/AMD64 one (which we want to see if it ever occurs in the
+ // regression test suite).
+ //
+ // If you change this message, please update
+ // cachegrind/tests/filter_stderr!
+ //
+ if (!all_caches_clo_defined) {
+ VG_(dmsg)("Warning: Cannot auto-detect cache config on s390x, using one "
+ "or more defaults \n");
+ }
+}
+
+#endif
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
--- valgrind-upstream.orig/cachegrind/cg_branchpred.c
+++ valgrind-upstream/cachegrind/cg_branchpred.c
@@ -48,6 +48,8 @@
# define N_IADDR_LO_ZERO_BITS 2
#elif defined(VGA_x86) || defined(VGA_amd64)
# define N_IADDR_LO_ZERO_BITS 0
+#elif defined(VGA_s390x)
+# define N_IADDR_LO_ZERO_BITS 1
#else
# error "Unsupported architecture"
#endif
--- valgrind-upstream.orig/drd/drd_bitmap.h
+++ valgrind-upstream/drd/drd_bitmap.h
@@ -139,7 +139,7 @@ Addr make_address(const UWord a1, const
/** Log2 of BITS_PER_UWORD. */
#if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_arm)
#define BITS_PER_BITS_PER_UWORD 5
-#elif defined(VGA_amd64) || defined(VGA_ppc64)
+#elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_s390x)
#define BITS_PER_BITS_PER_UWORD 6
#else
#error Unknown platform.
--- valgrind-upstream.orig/drd/drd_load_store.c
+++ valgrind-upstream/drd/drd_load_store.c
@@ -48,6 +48,8 @@
#define STACK_POINTER_OFFSET OFFSET_ppc64_GPR1
#elif defined(VGA_arm)
#define STACK_POINTER_OFFSET OFFSET_arm_R13
+#elif defined(VGA_s390x)
+#define STACK_POINTER_OFFSET OFFSET_s390x_r15
#else
#error Unknown architecture.
#endif
--- valgrind-upstream.orig/exp-ptrcheck/h_main.c
+++ valgrind-upstream/exp-ptrcheck/h_main.c
@@ -564,7 +564,7 @@ static void pp_curr_ExeContext(void)
# define SHMEM_SECMAP_SHIFT 2
# define SHMEM_IS_WORD_ALIGNED(_a) VG_IS_4_ALIGNED(_a)
# define SEC_MAP_WORDS (0x10000UL / 4UL) /* 16k */
-#elif defined(VGA_amd64) || defined(VGA_ppc64)
+#elif defined(VGA_amd64) || defined(VGA_ppc64) || defined(VGA_s390x)
# define SHMEM_SECMAP_MASK 0xFFF8
# define SHMEM_SECMAP_SHIFT 3
# define SHMEM_IS_WORD_ALIGNED(_a) VG_IS_8_ALIGNED(_a)
@@ -1296,6 +1296,11 @@ typedef
# define PC_SIZEOF_GUEST_STATE sizeof(VexGuestARMState)
#endif
+#if defined(VGA_s390x)
+# include "libvex_guest_s390x.h"
+# define PC_SIZEOF_GUEST_STATE sizeof(VexGuestS390XState)
+#endif
+
/* See description on definition of type IntRegInfo. */
static void get_IntRegInfo ( /*OUT*/IntRegInfo* iii, Int offset, Int szB )
@@ -1833,6 +1838,14 @@ static void get_IntRegInfo ( /*OUT*/IntR
tl_assert(0);
+ /* -------------------- s390x -------------------- */
+
+# elif defined(VGA_s390x)
+
+ Int o = offset;
+
+ VG_(tool_panic)("not implemented for s390x");
+
# else
# error "FIXME: not implemented for this architecture"
# endif
@@ -1914,6 +1927,11 @@ static Bool is_integer_guest_reg_array (
VG_(printf)("\n");
tl_assert(0);
+ /* -------------------- s390x -------------------- */
+# elif defined(VGA_s390x)
+
+ tl_assert(0);
+
/* -------------------- arm -------------------- */
# elif defined(VGA_arm)
/* There are no rotating register sections on ARM. */
@@ -2472,7 +2490,9 @@ static void setup_post_syscall_table ( v
ADD(0, __NR_symlink);
ADD(0, __NR_sysinfo);
ADD(0, __NR_tgkill);
+#if defined(__NR_time)
ADD(0, __NR_time);
+# endif
ADD(0, __NR_times);
ADD(0, __NR_truncate);
# if defined(__NR_truncate64)
@@ -2754,6 +2774,8 @@ static inline Bool looks_like_a_pointer(
tl_assert(sizeof(UWord) == 4);
return (a >= 0x00008000UL && a < 0xFF000000UL);
+# elif defined(VGA_s390x)
+ tl_assert(0);
# else
# error "Unsupported architecture"
# endif
--- valgrind-upstream.orig/exp-ptrcheck/pc_main.c
+++ valgrind-upstream/exp-ptrcheck/pc_main.c
@@ -140,6 +140,10 @@ static void pc_post_clo_init ( void )
"(like --enable-sg-checks=no).\n");
}
sg_clo_enable_sg_checks = False;
+# elif defined(VGA_s390x)
+ /* fixs390: to be done. */
+ VG_(message)(Vg_UserMsg,
+ "ERROR: exp-ptrcheck on s390x platform is not supported yet.\n");
# else
# error "Unsupported architecture"
# endif
--- valgrind-upstream.orig/memcheck/mc_machine.c
+++ valgrind-upstream/memcheck/mc_machine.c
@@ -65,6 +65,11 @@
# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestPPC64State)
#endif
+#if defined(VGA_s390x)
+# include "libvex_guest_s390x.h"
+# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestS390XState)
+#endif
+
#if defined(VGA_arm)
# include "libvex_guest_arm.h"
# define MC_SIZEOF_GUEST_STATE sizeof(VexGuestARMState)
@@ -681,6 +686,54 @@ static Int get_otrack_shadow_offset_wrk
# undef GOF
# undef SZB
+ /* -------------------- s390x -------------------- */
+
+# elif defined(VGA_s390x)
+# define GOF(_fieldname) \
+ (offsetof(VexGuestS390XState,guest_##_fieldname))
+ Int o = offset;
+ Int sz = szB;
+ tl_assert(sz > 0);
+ tl_assert(host_is_big_endian());
+
+ /* no matter what byte(s) we change, we have changed the full 8 byte value
+ and need to track this change for the whole register */
+ if (o >= GOF(r0) && sz <= 8 && o <= (GOF(r15) + 8 - sz))
+ return GOF(r0) + ((o-GOF(r0)) & -8) ;
+
+
+ /* fprs are accesses 4 or 8 byte at once. Again, we track that change for
+ the full register */
+ if ((sz == 8 || sz == 4) && o >= GOF(f0) && o <= GOF(f15)+8-sz)
+ return GOF(f0) + ((o-GOF(f0)) & -8) ;
+
+ /* access registers are accessed 4 bytes at once */
+ if (sz == 4 && o >= GOF(a0) && o <= GOF(a15))
+ return o;
+
+ /* we access the guest counter either fully or one of the 4byte words */
+ if (o == GOF(counter) && (sz == 8 || sz ==4))
+ return o;
+ if (o == GOF(counter) + 4 && sz == 4)
+ return o;
+
+ if (o == GOF(CC_OP)) return -1;
+ if (o == GOF(CC_DEP1)) return o;
+ if (o == GOF(CC_DEP2)) return o;
+ if (o == GOF(CC_NDEP)) return -1;
+ if (o == GOF(TISTART)) return -1;
+ if (o == GOF(TILEN)) return -1;
+ if (o == GOF(NRADDR)) return -1;
+ if (o == GOF(IP_AT_SYSCALL)) return -1;
+ if (o == GOF(fpc)) return -1;
+ if (o == GOF(IA)) return -1;
+ if (o == GOF(SYSNO)) return -1;
+ VG_(printf)("MC_(get_otrack_shadow_offset)(s390x)(off=%d,sz=%d)\n",
+ offset,szB);
+ tl_assert(0);
+# undef GOF
+
+
/* --------------------- arm --------------------- */
# elif defined(VGA_arm)
@@ -888,6 +941,11 @@ IRType MC_(get_otrack_reg_array_equiv_in
VG_(printf)("\n");
tl_assert(0);
+ /* --------------------- s390x --------------------- */
+# elif defined(VGA_s390x)
+ /* Should never het here because s390x does not use Ist_PutI
+ and Iex_GetI. */
+ tl_assert(0);
# else
# error "FIXME: not implemented for this architecture"
# endif
|
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:15
|
--- README.s390 | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) --- /dev/null +++ valgrind-upstream/README.s390 @@ -0,0 +1,33 @@ +Requirements +------------ +- You need GCC 3.1 or later to compile the s390 port. +- A working combination of autotools is required. The following + combination is known to work: automake 1.9.6 and autoconf 2.59 +- To run valgrind a z900 machine or any later model is needed. +- The long displacement facility must be installed on the host machine. + + +Limitations +----------- +- 31-bit client programs are not supported. +- Hexadecimal floating point is not supported. +- Decimal floating point is not supported yet. +- Currently, only memcheck, massif, lackey, and none are supported +- helgrind and drd seem to work but are not yet supported. +- exp-ptrcheck and callgrind are not supported. + + +Recommendations +--------------- +Applications should be compiled with -fno-builtin to avoid +false positives due to builtin string operations when running memcheck. + + +Reading Material +---------------- +(1) Linux for zSeries ELF ABI Supplement + http://refspecs.linuxfoundation.org/ELF/zSeries/index.html +(2) z/Architecture Principles of Operation + http://publibfi.boulder.ibm.com/epubs/pdf/dz9zr008.pdf +(3) z/Architecture Reference Summary + http://publibfi.boulder.ibm.com/epubs/pdf/dz9zs006.pdf |
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:19
|
This provides signal frames for rt and non-rt signals
---
coregrind/m_sigframe/sigframe-s390x-linux.c | 570 ++++++++++++++++++++++++++++
1 file changed, 570 insertions(+)
--- /dev/null
+++ valgrind-upstream/coregrind/m_sigframe/sigframe-s390x-linux.c
@@ -0,0 +1,570 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Create/destroy signal delivery frames. ---*/
+/*--- sigframe-s390x-linux.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright IBM Corp. 2010
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Christian Borntraeger */
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_machine.h"
+#include "pub_core_options.h"
+#include "pub_core_sigframe.h"
+#include "pub_core_signals.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_trampoline.h"
+
+#if defined(VGA_s390x)
+
+/* This module creates and removes signal frames for signal deliveries
+ on s390x-linux.
+
+ Note, this file contains kernel-specific knowledge in the form of
+ 'struct sigframe' and 'struct rt_sigframe'.
+
+ Either a 'struct sigframe' or a 'struct rtsigframe' is pushed
+ onto the client's stack. This contains a subsidiary
+ vki_ucontext. That holds the vcpu's state across the signal,
+ so that the sighandler can mess with the vcpu state if it
+ really wants.
+*/
+
+#define SET_SIGNAL_GPR(zztst, zzn, zzval) \
+ do { zztst->arch.vex.guest_r##zzn = (unsigned long)(zzval); \
+ VG_TRACK( post_reg_write, Vg_CoreSignal, zztst->tid, \
+ offsetof(VexGuestS390XState,guest_r##zzn), \
+ sizeof(UWord) ); \
+ } while (0)
+
+/*------------------------------------------------------------*/
+/*--- Signal frame layouts ---*/
+/*------------------------------------------------------------*/
+
+// A structure in which to save the application's registers
+// during the execution of signal handlers.
+
+// Linux has 2 signal frame structures: one for normal signal
+// deliveries, and one for SA_SIGINFO deliveries (also known as RT
+// signals).
+//
+// In theory, so long as we get the arguments to the handler function
+// right, it doesn't matter what the exact layout of the rest of the
+// frame is. Unfortunately, things like gcc's exception unwinding
+// make assumptions about the locations of various parts of the frame,
+// so we need to duplicate it exactly.
+
+/* Valgrind-specific parts of the signal frame */
+struct vg_sigframe
+{
+ /* Sanity check word. */
+ UInt magicPI;
+
+ UInt handlerflags; /* flags for signal handler */
+
+
+ /* Safely-saved version of sigNo, as described above. */
+ Int sigNo_private;
+
+ /* XXX This is wrong. Surely we should store the shadow values
+ into the shadow memory behind the actual values? */
+ VexGuestS390XState vex_shadow1;
+ VexGuestS390XState vex_shadow2;
+
+ /* HACK ALERT */
+ VexGuestS390XState vex;
+ /* end HACK ALERT */
+
+ /* saved signal mask to be restored when handler returns */
+ vki_sigset_t mask;
+
+ /* Sanity check word. Is the highest-addressed word; do not
+ move!*/
+ UInt magicE;
+};
+
+#define S390_SYSCALL_SIZE 2
+
+struct sigframe
+{
+ UChar callee_used_stack[__VKI_SIGNAL_FRAMESIZE];
+ struct vki_sigcontext sc;
+ _vki_sigregs sregs;
+ Int sigNo;
+ UChar retcode[S390_SYSCALL_SIZE];
+
+ struct vg_sigframe vg;
+};
+
+struct rt_sigframe
+{
+ UChar callee_used_stack[__VKI_SIGNAL_FRAMESIZE];
+ UChar retcode[S390_SYSCALL_SIZE];
+ struct vki_siginfo info;
+ struct vki_ucontext uc;
+
+ struct vg_sigframe vg;
+};
+
+/*------------------------------------------------------------*/
+/*--- Creating signal frames ---*/
+/*------------------------------------------------------------*/
+
+/* Saves all user-controlled register into a _vki_sigregs structure */
+static void save_sigregs(ThreadState *tst, _vki_sigregs *sigregs)
+{
+ sigregs->regs.gprs[0] = tst->arch.vex.guest_r0;
+ sigregs->regs.gprs[1] = tst->arch.vex.guest_r1;
+ sigregs->regs.gprs[2] = tst->arch.vex.guest_r2;
+ sigregs->regs.gprs[3] = tst->arch.vex.guest_r3;
+ sigregs->regs.gprs[4] = tst->arch.vex.guest_r4;
+ sigregs->regs.gprs[5] = tst->arch.vex.guest_r5;
+ sigregs->regs.gprs[6] = tst->arch.vex.guest_r6;
+ sigregs->regs.gprs[7] = tst->arch.vex.guest_r7;
+ sigregs->regs.gprs[8] = tst->arch.vex.guest_r8;
+ sigregs->regs.gprs[9] = tst->arch.vex.guest_r9;
+ sigregs->regs.gprs[10] = tst->arch.vex.guest_r10;
+ sigregs->regs.gprs[11] = tst->arch.vex.guest_r11;
+ sigregs->regs.gprs[12] = tst->arch.vex.guest_r12;
+ sigregs->regs.gprs[13] = tst->arch.vex.guest_r13;
+ sigregs->regs.gprs[14] = tst->arch.vex.guest_r14;
+ sigregs->regs.gprs[15] = tst->arch.vex.guest_r15;
+
+ sigregs->regs.acrs[0] = tst->arch.vex.guest_a0;
+ sigregs->regs.acrs[1] = tst->arch.vex.guest_a1;
+ sigregs->regs.acrs[2] = tst->arch.vex.guest_a2;
+ sigregs->regs.acrs[3] = tst->arch.vex.guest_a3;
+ sigregs->regs.acrs[4] = tst->arch.vex.guest_a4;
+ sigregs->regs.acrs[5] = tst->arch.vex.guest_a5;
+ sigregs->regs.acrs[6] = tst->arch.vex.guest_a6;
+ sigregs->regs.acrs[7] = tst->arch.vex.guest_a7;
+ sigregs->regs.acrs[8] = tst->arch.vex.guest_a8;
+ sigregs->regs.acrs[9] = tst->arch.vex.guest_a9;
+ sigregs->regs.acrs[10] = tst->arch.vex.guest_a10;
+ sigregs->regs.acrs[11] = tst->arch.vex.guest_a11;
+ sigregs->regs.acrs[12] = tst->arch.vex.guest_a12;
+ sigregs->regs.acrs[13] = tst->arch.vex.guest_a13;
+ sigregs->regs.acrs[14] = tst->arch.vex.guest_a14;
+ sigregs->regs.acrs[15] = tst->arch.vex.guest_a15;
+
+ sigregs->fpregs.fprs[0] = tst->arch.vex.guest_f0;
+ sigregs->fpregs.fprs[1] = tst->arch.vex.guest_f1;
+ sigregs->fpregs.fprs[2] = tst->arch.vex.guest_f2;
+ sigregs->fpregs.fprs[3] = tst->arch.vex.guest_f3;
+ sigregs->fpregs.fprs[4] = tst->arch.vex.guest_f4;
+ sigregs->fpregs.fprs[5] = tst->arch.vex.guest_f5;
+ sigregs->fpregs.fprs[6] = tst->arch.vex.guest_f6;
+ sigregs->fpregs.fprs[7] = tst->arch.vex.guest_f7;
+ sigregs->fpregs.fprs[8] = tst->arch.vex.guest_f8;
+ sigregs->fpregs.fprs[9] = tst->arch.vex.guest_f9;
+ sigregs->fpregs.fprs[10] = tst->arch.vex.guest_f10;
+ sigregs->fpregs.fprs[11] = tst->arch.vex.guest_f11;
+ sigregs->fpregs.fprs[12] = tst->arch.vex.guest_f12;
+ sigregs->fpregs.fprs[13] = tst->arch.vex.guest_f13;
+ sigregs->fpregs.fprs[14] = tst->arch.vex.guest_f14;
+ sigregs->fpregs.fprs[15] = tst->arch.vex.guest_f15;
+ sigregs->fpregs.fpc = tst->arch.vex.guest_fpc;
+
+ sigregs->regs.psw.addr = tst->arch.vex.guest_IA;
+ /* save a sane dummy mask */
+ sigregs->regs.psw.mask = 0x0705000180000000UL;
+}
+
+static void restore_sigregs(ThreadState *tst, _vki_sigregs *sigregs)
+{
+ tst->arch.vex.guest_r0 = sigregs->regs.gprs[0];
+ tst->arch.vex.guest_r1 = sigregs->regs.gprs[1];
+ tst->arch.vex.guest_r2 = sigregs->regs.gprs[2];
+ tst->arch.vex.guest_r3 = sigregs->regs.gprs[3];
+ tst->arch.vex.guest_r4 = sigregs->regs.gprs[4];
+ tst->arch.vex.guest_r5 = sigregs->regs.gprs[5];
+ tst->arch.vex.guest_r6 = sigregs->regs.gprs[6];
+ tst->arch.vex.guest_r7 = sigregs->regs.gprs[7];
+ tst->arch.vex.guest_r8 = sigregs->regs.gprs[8];
+ tst->arch.vex.guest_r9 = sigregs->regs.gprs[9];
+ tst->arch.vex.guest_r10 = sigregs->regs.gprs[10];
+ tst->arch.vex.guest_r11 = sigregs->regs.gprs[11];
+ tst->arch.vex.guest_r12 = sigregs->regs.gprs[12];
+ tst->arch.vex.guest_r13 = sigregs->regs.gprs[13];
+ tst->arch.vex.guest_r14 = sigregs->regs.gprs[14];
+ tst->arch.vex.guest_r15 = sigregs->regs.gprs[15];
+
+ tst->arch.vex.guest_a0 = sigregs->regs.acrs[0];
+ tst->arch.vex.guest_a1 = sigregs->regs.acrs[1];
+ tst->arch.vex.guest_a2 = sigregs->regs.acrs[2];
+ tst->arch.vex.guest_a3 = sigregs->regs.acrs[3];
+ tst->arch.vex.guest_a4 = sigregs->regs.acrs[4];
+ tst->arch.vex.guest_a5 = sigregs->regs.acrs[5];
+ tst->arch.vex.guest_a6 = sigregs->regs.acrs[6];
+ tst->arch.vex.guest_a7 = sigregs->regs.acrs[7];
+ tst->arch.vex.guest_a8 = sigregs->regs.acrs[8];
+ tst->arch.vex.guest_a9 = sigregs->regs.acrs[9];
+ tst->arch.vex.guest_a10 = sigregs->regs.acrs[10];
+ tst->arch.vex.guest_a11 = sigregs->regs.acrs[11];
+ tst->arch.vex.guest_a12 = sigregs->regs.acrs[12];
+ tst->arch.vex.guest_a13 = sigregs->regs.acrs[13];
+ tst->arch.vex.guest_a14 = sigregs->regs.acrs[14];
+ tst->arch.vex.guest_a15 = sigregs->regs.acrs[15];
+
+ tst->arch.vex.guest_f0 = sigregs->fpregs.fprs[0];
+ tst->arch.vex.guest_f1 = sigregs->fpregs.fprs[1];
+ tst->arch.vex.guest_f2 = sigregs->fpregs.fprs[2];
+ tst->arch.vex.guest_f3 = sigregs->fpregs.fprs[3];
+ tst->arch.vex.guest_f4 = sigregs->fpregs.fprs[4];
+ tst->arch.vex.guest_f5 = sigregs->fpregs.fprs[5];
+ tst->arch.vex.guest_f6 = sigregs->fpregs.fprs[6];
+ tst->arch.vex.guest_f7 = sigregs->fpregs.fprs[7];
+ tst->arch.vex.guest_f8 = sigregs->fpregs.fprs[8];
+ tst->arch.vex.guest_f9 = sigregs->fpregs.fprs[9];
+ tst->arch.vex.guest_f10 = sigregs->fpregs.fprs[10];
+ tst->arch.vex.guest_f11 = sigregs->fpregs.fprs[11];
+ tst->arch.vex.guest_f12 = sigregs->fpregs.fprs[12];
+ tst->arch.vex.guest_f13 = sigregs->fpregs.fprs[13];
+ tst->arch.vex.guest_f14 = sigregs->fpregs.fprs[14];
+ tst->arch.vex.guest_f15 = sigregs->fpregs.fprs[15];
+ tst->arch.vex.guest_fpc = sigregs->fpregs.fpc;
+
+ tst->arch.vex.guest_IA = sigregs->regs.psw.addr;
+}
+
+/* Extend the stack segment downwards if needed so as to ensure the
+ new signal frames are mapped to something. Return a Bool
+ indicating whether or not the operation was successful.
+*/
+static Bool extend ( ThreadState *tst, Addr addr, SizeT size )
+{
+ ThreadId tid = tst->tid;
+ NSegment const* stackseg = NULL;
+
+ if (VG_(extend_stack)(addr, tst->client_stack_szB)) {
+ stackseg = VG_(am_find_nsegment)(addr);
+ if (0 && stackseg)
+ VG_(printf)("frame=%#lx seg=%#lx-%#lx\n",
+ addr, stackseg->start, stackseg->end);
+ }
+
+ if (stackseg == NULL || !stackseg->hasR || !stackseg->hasW) {
+ VG_(message)(
+ Vg_UserMsg,
+ "Can't extend stack to %#lx during signal delivery for thread %d:\n",
+ addr, tid);
+ if (stackseg == NULL)
+ VG_(message)(Vg_UserMsg, " no stack segment\n");
+ else
+ VG_(message)(Vg_UserMsg, " too small or bad protection modes\n");
+
+ /* set SIGSEGV to default handler */
+ VG_(set_default_handler)(VKI_SIGSEGV);
+ VG_(synth_fault_mapping)(tid, addr);
+
+ /* The whole process should be about to die, since the default
+ action of SIGSEGV to kill the whole process. */
+ return False;
+ }
+
+ /* For tracking memory events, indicate the entire frame has been
+ allocated. */
+ VG_TRACK( new_mem_stack_signal, addr - VG_STACK_REDZONE_SZB,
+ size + VG_STACK_REDZONE_SZB, tid );
+
+ return True;
+}
+
+
+/* Build the Valgrind-specific part of a signal frame. */
+
+static void build_vg_sigframe(struct vg_sigframe *frame,
+ ThreadState *tst,
+ UInt flags,
+ Int sigNo)
+{
+ frame->sigNo_private = sigNo;
+ frame->magicPI = 0x31415927;
+ frame->vex_shadow1 = tst->arch.vex_shadow1;
+ frame->vex_shadow2 = tst->arch.vex_shadow2;
+ /* HACK ALERT */
+ frame->vex = tst->arch.vex;
+ /* end HACK ALERT */
+ frame->mask = tst->sig_mask;
+ frame->handlerflags = flags;
+ frame->magicE = 0x27182818;
+}
+
+
+static Addr build_sigframe(ThreadState *tst,
+ Addr sp_top_of_frame,
+ const vki_siginfo_t *siginfo,
+ const struct vki_ucontext *siguc,
+ UInt flags,
+ const vki_sigset_t *mask,
+ void *restorer)
+{
+ struct sigframe *frame;
+ Addr sp = sp_top_of_frame;
+
+ vg_assert((flags & VKI_SA_SIGINFO) == 0);
+ vg_assert((sizeof(*frame) & 7) == 0);
+ vg_assert((sp & 7) == 0);
+
+ sp -= sizeof(*frame);
+ frame = (struct sigframe *)sp;
+
+ if (!extend(tst, sp, sizeof(*frame)))
+ return sp_top_of_frame;
+
+ /* retcode, sigNo, sc, sregs fields are to be written */
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
+ sp, offsetof(struct sigframe, vg) );
+
+ save_sigregs(tst, &frame->sregs);
+
+ frame->sigNo = siginfo->si_signo;
+ frame->sc.sregs = &frame->sregs;
+ VG_(memcpy)(frame->sc.oldmask, mask->sig, sizeof(frame->sc.oldmask));
+
+ if (flags & VKI_SA_RESTORER) {
+ SET_SIGNAL_GPR(tst, 14, restorer);
+ } else {
+ frame->retcode[0] = 0x0a;
+ frame->retcode[1] = __NR_sigreturn;
+ /* This normally should be &frame->recode. but since there
+ might be problems with non-exec stack and we must discard
+ the translation for the on-stack sigreturn we just use the
+ trampoline like x86,ppc. We still fill in the retcode, lets
+ just hope that nobody actually jumps here */
+ SET_SIGNAL_GPR(tst, 14, &VG_(s390x_linux_SUBST_FOR_sigreturn));
+ }
+
+ SET_SIGNAL_GPR(tst, 2, siginfo->si_signo);
+ SET_SIGNAL_GPR(tst, 3, &frame->sc);
+ /* fixs390: we dont fill in trapno and prot_addr in r4 and r5*/
+
+ /* Set up backchain. */
+ *((Addr *) sp) = sp_top_of_frame;
+
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
+ sp, offsetof(struct sigframe, vg) );
+
+ build_vg_sigframe(&frame->vg, tst, flags, siginfo->si_signo);
+
+ return sp;
+}
+
+static Addr build_rt_sigframe(ThreadState *tst,
+ Addr sp_top_of_frame,
+ const vki_siginfo_t *siginfo,
+ const struct vki_ucontext *siguc,
+ UInt flags,
+ const vki_sigset_t *mask,
+ void *restorer)
+{
+ struct rt_sigframe *frame;
+ Addr sp = sp_top_of_frame;
+ Int sigNo = siginfo->si_signo;
+
+ vg_assert((flags & VKI_SA_SIGINFO) != 0);
+ vg_assert((sizeof(*frame) & 7) == 0);
+ vg_assert((sp & 7) == 0);
+
+ sp -= sizeof(*frame);
+ frame = (struct rt_sigframe *)sp;
+
+ if (!extend(tst, sp, sizeof(*frame)))
+ return sp_top_of_frame;
+
+ /* retcode, sigNo, sc, sregs fields are to be written */
+ VG_TRACK( pre_mem_write, Vg_CoreSignal, tst->tid, "signal handler frame",
+ sp, offsetof(struct rt_sigframe, vg) );
+
+ save_sigregs(tst, &frame->uc.uc_mcontext);
+
+ if (flags & VKI_SA_RESTORER) {
+ frame->retcode[0] = 0;
+ frame->retcode[1] = 0;
+ SET_SIGNAL_GPR(tst, 14, restorer);
+ } else {
+ frame->retcode[0] = 0x0a;
+ frame->retcode[1] = __NR_rt_sigreturn;
+ /* This normally should be &frame->recode. but since there
+ might be problems with non-exec stack and we must discard
+ the translation for the on-stack sigreturn we just use the
+ trampoline like x86,ppc. We still fill in the retcode, lets
+ just hope that nobody actually jumps here */
+ SET_SIGNAL_GPR(tst, 14, &VG_(s390x_linux_SUBST_FOR_rt_sigreturn));
+ }
+
+ VG_(memcpy)(&frame->info, siginfo, sizeof(vki_siginfo_t));
+ frame->uc.uc_flags = 0;
+ frame->uc.uc_link = 0;
+ frame->uc.uc_sigmask = *mask;
+ frame->uc.uc_stack = tst->altstack;
+
+ SET_SIGNAL_GPR(tst, 2, siginfo->si_signo);
+ SET_SIGNAL_GPR(tst, 3, &frame->info);
+ SET_SIGNAL_GPR(tst, 4, &frame->uc);
+
+ /* Set up backchain. */
+ *((Addr *) sp) = sp_top_of_frame;
+
+ VG_TRACK( post_mem_write, Vg_CoreSignal, tst->tid,
+ sp, offsetof(struct rt_sigframe, vg) );
+
+ build_vg_sigframe(&frame->vg, tst, flags, sigNo);
+ return sp;
+}
+
+/* EXPORTED */
+void VG_(sigframe_create)( ThreadId tid,
+ Addr sp_top_of_frame,
+ const vki_siginfo_t *siginfo,
+ const struct vki_ucontext *siguc,
+ void *handler,
+ UInt flags,
+ const vki_sigset_t *mask,
+ void *restorer )
+{
+ Addr sp;
+ ThreadState* tst = VG_(get_ThreadState)(tid);
+
+ if (flags & VKI_SA_SIGINFO)
+ sp = build_rt_sigframe(tst, sp_top_of_frame, siginfo, siguc,
+ flags, mask, restorer);
+ else
+ sp = build_sigframe(tst, sp_top_of_frame, siginfo, siguc,
+ flags, mask, restorer);
+
+ /* Set the thread so it will next run the handler. */
+ VG_(set_SP)(tid, sp);
+ VG_TRACK( post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
+
+ tst->arch.vex.guest_IA = (Addr) handler;
+ /* We might have interrupted a repeating instruction that uses the guest
+ counter. Since our VEX requires that a new instruction will see a
+ guest counter == 0, we have to set it here. The old value will be
+ restored by restore_vg_sigframe. */
+ tst->arch.vex.guest_counter = 0;
+ /* This thread needs to be marked runnable, but we leave that the
+ caller to do. */
+}
+
+
+/*------------------------------------------------------------*/
+/*--- Destroying signal frames ---*/
+/*------------------------------------------------------------*/
+
+/* Return False and don't do anything, just set the client to take a
+ segfault, if it looks like the frame is corrupted. */
+static
+Bool restore_vg_sigframe ( ThreadState *tst,
+ struct vg_sigframe *frame, Int *sigNo )
+{
+ if (frame->magicPI != 0x31415927 ||
+ frame->magicE != 0x27182818) {
+ VG_(message)(Vg_UserMsg, "Thread %d return signal frame "
+ "corrupted. Killing process.\n",
+ tst->tid);
+ VG_(set_default_handler)(VKI_SIGSEGV);
+ VG_(synth_fault)(tst->tid);
+ *sigNo = VKI_SIGSEGV;
+ return False;
+ }
+ tst->sig_mask = frame->mask;
+ tst->tmp_sig_mask = frame->mask;
+ tst->arch.vex_shadow1 = frame->vex_shadow1;
+ tst->arch.vex_shadow2 = frame->vex_shadow2;
+ /* HACK ALERT */
+ tst->arch.vex = frame->vex;
+ /* end HACK ALERT */
+ *sigNo = frame->sigNo_private;
+ return True;
+}
+
+static
+SizeT restore_sigframe ( ThreadState *tst,
+ struct sigframe *frame, Int *sigNo )
+{
+ if (restore_vg_sigframe(tst, &frame->vg, sigNo))
+ restore_sigregs(tst, frame->sc.sregs);
+
+ return sizeof(*frame);
+}
+
+static
+SizeT restore_rt_sigframe ( ThreadState *tst,
+ struct rt_sigframe *frame, Int *sigNo )
+{
+ if (restore_vg_sigframe(tst, &frame->vg, sigNo)) {
+ restore_sigregs(tst, &frame->uc.uc_mcontext);
+ }
+ return sizeof(*frame);
+}
+
+
+/* EXPORTED */
+void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
+{
+ Addr sp;
+ ThreadState* tst;
+ SizeT size;
+ Int sigNo;
+
+ tst = VG_(get_ThreadState)(tid);
+
+ /* Correctly reestablish the frame base address. */
+ sp = tst->arch.vex.guest_SP;
+
+ if (!isRT)
+ size = restore_sigframe(tst, (struct sigframe *)sp, &sigNo);
+ else
+ size = restore_rt_sigframe(tst, (struct rt_sigframe *)sp, &sigNo);
+
+ /* same as for creation: we must announce the full memory (including
+ alignment), otherwise massif might fail on longjmp */
+ VG_TRACK( die_mem_stack_signal, sp - VG_STACK_REDZONE_SZB,
+ size + VG_STACK_REDZONE_SZB );
+
+ if (VG_(clo_trace_signals))
+ VG_(message)(
+ Vg_DebugMsg,
+ "VG_(sigframe_destroy) (thread %d): isRT=%d valid magic; IP=%#llx\n",
+ tid, isRT, tst->arch.vex.guest_IA);
+
+ /* tell the tools */
+ VG_TRACK( post_deliver_signal, tid, sigNo );
+}
+
+#endif /* VGA_s390x */
+
+/*--------------------------------------------------------------------*/
+/*--- end sigframe-s390x-linux.c ---*/
+/*--------------------------------------------------------------------*/
|
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:19
|
Nothing special here. We do the same as other architectures for several
functions and methods.
---
coregrind/m_aspacemgr/aspacemgr-common.c | 3 ++-
coregrind/m_aspacemgr/aspacemgr-linux.c | 2 +-
coregrind/m_libcfile.c | 12 ++++++------
coregrind/m_libcproc.c | 2 +-
coregrind/m_syswrap/priv_types_n_macros.h | 2 +-
coregrind/m_translate.c | 5 +++--
coregrind/m_transtab.c | 3 +++
coregrind/pub_core_mallocfree.h | 1 +
include/pub_tool_basics.h | 4 ++--
9 files changed, 20 insertions(+), 14 deletions(-)
--- valgrind-upstream.orig/coregrind/m_aspacemgr/aspacemgr-common.c
+++ valgrind-upstream/coregrind/m_aspacemgr/aspacemgr-common.c
@@ -159,7 +159,8 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr s
res = VG_(do_syscall6)(__NR_mmap2, (UWord)start, length,
prot, flags, fd, offset / 4096);
# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \
- || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
+ || defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) \
+ || defined(VGP_s390x_linux)
res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
prot, flags, fd, offset);
# elif defined(VGP_x86_darwin)
--- valgrind-upstream.orig/coregrind/m_aspacemgr/aspacemgr-linux.c
+++ valgrind-upstream/coregrind/m_aspacemgr/aspacemgr-linux.c
@@ -903,7 +903,7 @@ static void sync_check_mapping_callback
have a sloppyXcheck mode which we enable on x86 - in this mode we
allow the kernel to report execute permission when we weren't
expecting it but not vice versa. */
-# if defined(VGA_x86)
+# if defined(VGA_x86) || defined (VGA_s390x)
sloppyXcheck = True;
# else
sloppyXcheck = False;
--- valgrind-upstream.orig/coregrind/m_libcfile.c
+++ valgrind-upstream/coregrind/m_libcfile.c
@@ -795,7 +795,7 @@ static Int parse_inet_addr_and_port ( UC
Int VG_(socket) ( Int domain, Int type, Int protocol )
{
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
SysRes res;
UWord args[3];
args[0] = domain;
@@ -836,7 +836,7 @@ static
Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
{
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
SysRes res;
UWord args[3];
args[0] = sockfd;
@@ -876,7 +876,7 @@ Int VG_(write_socket)( Int sd, void *msg
SIGPIPE */
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
SysRes res;
UWord args[4];
args[0] = sd;
@@ -908,7 +908,7 @@ Int VG_(write_socket)( Int sd, void *msg
Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
{
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
SysRes res;
UWord args[3];
args[0] = sd;
@@ -940,7 +940,7 @@ Int VG_(getsockname) ( Int sd, struct vk
Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
{
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
SysRes res;
UWord args[3];
args[0] = sd;
@@ -973,7 +973,7 @@ Int VG_(getsockopt) ( Int sd, Int level,
Int *optlen)
{
# if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64_linux)
+ || defined(VGP_ppc64_linux) || defined(VGP_s390x_linux)
SysRes res;
UWord args[5];
args[0] = sd;
--- valgrind-upstream.orig/coregrind/m_libcproc.c
+++ valgrind-upstream/coregrind/m_libcproc.c
@@ -545,7 +545,7 @@ Int VG_(getgroups)( Int size, UInt* list
# elif defined(VGP_amd64_linux) || defined(VGP_ppc64_linux) \
|| defined(VGP_arm_linux) \
|| defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5) \
- || defined(VGO_darwin)
+ || defined(VGO_darwin) || defined(VGP_s390x_linux)
SysRes sres;
sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
if (sr_isError(sres))
--- valgrind-upstream.orig/coregrind/m_syswrap/priv_types_n_macros.h
+++ valgrind-upstream/coregrind/m_syswrap/priv_types_n_macros.h
@@ -89,7 +89,7 @@ typedef
Int o_sysno;
# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
|| defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux) \
- || defined(VGP_arm_linux)
+ || defined(VGP_arm_linux) || defined(VGP_s390x_linux)
Int o_arg1;
Int o_arg2;
Int o_arg3;
--- valgrind-upstream.orig/coregrind/m_translate.c
+++ valgrind-upstream/coregrind/m_translate.c
@@ -692,7 +692,7 @@ void log_bytes ( HChar* bytes, Int nbyte
static Bool translations_allowable_from_seg ( NSegment const* seg )
{
-# if defined(VGA_x86)
+# if defined(VGA_x86) || defined(VGA_s390x)
Bool allowR = True;
# else
Bool allowR = False;
@@ -1508,7 +1508,8 @@ Bool VG_(translate) ( ThreadId tid,
? (void*) &VG_(run_innerloop__dispatch_profiled)
: (void*) &VG_(run_innerloop__dispatch_unprofiled);
# elif defined(VGA_ppc32) || defined(VGA_ppc64) \
- || defined(VGA_arm)
+ || defined(VGA_arm) || defined(VGA_s390x)
+ /* See comment libvex.h; machine has link register --> dipatch = NULL */
vta.dispatch = NULL;
# else
# error "Unknown arch"
--- valgrind-upstream.orig/coregrind/m_transtab.c
+++ valgrind-upstream/coregrind/m_transtab.c
@@ -901,6 +901,9 @@ static void invalidate_icache ( void *pt
# elif defined(VGA_amd64)
/* no need to do anything, hardware provides coherence */
+# elif defined(VGA_s390x)
+ /* no need to do anything, hardware provides coherence */
+
# elif defined(VGP_arm_linux)
/* ARM cache flushes are privileged, so we must defer to the kernel. */
Addr startaddr = (Addr) ptr;
--- valgrind-upstream.orig/coregrind/pub_core_mallocfree.h
+++ valgrind-upstream/coregrind/pub_core_mallocfree.h
@@ -77,6 +77,7 @@ typedef Int ArenaId;
// for any AltiVec- or SSE-related type. This matches the Darwin libc.
#elif defined(VGP_amd64_linux) || \
defined(VGP_ppc64_linux) || \
+ defined(VGP_s390x_linux) || \
defined(VGP_ppc64_aix5) || \
defined(VGP_ppc32_aix5) || \
defined(VGP_x86_darwin) || \
--- valgrind-upstream.orig/include/pub_tool_basics.h
+++ valgrind-upstream/include/pub_tool_basics.h
@@ -292,7 +292,7 @@ static inline Bool sr_EQ ( SysRes sr1, S
#if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm)
# define VG_LITTLEENDIAN 1
-#elif defined(VGA_ppc32) || defined(VGA_ppc64)
+#elif defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x)
# define VG_BIGENDIAN 1
#else
# error Unknown arch
@@ -302,7 +302,7 @@ static inline Bool sr_EQ ( SysRes sr1, S
#if defined(VGA_x86)
# define VG_REGPARM(n) __attribute__((regparm(n)))
#elif defined(VGA_amd64) || defined(VGA_ppc32) \
- || defined(VGA_ppc64) || defined(VGA_arm)
+ || defined(VGA_ppc64) || defined(VGA_arm) || defined(VGA_s390x)
# define VG_REGPARM(n) /* */
#else
# error Unknown arch
|
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:22
|
This patch implements client and host system calls for s390x.
---
coregrind/m_syscall.c | 63 +
coregrind/m_syswrap/syscall-s390x-linux.S | 172 +++
coregrind/m_syswrap/syswrap-generic.c | 5
coregrind/m_syswrap/syswrap-linux.c | 19
coregrind/m_syswrap/syswrap-main.c | 79 +
coregrind/m_syswrap/syswrap-s390x-linux.c | 1524 ++++++++++++++++++++++++++++++
coregrind/pub_core_syscall.h | 1
7 files changed, 1855 insertions(+), 8 deletions(-)
--- valgrind-upstream.orig/coregrind/m_syscall.c
+++ valgrind-upstream/coregrind/m_syscall.c
@@ -100,6 +100,17 @@ SysRes VG_(mk_SysRes_ppc64_linux) ( ULon
return res;
}
+SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) {
+ SysRes res;
+ res._isError = val >= -4095 && val <= -1;
+ if (res._isError) {
+ res._val = -val;
+ } else {
+ res._val = val;
+ }
+ return res;
+}
+
SysRes VG_(mk_SysRes_arm_linux) ( Int val ) {
SysRes res;
res._isError = val >= -4095 && val <= -1;
@@ -719,6 +730,40 @@ asm(".private_extern _do_syscall_mach_WR
" retq \n"
);
+#elif defined(VGP_s390x_linux)
+
+#define _svc_clobber "1", "cc", "memory"
+
+static UWord do_syscall_WRK (
+ UWord syscall_no,
+ UWord arg1, UWord arg2, UWord arg3,
+ UWord arg4, UWord arg5, UWord arg6
+ )
+{
+ register UWord __arg1 asm("2") = arg1;
+ register UWord __arg2 asm("3") = arg2;
+ register UWord __arg3 asm("4") = arg3;
+ register UWord __arg4 asm("5") = arg4;
+ register UWord __arg5 asm("6") = arg5;
+ register UWord __arg6 asm("7") = arg6;
+ register ULong __svcres asm("2");
+
+ __asm__ __volatile__ (
+ "lgr %%r1,%1\n\t"
+ "svc 0\n\t"
+ : "=d" (__svcres)
+ : "a" (syscall_no),
+ "0" (__arg1),
+ "d" (__arg2),
+ "d" (__arg3),
+ "d" (__arg4),
+ "d" (__arg5),
+ "d" (__arg6)
+ : _svc_clobber);
+
+ return (UWord) (__svcres);
+}
+
#else
# error Unknown platform
#endif
@@ -846,6 +891,24 @@ SysRes VG_(do_syscall) ( UWord sysno, UW
}
return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO );
+#elif defined(VGP_s390x_linux)
+ UWord val;
+
+ if (sysno == __NR_mmap) {
+ ULong argbuf[6];
+
+ argbuf[0] = a1;
+ argbuf[1] = a2;
+ argbuf[2] = a3;
+ argbuf[3] = a4;
+ argbuf[4] = a5;
+ argbuf[5] = a6;
+ val = do_syscall_WRK(sysno,(UWord)&argbuf[0],0,0,0,0,0);
+ } else {
+ val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6);
+ }
+
+ return VG_(mk_SysRes_s390x_linux)( val );
#else
# error Unknown platform
#endif
--- /dev/null
+++ valgrind-upstream/coregrind/m_syswrap/syscall-s390x-linux.S
@@ -0,0 +1,172 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Support for doing system calls. syscall-s390x-linux.S ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright IBM Corp. 2010
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Christian Borntraeger */
+
+#include "pub_core_basics_asm.h"
+#include "pub_core_vkiscnums_asm.h"
+#include "libvex_guest_offsets.h"
+
+#if defined(VGA_s390x)
+
+/*----------------------------------------------------------------*/
+/*
+ Perform a syscall for the client. This will run a syscall
+ with the client's specific per-thread signal mask.
+
+ The structure of this function is such that, if the syscall is
+ interrupted by a signal, we can determine exactly what
+ execution state we were in with respect to the execution of
+ the syscall by examining the value of NIP in the signal
+ handler. This means that we can always do the appropriate
+ thing to precisely emulate the kernel's signal/syscall
+ interactions.
+
+ The syscall number is taken from the argument, since the syscall
+ number can be encoded in the svc instruction itself.
+ The syscall result is written back to guest register r2.
+
+ Returns 0 if the syscall was successfully called (even if the
+ syscall itself failed), or a nonzero error code in the lowest
+ 8 bits if one of the sigprocmasks failed (there's no way to
+ determine which one failed). And there's no obvious way to
+ recover from that either, but nevertheless we want to know.
+
+ VG_(fixup_guest_state_after_syscall_interrupted) does the
+ thread state fixup in the case where we were interrupted by a
+ signal.
+
+ Prototype:
+
+ UWord ML_(do_syscall_for_client_WRK)(
+ Int syscallno, // r2
+ void* guest_state, // r3
+ const vki_sigset_t *sysmask, // r4
+ const vki_sigset_t *postmask, // r5
+ Int nsigwords) // r6
+*/
+/* from vki_arch.h */
+#define VKI_SIG_SETMASK 2
+
+#define SP_SAVE 16
+#define SP_R2 SP_SAVE + 0*8
+#define SP_R3 SP_SAVE + 1*8
+#define SP_R4 SP_SAVE + 2*8
+#define SP_R5 SP_SAVE + 3*8
+#define SP_R6 SP_SAVE + 4*8
+#define SP_R7 SP_SAVE + 5*8
+#define SP_R8 SP_SAVE + 6*8
+#define SP_R9 SP_SAVE + 7*8
+
+.align 4
+.globl ML_(do_syscall_for_client_WRK)
+ML_(do_syscall_for_client_WRK):
+1: /* Even though we can't take a signal until the sigprocmask completes,
+ start the range early.
+ If eip is in the range [1,2), the syscall hasn't been started yet */
+
+ /* Set the signal mask which should be current during the syscall. */
+ /* Save and restore all the parameters and all the registers that
+ we clobber (r6-r9) */
+ stmg %r2,%r9, SP_R2(%r15)
+
+ lghi %r2, VKI_SIG_SETMASK /* how */
+ lgr %r3, %r4 /* sysmask */
+ lgr %r4, %r5 /* postmask */
+ lgr %r5, %r6 /* nsigwords */
+ svc __NR_rt_sigprocmask
+ cghi %r2, 0x0
+ jne 7f /* sigprocmask failed */
+
+ /* OK, that worked. Now do the syscall proper. */
+ lg %r9, SP_R3(%r15) /* guest state --> r9 */
+ lg %r2, OFFSET_s390x_r2(%r9) /* guest r2 --> real r2 */
+ lg %r3, OFFSET_s390x_r3(%r9) /* guest r3 --> real r3 */
+ lg %r4, OFFSET_s390x_r4(%r9) /* guest r4 --> real r4 */
+ lg %r5, OFFSET_s390x_r5(%r9) /* guest r5 --> real r5 */
+ lg %r6, OFFSET_s390x_r6(%r9) /* guest r6 --> real r6 */
+ lg %r7, OFFSET_s390x_r7(%r9) /* guest r7 --> real r7 */
+ lg %r1, SP_R2(%r15) /* syscallno -> r1 */
+
+2: svc 0
+
+3:
+ stg %r2, OFFSET_s390x_r2(%r9)
+
+4: /* Re-block signals. If eip is in [4,5), then the syscall
+ is complete and we needn't worry about it. */
+ lghi %r2, VKI_SIG_SETMASK /* how */
+ lg %r3, SP_R5(%r15) /* postmask */
+ lghi %r4, 0x0 /* NULL */
+ lg %r5, SP_R6(%r15) /* nsigwords */
+ svc __NR_rt_sigprocmask
+ cghi %r2, 0x0
+ jne 7f /* sigprocmask failed */
+
+5: /* everyting ok. return 0 and restore the call-saved
+ registers, that we have clobbered */
+ lghi %r2, 0x0
+ lmg %r6,%r9, SP_R6(%r15)
+ br %r14
+
+7: /* some problem. return 0x8000 | error and restore the call-saved
+ registers we have clobbered. */
+ nill %r2, 0x7fff
+ oill %r2, 0x8000
+ lmg %r6,%r9, SP_R6(%r15)
+ br %r14
+
+.section .rodata
+/* export the ranges so that
+ VG_(fixup_guest_state_after_syscall_interrupted) can do the
+ right thing */
+
+.globl ML_(blksys_setup)
+.globl ML_(blksys_restart)
+.globl ML_(blksys_complete)
+.globl ML_(blksys_committed)
+.globl ML_(blksys_finished)
+
+/* the compiler can assume that 8 byte data elements are aligned on 8 byte */
+.align 8
+ML_(blksys_setup): .quad 1b
+ML_(blksys_restart): .quad 2b
+ML_(blksys_complete): .quad 3b
+ML_(blksys_committed): .quad 4b
+ML_(blksys_finished): .quad 5b
+.previous
+
+/* Let the linker know we don't need an executable stack */
+.section .note.GNU-stack,"",@progbits
+
+#endif /* VGA_s390x */
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
--- valgrind-upstream.orig/coregrind/m_syswrap/syswrap-generic.c
+++ valgrind-upstream/coregrind/m_syswrap/syswrap-generic.c
@@ -1958,6 +1958,11 @@ ML_(generic_POST_sys_shmctl) ( ThreadId
* call, mmap (aka sys_mmap) which takes the arguments in the
* normal way and the offset in bytes.
*
+ * - On s390x-linux there is mmap (aka old_mmap) which takes the
+ * arguments in a memory block and the offset in bytes. mmap2
+ * is also available (but not exported via unistd.h) with
+ * arguments ina memory block and the offset in pages.
+ *
* To cope with all this we provide a generic handler function here
* and then each platform implements one or more system call handlers
* which call this generic routine after extracting and normalising
--- valgrind-upstream.orig/coregrind/m_syswrap/syswrap-linux.c
+++ valgrind-upstream/coregrind/m_syswrap/syswrap-linux.c
@@ -206,6 +206,14 @@ static void run_a_thread_NORETURN ( Word
"svc 0x00000000\n" /* exit(tst->os_state.exitcode) */
: "=m" (tst->status)
: "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
+#elif defined(VGP_s390x_linux)
+ asm volatile (
+ "st %1, %0\n" /* set tst->status = VgTs_Empty */
+ "lg 2, %3\n" /* set r2 = tst->os_state.exitcode */
+ "svc %2\n" /* exit(tst->os_state.exitcode) */
+ : "=m" (tst->status)
+ : "d" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
+ : "2");
#else
# error Unknown platform
#endif
@@ -288,6 +296,11 @@ void VG_(main_thread_wrapper_NORETURN)(T
sp -= 112;
sp &= ~((Addr)0xF);
*(UWord *)sp = 0;
+#elif defined(VGP_s390x_linux)
+ /* make a stack frame */
+ sp -= 160;
+ sp &= ~((Addr)0xF);
+ *(UWord *)sp = 0;
#endif
/* If we can't even allocate the first thread's stack, we're hosed.
@@ -342,6 +355,10 @@ SysRes ML_(do_fork_clone) ( ThreadId tid
res = VG_(do_syscall5)( __NR_clone, flags,
(UWord)NULL, (UWord)parent_tidptr,
(UWord)child_tidptr, (UWord)NULL );
+#elif defined(VGP_s390x_linux)
+ /* note that s390 has first the stack and then the flags */
+ res = VG_(do_syscall4)( __NR_clone, (UWord) NULL, flags,
+ (UWord)parent_tidptr, (UWord)child_tidptr);
#else
# error Unknown platform
#endif
@@ -3566,7 +3583,7 @@ POST(sys_lookup_dcookie)
}
#endif
-#if defined(VGP_amd64_linux)
+#if defined(VGP_amd64_linux) || defined(VGP_s390x_linux)
PRE(sys_lookup_dcookie)
{
*flags |= SfMayBlock;
--- valgrind-upstream.orig/coregrind/m_syswrap/syswrap-main.c
+++ valgrind-upstream/coregrind/m_syswrap/syswrap-main.c
@@ -60,14 +60,14 @@
/* Useful info which needs to be recorded somewhere:
Use of registers in syscalls is:
- NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
+ NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
LINUX:
- x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
- amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
- ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
- ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
- arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
-
+ x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
+ amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
+ ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
+ ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
+ arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
+ s390x SYSNO r2 r3 r4 r5 r6 r7 n/a n/a r2 (== ARG1)
AIX:
ppc32 r2 r3 r4 r5 r6 r7 r8 r9 r10 r3(res),r4(err)
ppc64 r2 r3 r4 r5 r6 r7 r8 r9 r10 r3(res),r4(err)
@@ -160,6 +160,9 @@
x86: Success(N) ==> edx:eax = N, cc = 0
Fail(N) ==> edx:eax = N, cc = 1
+ s390x: Success(N) ==> r2 = N
+ Fail(N) ==> r2 = -N
+
* The post wrapper is called if:
- it exists, and
@@ -611,6 +614,17 @@ void getSyscallArgsFromGuestState ( /*OU
// no canonical->sysno adjustment needed
+#elif defined(VGP_s390x_linux)
+ VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
+ canonical->sysno = gst->guest_SYSNO;
+ canonical->arg1 = gst->guest_r2;
+ canonical->arg2 = gst->guest_r3;
+ canonical->arg3 = gst->guest_r4;
+ canonical->arg4 = gst->guest_r5;
+ canonical->arg5 = gst->guest_r6;
+ canonical->arg6 = gst->guest_r7;
+ canonical->arg7 = 0;
+ canonical->arg8 = 0;
#else
# error "getSyscallArgsFromGuestState: unknown arch"
#endif
@@ -728,6 +742,16 @@ void putSyscallArgsIntoGuestState ( /*IN
stack[1] = canonical->arg7;
stack[2] = canonical->arg8;
+#elif defined(VGP_s390x_linux)
+ VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
+ gst->guest_SYSNO = canonical->sysno;
+ gst->guest_r2 = canonical->arg1;
+ gst->guest_r3 = canonical->arg2;
+ gst->guest_r4 = canonical->arg3;
+ gst->guest_r5 = canonical->arg4;
+ gst->guest_r6 = canonical->arg5;
+ gst->guest_r7 = canonical->arg6;
+
#else
# error "putSyscallArgsIntoGuestState: unknown arch"
#endif
@@ -842,6 +866,11 @@ void getSyscallStatusFromGuestState ( /*
);
canonical->what = SsComplete;
+# elif defined(VGP_s390x_linux)
+ VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
+ canonical->sres = VG_(mk_SysRes_s390x_linux)( gst->guest_r2 );
+ canonical->what = SsComplete;
+
# else
# error "getSyscallStatusFromGuestState: unknown arch"
# endif
@@ -1016,6 +1045,15 @@ void putSyscallStatusIntoGuestState ( /*
break;
}
+# elif defined(VGP_s390x_linux)
+ VexGuestS390XState* gst = (VexGuestS390XState*)gst_vanilla;
+ vg_assert(canonical->what == SsComplete);
+ if (sr_isError(canonical->sres)) {
+ gst->guest_r2 = - (Long)sr_Err(canonical->sres);
+ } else {
+ gst->guest_r2 = sr_Res(canonical->sres);
+ }
+
# else
# error "putSyscallStatusIntoGuestState: unknown arch"
# endif
@@ -1129,6 +1167,16 @@ void getSyscallArgLayout ( /*OUT*/Syscal
layout->s_arg7 = sizeof(UWord) * 1;
layout->s_arg8 = sizeof(UWord) * 2;
+#elif defined(VGP_s390x_linux)
+ layout->o_sysno = OFFSET_s390x_SYSNO;
+ layout->o_arg1 = OFFSET_s390x_r2;
+ layout->o_arg2 = OFFSET_s390x_r3;
+ layout->o_arg3 = OFFSET_s390x_r4;
+ layout->o_arg4 = OFFSET_s390x_r5;
+ layout->o_arg5 = OFFSET_s390x_r6;
+ layout->o_arg6 = OFFSET_s390x_r7;
+ layout->uu_arg7 = -1; /* impossible value */
+ layout->uu_arg8 = -1; /* impossible value */
#else
# error "getSyscallLayout: unknown arch"
#endif
@@ -1957,6 +2005,23 @@ void ML_(fixup_guest_state_to_restart_sy
// DDD: #warning GrP fixme amd64 restart unimplemented
vg_assert(0);
+#elif defined(VGP_s390x_linux)
+ arch->vex.guest_IA -= 2; // sizeof(syscall)
+
+ /* Make sure our caller is actually sane, and we're really backing
+ back over a syscall.
+
+ syscall == 0A <num>
+ */
+ {
+ UChar *p = (UChar *)arch->vex.guest_IA;
+ if (p[0] != 0x0A)
+ VG_(message)(Vg_DebugMsg,
+ "?! restarting over syscall at %#llx %02x %02x\n",
+ arch->vex.guest_IA, p[0], p[1]);
+
+ vg_assert(p[0] == 0x0A);
+ }
#else
# error "ML_(fixup_guest_state_to_restart_syscall): unknown plat"
#endif
--- /dev/null
+++ valgrind-upstream/coregrind/m_syswrap/syswrap-s390x-linux.c
@@ -0,0 +1,1524 @@
+
+/*--------------------------------------------------------------------*/
+/*--- Platform-specific syscalls stuff. syswrap-s390x-linux.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright IBM Corp. 2010
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+/* Contributed by Christian Borntraeger */
+
+#if defined(VGP_s390x_linux)
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+#include "pub_core_vkiscnums.h"
+#include "pub_core_threadstate.h"
+#include "pub_core_aspacemgr.h"
+#include "pub_core_debuglog.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
+#include "pub_core_libcproc.h"
+#include "pub_core_libcsignal.h"
+#include "pub_core_mallocfree.h"
+#include "pub_core_options.h"
+#include "pub_core_scheduler.h"
+#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
+#include "pub_core_signals.h"
+#include "pub_core_syscall.h"
+#include "pub_core_syswrap.h"
+#include "pub_core_tooliface.h"
+#include "pub_core_stacks.h" // VG_(register_stack)
+
+#include "priv_types_n_macros.h"
+#include "priv_syswrap-generic.h" /* for decls of generic wrappers */
+#include "priv_syswrap-linux.h" /* for decls of linux-ish wrappers */
+#include "priv_syswrap-linux-variants.h" /* decls of linux variant wrappers */
+#include "priv_syswrap-main.h"
+
+
+/* ---------------------------------------------------------------------
+ clone() handling
+ ------------------------------------------------------------------ */
+
+/* Call f(arg1), but first switch stacks, using 'stack' as the new
+ stack, and use 'retaddr' as f's return-to address. Also, clear all
+ the integer registers before entering f.
+ Thought: Why are we clearing the GPRs ? The callee pointed to by f
+ is a regular C function which will play by the ABI rules. So there is
+ no need to zero out the GPRs. If we assumed that f accesses registers at
+ will, then it would make sense to create a defined register state.
+ But then, why only for the GPRs and not the FPRs ? */
+__attribute__((noreturn))
+void ML_(call_on_new_stack_0_1) ( Addr stack,
+ Addr retaddr,
+ void (*f)(Word),
+ Word arg1 );
+/* Upon entering this function we have the following setup:
+ r2 = stack
+ r3 = retaddr
+ r4 = f_desc
+ r5 = arg1
+*/
+asm(
+ ".text\n"
+ ".align 4\n"
+ ".globl vgModuleLocal_call_on_new_stack_0_1\n"
+ ".type vgModuleLocal_call_on_new_stack_0_1, @function\n"
+ "vgModuleLocal_call_on_new_stack_0_1:\n"
+ " lgr %r15,%r2\n" // stack to r15
+ " lgr %r14,%r3\n" // retaddr to r14
+ " lgr %r2,%r5\n" // arg1 to r2
+ // zero all gprs to get a defined state
+ " lghi %r0,0\n"
+ " lghi %r1,0\n"
+ // r2 holds the argument for the callee
+ " lghi %r3,0\n"
+ // r4 holds the callee address
+ " lghi %r5,0\n"
+ " lghi %r6,0\n"
+ " lghi %r7,0\n"
+ " lghi %r8,0\n"
+ " lghi %r9,0\n"
+ " lghi %r10,0\n"
+ " lghi %r11,0\n"
+ " lghi %r12,0\n"
+ " lghi %r13,0\n"
+ // r14 holds the return address for the callee
+ // r15 is the stack pointer
+ " br %r4\n" // jump to f
+ ".previous\n"
+ );
+
+/*
+ Perform a clone system call. clone is strange because it has
+ fork()-like return-twice semantics, so it needs special
+ handling here.
+
+ Upon entry, we have:
+ void* child_stack in r2
+ long flags in r3
+ int* parent_tid in r4
+ int* child_tid in r5
+ int* child_tid in r6
+ Word (*fn)(void *) 160(r15)
+ void *arg 168(r15)
+
+ System call requires:
+ void* child_stack in r2 (sc arg1)
+ long flags in r3 (sc arg2)
+ int* parent_tid in r4 (sc arg3)
+ int* child_tid in r5 (sc arg4)
+ void* tlsaddr in r6 (sc arg5)
+
+ Returns a ULong encoded as: top half is %cr following syscall,
+ low half is syscall return value (r3).
+ */
+#define __NR_CLONE VG_STRINGIFY(__NR_clone)
+#define __NR_EXIT VG_STRINGIFY(__NR_exit)
+
+extern
+ULong do_syscall_clone_s390x_linux ( void *stack,
+ ULong flags,
+ Int *child_tid,
+ Int *parent_tid,
+ Addr tlsaddr,
+ Word (*fn)(void *),
+ void *arg);
+asm(
+ " .text\n"
+ " .align 4\n"
+ "do_syscall_clone_s390x_linux:\n"
+ " lg %r1, 160(%r15)\n" // save fn from parent stack into r1
+ " lg %r0, 168(%r15)\n" // save arg from parent stack into r0
+ " aghi %r2, -160\n" // create stack frame for child
+ // all syscall parameters are already in place (r2-r6)
+ " svc " __NR_CLONE"\n" // clone()
+ " ltgr %r2,%r2\n" // child if retval == 0
+ " jne 1f\n"
+
+ // CHILD - call thread function
+ " lgr %r2, %r0\n" // get arg from r0
+ " basr %r14,%r1\n" // call fn
+
+ // exit. The result is already in r2
+ " svc " __NR_EXIT"\n"
+
+ // Exit returned?!
+ " j +2\n"
+
+ "1:\n" // PARENT or ERROR
+ " br %r14\n"
+ ".previous\n"
+);
+
+#undef __NR_CLONE
+#undef __NR_EXIT
+
+void VG_(cleanup_thread) ( ThreadArchState* arch )
+{
+ /* only used on x86 for descriptor tables */
+}
+
+static void setup_child ( /*OUT*/ ThreadArchState *child,
+ /*IN*/ ThreadArchState *parent )
+{
+ /* We inherit our parent's guest state. */
+ child->vex = parent->vex;
+ child->vex_shadow1 = parent->vex_shadow1;
+ child->vex_shadow2 = parent->vex_shadow2;
+}
+
+
+/*
+ When a client clones, we need to keep track of the new thread. This means:
+ 1. allocate a ThreadId+ThreadState+stack for the the thread
+
+ 2. initialize the thread's new VCPU state
+
+ 3. create the thread using the same args as the client requested,
+ but using the scheduler entrypoint for IP, and a separate stack
+ for SP.
+ */
+static SysRes do_clone ( ThreadId ptid,
+ Addr sp, ULong flags,
+ Int *parent_tidptr,
+ Int *child_tidptr,
+ Addr tlsaddr)
+{
+ static const Bool debug = False;
+
+ ThreadId ctid = VG_(alloc_ThreadState)();
+ ThreadState* ptst = VG_(get_ThreadState)(ptid);
+ ThreadState* ctst = VG_(get_ThreadState)(ctid);
+ UWord* stack;
+ NSegment const* seg;
+ SysRes res;
+ ULong r2;
+ vki_sigset_t blockall, savedmask;
+
+ VG_(sigfillset)(&blockall);
+
+ vg_assert(VG_(is_running_thread)(ptid));
+ vg_assert(VG_(is_valid_tid)(ctid));
+
+ stack = (UWord*)ML_(allocstack)(ctid);
+ if (stack == NULL) {
+ res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
+ goto out;
+ }
+
+ /* Copy register state
+
+ Both parent and child return to the same place, and the code
+ following the clone syscall works out which is which, so we
+ don't need to worry about it.
+
+ The parent gets the child's new tid returned from clone, but the
+ child gets 0.
+
+ If the clone call specifies a NULL sp for the new thread, then
+ it actually gets a copy of the parent's sp.
+ */
+ setup_child( &ctst->arch, &ptst->arch );
+
+ /* Make sys_clone appear to have returned Success(0) in the
+ child. */
+ ctst->arch.vex.guest_r2 = 0;
+
+ if (sp != 0)
+ ctst->arch.vex.guest_r15 = sp;
+
+ ctst->os_state.parent = ptid;
+
+ /* inherit signal mask */
+ ctst->sig_mask = ptst->sig_mask;
+ ctst->tmp_sig_mask = ptst->sig_mask;
+
+ /* have the parents thread group */
+ ctst->os_state.threadgroup = ptst->os_state.threadgroup;
+
+ /* We don't really know where the client stack is, because its
+ allocated by the client. The best we can do is look at the
+ memory mappings and try to derive some useful information. We
+ assume that esp starts near its highest possible value, and can
+ only go down to the start of the mmaped segment. */
+ seg = VG_(am_find_nsegment)((Addr)sp);
+ if (seg && seg->kind != SkResvn) {
+ ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(sp);
+ ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
+
+ VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
+
+ if (debug)
+ VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
+ ctid, seg->start, VG_PGROUNDUP(sp));
+ } else {
+ VG_(message)(Vg_UserMsg,
+ "!? New thread %d starts with SP(%#lx) unmapped\n",
+ ctid, sp);
+ ctst->client_stack_szB = 0;
+ }
+
+ /* Assume the clone will succeed, and tell any tool that wants to
+ know that this thread has come into existence. If the clone
+ fails, we'll send out a ll_exit notification for it at the out:
+ label below, to clean up. */
+ VG_TRACK ( pre_thread_ll_create, ptid, ctid );
+
+ if (flags & VKI_CLONE_SETTLS) {
+ if (debug)
+ VG_(printf)("clone child has SETTLS: tls at %#lx\n", tlsaddr);
+ ctst->arch.vex.guest_a0 = (UInt) (tlsaddr >> 32);
+ ctst->arch.vex.guest_a1 = (UInt) tlsaddr;
+ }
+ flags &= ~VKI_CLONE_SETTLS;
+
+ /* start the thread with everything blocked */
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
+
+ /* Create the new thread */
+ r2 = do_syscall_clone_s390x_linux(
+ stack, flags, child_tidptr, parent_tidptr, tlsaddr,
+ ML_(start_thread_NORETURN), &VG_(threads)[ctid]);
+
+ res = VG_(mk_SysRes_s390x_linux)( r2 );
+
+ VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
+
+ out:
+ if (sr_isError(res)) {
+ /* clone failed */
+ ctst->status = VgTs_Empty;
+ /* oops. Better tell the tool the thread exited in a hurry :-) */
+ VG_TRACK( pre_thread_ll_exit, ctid );
+ }
+
+ return res;
+
+}
+
+
+
+/* ---------------------------------------------------------------------
+ PRE/POST wrappers for s390x/Linux-specific syscalls
+ ------------------------------------------------------------------ */
+
+#define PRE(name) DEFN_PRE_TEMPLATE(s390x_linux, name)
+#define POST(name) DEFN_POST_TEMPLATE(s390x_linux, name)
+
+/* Add prototypes for the wrappers declared here, so that gcc doesn't
+ harass us for not having prototypes. Really this is a kludge --
+ the right thing to do is to make these wrappers 'static' since they
+ aren't visible outside this file, but that requires even more macro
+ magic. */
+
+DECL_TEMPLATE(s390x_linux, sys_ptrace);
+DECL_TEMPLATE(s390x_linux, sys_socketcall);
+DECL_TEMPLATE(s390x_linux, sys_mmap);
+DECL_TEMPLATE(s390x_linux, sys_ipc);
+DECL_TEMPLATE(s390x_linux, sys_clone);
+DECL_TEMPLATE(s390x_linux, sys_sigreturn);
+DECL_TEMPLATE(s390x_linux, sys_rt_sigreturn);
+DECL_TEMPLATE(s390x_linux, sys_fadvise64);
+
+// PEEK TEXT,DATA and USER are common to all architectures
+// PEEKUSR_AREA and POKEUSR_AREA are special, having a memory area
+// containing the real addr, data, and len field pointed to by ARG3
+// instead of ARG4
+PRE(sys_ptrace)
+{
+ PRINT("sys_ptrace ( %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4);
+ PRE_REG_READ4(int, "ptrace",
+ long, request, long, pid, long, addr, long, data);
+ switch (ARG1) {
+ case VKI_PTRACE_PEEKTEXT:
+ case VKI_PTRACE_PEEKDATA:
+ case VKI_PTRACE_PEEKUSR:
+ PRE_MEM_WRITE( "ptrace(peek)", ARG4,
+ sizeof (long));
+ break;
+ case VKI_PTRACE_GETEVENTMSG:
+ PRE_MEM_WRITE( "ptrace(geteventmsg)", ARG4, sizeof(unsigned long));
+ break;
+ case VKI_PTRACE_GETSIGINFO:
+ PRE_MEM_WRITE( "ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t));
+ break;
+ case VKI_PTRACE_SETSIGINFO:
+ PRE_MEM_READ( "ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t));
+ break;
+ case VKI_PTRACE_PEEKUSR_AREA:
+ {
+ vki_ptrace_area *pa;
+
+ /* Reads a part of the user area into the memory at pa->process_addr */
+ pa = (vki_ptrace_area *) ARG3;
+ PRE_MEM_READ("ptrace(peekusrarea ptrace_area->len)",
+ (unsigned long) &pa->vki_len, sizeof(pa->vki_len));
+ PRE_MEM_READ("ptrace(peekusrarea ptrace_area->kernel_addr)",
+ (unsigned long) &pa->vki_kernel_addr, sizeof(pa->vki_kernel_addr));
+ PRE_MEM_READ("ptrace(peekusrarea ptrace_area->process_addr)",
+ (unsigned long) &pa->vki_process_addr, sizeof(pa->vki_process_addr));
+ PRE_MEM_WRITE("ptrace(peekusrarea *(ptrace_area->process_addr))",
+ pa->vki_process_addr, pa->vki_len);
+ break;
+ }
+ case VKI_PTRACE_POKEUSR_AREA:
+ {
+ vki_ptrace_area *pa;
+
+ /* Updates a part of the user area from the memory at pa->process_addr */
+ pa = (vki_ptrace_area *) ARG3;
+ PRE_MEM_READ("ptrace(pokeusrarea ptrace_area->len)",
+ (unsigned long) &pa->vki_len, sizeof(pa->vki_len));
+ PRE_MEM_READ("ptrace(pokeusrarea ptrace_area->kernel_addr)",
+ (unsigned long) &pa->vki_kernel_addr, sizeof(pa->vki_kernel_addr));
+ PRE_MEM_READ("ptrace(pokeusrarea ptrace_area->process_addr)",
+ (unsigned long) &pa->vki_process_addr, sizeof(pa->vki_process_addr));
+ PRE_MEM_READ("ptrace(pokeusrarea *(ptrace_area->process_addr))",
+ pa->vki_process_addr, pa->vki_len);
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+POST(sys_ptrace)
+{
+ switch (ARG1) {
+ case VKI_PTRACE_PEEKTEXT:
+ case VKI_PTRACE_PEEKDATA:
+ case VKI_PTRACE_PEEKUSR:
+ POST_MEM_WRITE( ARG4, sizeof (long));
+ break;
+ case VKI_PTRACE_GETEVENTMSG:
+ POST_MEM_WRITE( ARG4, sizeof(unsigned long));
+ break;
+ case VKI_PTRACE_GETSIGINFO:
+ /* XXX: This is a simplification. Different parts of the
+ * siginfo_t are valid depending on the type of signal.
+ */
+ POST_MEM_WRITE( ARG4, sizeof(vki_siginfo_t));
+ break;
+ case VKI_PTRACE_PEEKUSR_AREA:
+ {
+ vki_ptrace_area *pa;
+
+ pa = (vki_ptrace_area *) ARG3;
+ POST_MEM_WRITE(pa->vki_process_addr, pa->vki_len);
+ }
+ default:
+ break;
+ }
+}
+
+
+PRE(sys_socketcall)
+{
+# define ARG2_0 (((UWord*)ARG2)[0])
+# define ARG2_1 (((UWord*)ARG2)[1])
+# define ARG2_2 (((UWord*)ARG2)[2])
+# define ARG2_3 (((UWord*)ARG2)[3])
+# define ARG2_4 (((UWord*)ARG2)[4])
+# define ARG2_5 (((UWord*)ARG2)[5])
+
+ *flags |= SfMayBlock;
+ PRINT("sys_socketcall ( %ld, %#lx )",ARG1,ARG2);
+ PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args);
+
+ switch (ARG1 /* request */) {
+
+ case VKI_SYS_SOCKETPAIR:
+ /* int socketpair(int d, int type, int protocol, int sv[2]); */
+ PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 4*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 );
+ break;
+
+ case VKI_SYS_SOCKET:
+ /* int socket(int domain, int type, int protocol); */
+ PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 3*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ break;
+
+ case VKI_SYS_BIND:
+ /* int bind(int sockfd, struct sockaddr *my_addr,
+ int addrlen); */
+ PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 3*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 );
+ break;
+
+ case VKI_SYS_LISTEN:
+ /* int listen(int s, int backlog); */
+ PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 2*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ break;
+
+ case VKI_SYS_ACCEPT: {
+ /* int accept(int s, struct sockaddr *addr, int *addrlen); */
+ PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 3*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
+ break;
+ }
+
+ case VKI_SYS_SENDTO:
+ /* int sendto(int s, const void *msg, int len,
+ unsigned int flags,
+ const struct sockaddr *to, int tolen); */
+ PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 6*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2,
+ ARG2_3, ARG2_4, ARG2_5 );
+ break;
+
+ case VKI_SYS_SEND:
+ /* int send(int s, const void *msg, size_t len, int flags); */
+ PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 4*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 );
+ break;
+
+ case VKI_SYS_RECVFROM:
+ /* int recvfrom(int s, void *buf, int len, unsigned int flags,
+ struct sockaddr *from, int *fromlen); */
+ PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 6*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2,
+ ARG2_3, ARG2_4, ARG2_5 );
+ break;
+
+ case VKI_SYS_RECV:
+ /* int recv(int s, void *buf, int len, unsigned int flags); */
+ /* man 2 recv says:
+ The recv call is normally used only on a connected socket
+ (see connect(2)) and is identical to recvfrom with a NULL
+ from parameter.
+ */
+ PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 4*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 );
+ break;
+
+ case VKI_SYS_CONNECT:
+ /* int connect(int sockfd,
+ struct sockaddr *serv_addr, int addrlen ); */
+ PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 3*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 );
+ break;
+
+ case VKI_SYS_SETSOCKOPT:
+ /* int setsockopt(int s, int level, int optname,
+ const void *optval, int optlen); */
+ PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 5*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
+ ARG2_3, ARG2_4 );
+ break;
+
+ case VKI_SYS_GETSOCKOPT:
+ /* int getsockopt(int s, int level, int optname,
+ void *optval, socklen_t *optlen); */
+ PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 5*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(linux_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
+ ARG2_3, ARG2_4 );
+ break;
+
+ case VKI_SYS_GETSOCKNAME:
+ /* int getsockname(int s, struct sockaddr* name, int* namelen) */
+ PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 3*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 );
+ break;
+
+ case VKI_SYS_GETPEERNAME:
+ /* int getpeername(int s, struct sockaddr* name, int* namelen) */
+ PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 3*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 );
+ break;
+
+ case VKI_SYS_SHUTDOWN:
+ /* int shutdown(int s, int how); */
+ PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 2*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ break;
+
+ case VKI_SYS_SENDMSG: {
+ /* int sendmsg(int s, const struct msghdr *msg, int flags); */
+ PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 3*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
+ break;
+ }
+
+ case VKI_SYS_RECVMSG: {
+ /* int recvmsg(int s, struct msghdr *msg, int flags); */
+ PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
+ if (!ML_(valid_client_addr)(ARG2, 3*sizeof(Addr), tid, NULL)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ break;
+ }
+ ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
+ break;
+ }
+
+ default:
+ VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%lx\n",ARG1);
+ SET_STATUS_Failure( VKI_EINVAL );
+ break;
+ }
+# undef ARG2_0
+# undef ARG2_1
+# undef ARG2_2
+# undef ARG2_3
+# undef ARG2_4
+# undef ARG2_5
+}
+
+POST(sys_socketcall)
+{
+# define ARG2_0 (((UWord*)ARG2)[0])
+# define ARG2_1 (((UWord*)ARG2)[1])
+# define ARG2_2 (((UWord*)ARG2)[2])
+# define ARG2_3 (((UWord*)ARG2)[3])
+# define ARG2_4 (((UWord*)ARG2)[4])
+# define ARG2_5 (((UWord*)ARG2)[5])
+
+ SysRes r;
+ vg_assert(SUCCESS);
+ switch (ARG1 /* request */) {
+
+ case VKI_SYS_SOCKETPAIR:
+ r = ML_(generic_POST_sys_socketpair)(
+ tid, VG_(mk_SysRes_Success)(RES),
+ ARG2_0, ARG2_1, ARG2_2, ARG2_3
+ );
+ SET_STATUS_from_SysRes(r);
+ break;
+
+ case VKI_SYS_SOCKET:
+ r = ML_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) );
+ SET_STATUS_from_SysRes(r);
+ break;
+
+ case VKI_SYS_BIND:
+ /* int bind(int sockfd, struct sockaddr *my_addr,
+ int addrlen); */
+ break;
+
+ case VKI_SYS_LISTEN:
+ /* int listen(int s, int backlog); */
+ break;
+
+ case VKI_SYS_ACCEPT:
+ /* int accept(int s, struct sockaddr *addr, int *addrlen); */
+ r = ML_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES),
+ ARG2_0, ARG2_1, ARG2_2 );
+ SET_STATUS_from_SysRes(r);
+ break;
+
+ case VKI_SYS_SENDTO:
+ break;
+
+ case VKI_SYS_SEND:
+ break;
+
+ case VKI_SYS_RECVFROM:
+ ML_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES),
+ ARG2_0, ARG2_1, ARG2_2,
+ ARG2_3, ARG2_4, ARG2_5 );
+ break;
+
+ case VKI_SYS_RECV:
+ ML_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 );
+ break;
+
+ case VKI_SYS_CONNECT:
+ break;
+
+ case VKI_SYS_SETSOCKOPT:
+ break;
+
+ case VKI_SYS_GETSOCKOPT:
+ ML_(linux_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES),
+ ARG2_0, ARG2_1,
+ ARG2_2, ARG2_3, ARG2_4 );
+ break;
+
+ case VKI_SYS_GETSOCKNAME:
+ ML_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES),
+ ARG2_0, ARG2_1, ARG2_2 );
+ break;
+
+ case VKI_SYS_GETPEERNAME:
+ ML_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES),
+ ARG2_0, ARG2_1, ARG2_2 );
+ break;
+
+ case VKI_SYS_SHUTDOWN:
+ break;
+
+ case VKI_SYS_SENDMSG:
+ break;
+
+ case VKI_SYS_RECVMSG:
+ ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
+ break;
+
+ default:
+ VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%lx\n",ARG1);
+ VG_(core_panic)("... bye!\n");
+ break; /*NOTREACHED*/
+ }
+# undef ARG2_0
+# undef ARG2_1
+# undef ARG2_2
+# undef ARG2_3
+# undef ARG2_4
+# undef ARG2_5
+}
+
+PRE(sys_mmap)
+{
+ UWord a0, a1, a2, a3, a4, a5;
+ SysRes r;
+
+ UWord* args = (UWord*)ARG1;
+ PRE_REG_READ1(long, "sys_mmap", struct mmap_arg_struct *, args);
+ PRE_MEM_READ( "sys_mmap(args)", (Addr) args, 6*sizeof(UWord) );
+
+ a0 = args[0];
+ a1 = args[1];
+ a2 = args[2];
+ a3 = args[3];
+ a4 = args[4];
+ a5 = args[5];
+
+ PRINT("sys_mmap ( %#lx, %llu, %ld, %ld, %ld, %ld )",
+ a0, (ULong)a1, a2, a3, a4, a5 );
+
+ r = ML_(generic_PRE_sys_mmap)( tid, a0, a1, a2, a3, a4, (Off64T)a5 );
+ SET_STATUS_from_SysRes(r);
+}
+
+static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
+{
+ Addr* a_p = (Addr*)a;
+ PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
+ return *a_p;
+}
+
+PRE(sys_ipc)
+{
+ PRINT("sys_ipc ( %ld, %ld, %ld, %ld, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
+ // XXX: this is simplistic -- some args are not used in all circumstances.
+ PRE_REG_READ6(int, "ipc",
+ vki_uint, call, int, first, int, second, int, third,
+ void *, ptr, long, fifth)
+
+ switch (ARG1 /* call */) {
+ case VKI_SEMOP:
+ ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
+ *flags |= SfMayBlock;
+ break;
+ case VKI_SEMGET:
+ break;
+ case VKI_SEMCTL:
+ {
+ UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
+ ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
+ break;
+ }
+ case VKI_SEMTIMEDOP:
+ ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
+ *flags |= SfMayBlock;
+ break;
+ case VKI_MSGSND:
+ ML_(linux_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
+ if ((ARG4 & VKI_IPC_NOWAIT) == 0)
+ *flags |= SfMayBlock;
+ break;
+ case VKI_MSGRCV:
+ {
+ Addr msgp;
+ Word msgtyp;
+
+ msgp = deref_Addr( tid,
+ (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
+ "msgrcv(msgp)" );
+ msgtyp = deref_Addr( tid,
+ (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
+ "msgrcv(msgp)" );
+
+ ML_(linux_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
+
+ if ((ARG4 & VKI_IPC_NOWAIT) == 0)
+ *flags |= SfMayBlock;
+ break;
+ }
+ case VKI_MSGGET:
+ break;
+ case VKI_MSGCTL:
+ ML_(linux_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
+ break;
+ case VKI_SHMAT:
+ {
+ UWord w;
+ PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
+ w = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
+ if (w == 0)
+ SET_STATUS_Failure( VKI_EINVAL );
+ else
+ ARG5 = w;
+ break;
+ }
+ case VKI_SHMDT:
+ if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
+ SET_STATUS_Failure( VKI_EINVAL );
+ break;
+ case VKI_SHMGET:
+ break;
+ case VKI_SHMCTL: /* IPCOP_shmctl */
+ ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
+ break;
+ default:
+ VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %ld", ARG1 );
+ VG_(core_panic)("... bye!\n");
+ break; /*NOTREACHED*/
+ }
+}
+
+POST(sys_ipc)
+{
+ vg_assert(SUCCESS);
+ switch (ARG1 /* call */) {
+ case VKI_SEMOP:
+ case VKI_SEMGET:
+ break;
+ case VKI_SEMCTL:
+ {
+ UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
+ ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
+ break;
+ }
+ case VKI_SEMTIMEDOP:
+ case VKI_MSGSND:
+ break;
+ case VKI_MSGRCV:
+ {
+ Addr msgp;
+ Word msgtyp;
+
+ msgp = deref_Addr( tid,
+ (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
+ "msgrcv(msgp)" );
+ msgtyp = deref_Addr( tid,
+ (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
+ "msgrcv(msgp)" );
+
+ ML_(linux_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
+ break;
+ }
+ case VKI_MSGGET:
+ break;
+ case VKI_MSGCTL:
+ ML_(linux_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
+ break;
+ case VKI_SHMAT:
+ {
+ Addr addr;
+
+ /* force readability. before the syscall it is
+ * indeed uninitialized, as can be seen in
+ * glibc/sysdeps/unix/sysv/linux/shmat.c */
+ POST_MEM_WRITE( ARG4, sizeof( Addr ) );
+
+ addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
+ ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
+ break;
+ }
+ case VKI_SHMDT:
+ ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
+ break;
+ case VKI_SHMGET:
+ break;
+ case VKI_SHMCTL:
+ ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
+ break;
+ default:
+ VG_(message)(Vg_DebugMsg,
+ "FATAL: unhandled syscall(ipc) %ld",
+ ARG1 );
+ VG_(core_panic)("... bye!\n");
+ break; /*NOTREACHED*/
+ }
+}
+
+PRE(sys_clone)
+{
+ UInt cloneflags;
+
+ PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4, ARG5);
+ PRE_REG_READ4(int, "clone",
+ void *, child_stack,
+ unsigned long, flags,
+ int *, parent_tidptr,
+ int *, child_tidptr);
+
+ if (ARG2 & VKI_CLONE_PARENT_SETTID) {
+ PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
+ if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
+ VKI_PROT_WRITE)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ return;
+ }
+ }
+ if (ARG2 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
+ PRE_MEM_WRITE("clone(child_tidptr)", ARG4, sizeof(Int));
+ if (!VG_(am_is_valid_for_client)(ARG4, sizeof(Int),
+ VKI_PROT_WRITE)) {
+ SET_STATUS_Failure( VKI_EFAULT );
+ return;
+ }
+ }
+
+ cloneflags = ARG2;
+
+ if (!ML_(client_signal_OK)(ARG2 & VKI_CSIGNAL)) {
+ SET_STATUS_Failure( VKI_EINVAL );
+ return;
+ }
+
+ /* Only look at the flags we really care about */
+ switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
+ | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
+ case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
+ /* thread creation */
+ SET_STATUS_from_SysRes(
+ do_clone(tid,
+ (Addr)ARG1, /* child SP */
+ ARG2, /* flags */
+ (Int *)ARG3, /* parent_tidptr */
+ (Int *)ARG4, /* child_tidptr */
+ (Addr)ARG5)); /* tlsaddr */
+ break;
+
+ case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
+ /* FALLTHROUGH - assume vfork == fork */
+ cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
+
+ case 0: /* plain fork */
+ SET_STATUS_from_SysRes(
+ ML_(do_fork_clone)(tid,
+ cloneflags, /* flags */
+ (Int *)ARG3, /* parent_tidptr */
+ (Int *)ARG4)); /* child_tidptr */
+ break;
+
+ default:
+ /* should we just ENOSYS? */
+ VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx", ARG2);
+ VG_(message)(Vg_UserMsg, "");
+ VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
+ VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
+ VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
+ VG_(unimplemented)
+ ("Valgrind does not support general clone().");
+ }
+
+ if (SUCCESS) {
+ if (ARG2 & VKI_CLONE_PARENT_SETTID)
+ POST_MEM_WRITE(ARG3, sizeof(Int));
+ if (ARG2 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
+ POST_MEM_WRITE(ARG4, sizeof(Int));
+
+ /* Thread creation was successful; let the child have the chance
+ to run */
+ *flags |= SfYieldAfter;
+ }
+}
+
+PRE(sys_sigreturn)
+{
+ ThreadState* tst;
+ PRINT("sys_sigreturn ( )");
+
+ vg_assert(VG_(is_valid_tid)(tid));
+ vg_assert(tid >= 1 && tid < VG_N_THREADS);
+ vg_assert(VG_(is_running_thread)(tid));
+
+ tst = VG_(get_ThreadState)(tid);
+
+ /* This is only so that the EIP is (might be) useful to report if
+ something goes wrong in the sigreturn */
+ ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
+
+ /* Restore register state from frame and remove it */
+ VG_(sigframe_destroy)(tid, False);
+
+ /* Tell the driver not to update the guest state with the "result",
+ and set a bogus result to keep it happy. */
+ *flags |= SfNoWriteResult;
+ SET_STATUS_Success(0);
+
+ /* Check to see if any signals arose as a result of this. */
+ *flags |= SfPollAfter;
+}
+
+
+PRE(sys_rt_sigreturn)
+{
+ /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
+ an explanation of what follows. */
+
+ ThreadState* tst;
+ PRINT("sys_rt_sigreturn ( )");
+
+ vg_assert(VG_(is_valid_tid)(tid));
+ vg_assert(tid >= 1 && tid < VG_N_THREADS);
+ vg_assert(VG_(is_running_thread)(tid));
+
+ tst = VG_(get_ThreadState)(tid);
+
+ /* This is only so that the EIP is (might be) useful to report if
+ something goes wrong in the sigreturn */
+ ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
+
+ /* Restore register state from frame and remove it */
+ VG_(sigframe_destroy)(tid, True);
+
+ /* Tell the driver not to update the guest state with the "result",
+ and set a bogus result to keep it happy. */
+ *flags |= SfNoWriteResult;
+ SET_STATUS_Success(0);
+
+ /* Check to see if any signals arose as a result of this. */
+ *flags |= SfPollAfter;
+}
+
+/* we cant use the LINX_ version for 64 bit */
+PRE(sys_fadvise64)
+{
+ PRINT("sys_fadvise64 ( %ld, %ld, %ld, %ld )", ARG1,ARG2,ARG3,ARG4);
+ PRE_REG_READ4(long, "fadvise64",
+ int, fd, vki_loff_t, offset, vki_loff_t, len, int, advice);
+}
+
+#undef PRE
+#undef POST
+
+/* ---------------------------------------------------------------------
+ The s390x/Linux syscall table
+ ------------------------------------------------------------------ */
+
+/* Add an s390x-linux specific wrapper to a syscall table. */
+#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(s390x_linux, sysno, name)
+#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(s390x_linux, sysno, name)
+
+// This table maps from __NR_xxx syscall numbers from
+// linux/arch/s390/kernel/syscalls.S to the appropriate PRE/POST sys_foo()
+// wrappers on s390x. There are several unused numbers, which are only
+// defined on s390 (31bit mode) but no longer available on s390x (64 bit).
+// For those syscalls not handled by Valgrind, the annotation indicate its
+// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
+// (unknown).
+
+static SyscallTableEntry syscall_table[] = {
+ GENX_(0, sys_ni_syscall), /* unimplemented (by the kernel) */ // 0
+ GENX_(__NR_exit, sys_exit), // 1
+ GENX_(__NR_fork, sys_fork), // 2
+ GENXY(__NR_read, sys_read), // 3
+ GENX_(__NR_write, sys_write), // 4
+
+ GENXY(__NR_open, sys_open), // 5
+ GENXY(__NR_close, sys_close), // 6
+// ?????(__NR_restart_syscall, ), // 7
+ GENXY(__NR_creat, sys_creat), // 8
+ GENX_(__NR_link, sys_link), // 9
+
+ GENX_(__NR_unlink, sys_unlink), // 10
+ GENX_(__NR_execve, sys_execve), // 11
+ GENX_(__NR_chdir, sys_chdir), // 12
+ GENX_(13, sys_ni_syscall), /* unimplemented (by the kernel) */ // 13
+ GENX_(__NR_mknod, sys_mknod), // 14
+
+ GENX_(__NR_chmod, sys_chmod), // 15
+ GENX_(16, sys_ni_syscall), /* unimplemented (by the kernel) */ // 16
+ GENX_(17, sys_ni_syscall), /* unimplemented (by the kernel) */ // 17
+ GENX_(18, sys_ni_syscall), /* unimplemented (by the kernel) */ // 18
+ LINX_(__NR_lseek, sys_lseek), // 19
+
+ GENX_(__NR_getpid, sys_getpid), // 20
+ LINX_(__NR_mount, sys_mount), // 21
+ LINX_(__NR_umount, sys_oldumount), // 22
+ GENX_(23, sys_ni_syscall), /* unimplemented (by the kernel) */ // 23
+ GENX_(24, sys_ni_syscall), /* unimplemented (by the kernel) */ // 24
+
+ GENX_(25, sys_ni_syscall), /* unimplemented (by the kernel) */ // 25
+ PLAXY(__NR_ptrace, sys_ptrace), // 26
+ GENX_(__NR_alarm, sys_alarm), // 27
+ GENX_(28, sys_ni_syscall), /* unimplemented (by the kernel) */ // 28
+ GENX_(__NR_pause, sys_pause), // 29
+
+ LINX_(__NR_utime, sys_utime), // 30
+ GENX_(31, sys_ni_syscall), /* unimplemented (by the kernel) */ // 31
+ GENX_(32, sys_ni_syscall), /* unimplemented (by the kernel) */ // 32
+ GENX_(__NR_access, sys_access), // 33
+ GENX_(__NR_nice, sys_nice), // 34
+
+ GENX_(35, sys_ni_syscall), /* unimplemented (by the kernel) */ // 35
+ GENX_(__NR_sync, sys_sync), // 36
+ GENX_(__NR_kill, sys_kill), // 37
+ GENX_(__NR_rename, sys_rename), // 38
+ GENX_(__NR_mkdir, sys_mkdir), // 39
+
+ GENX_(__NR_rmdir, sys_rmdir), // 40
+ GENXY(__NR_dup, sys_dup), // 41
+ LINXY(__NR_pipe, sys_pipe), // 42
+ GENXY(__NR_times, sys_times), // 43
+ GENX_(44, sys_ni_syscall), /* unimplemented (by the kernel) */ // 44
+
+ GENX_(__NR_brk, sys_brk), // 45
+ GENX_(46, sys_ni_syscall), /* unimplemented (by the kernel) */ // 46
+ GENX_(47, sys_ni_syscall), /* unimplemented (by the kernel) */ // 47
+// ?????(__NR_signal, ), // 48
+ GENX_(49, sys_ni_syscall), /* unimplemented (by the kernel) */ // 49
+
+ GENX_(50, sys_ni_syscall), /* unimplemented (by the kernel) */ // 50
+ GENX_(__NR_acct, sys_acct), // 51
+ LINX_(__NR_umount2, sys_umount), // 52
+ GENX_(53, sys_ni_syscall), /* unimplemented (by the kernel) */ // 53
+ LINXY(__NR_ioctl, sys_ioctl), // 54
+
+ LINXY(__NR_fcntl, sys_fcntl), // 55
+ GENX_(56, sys_ni_syscall), /* unimplemented (by the kernel) */ // 56
+ GENX_(__NR_setpgid, sys_setpgid), // 57
+ GENX_(58, sys_ni_syscall), /* unimplemented (by the kernel) */ // 58
+ GENX_(59, sys_ni_syscall), /* unimplemented (by the kernel) */ // 59
+
+ GENX_(__NR_umask, sys_umask), // 60
+ GENX_(__NR_chroot, sys_chroot), // 61
+// ?????(__NR_ustat, sys_ustat), /* deprecated in favor of statfs */ // 62
+ GENXY(__NR_dup2, sys_dup2), // 63
+ GENX_(__NR_getppid, sys_getppid), // 64
+
+ GENX_(__NR_getpgrp, sys_getpgrp), // 65
+ GENX_(__NR_setsid, sys_setsid), // 66
+// ?????(__NR_sigaction, ), /* userspace uses rt_sigaction */ // 67
+ GENX_(68, sys_ni_syscall), /* unimplemented (by the kernel) */ // 68
+ GENX_(69, sys_ni_syscall), /* unimplemented (by the kernel) */ // 69
+
+ GENX_(70, sys_ni_syscall), /* unimplemented (by the kernel) */ // 70
+ GENX_(71, sys_ni_syscall), /* unimplemented (by the kernel) */ // 71
+// ?????(__NR_sigsuspend, ), // 72
+// ?????(__NR_sigpending, ), // 73
+// ?????(__NR_sethostname, ), // 74
+
+ GENX_(__NR_setrlimit, sys_setrlimit), // 75
+ GENXY(76, sys_getrlimit), /* see also 191 */ // 76
+ GENXY(__NR_getrusage, sys_getrusage), // 77
+ GENXY(__NR_gettimeofday, sys_gettimeofday), // 78
+ GENX_(__NR_settimeofday, sys_settimeofday), // 79
+
+ GENX_(80, sys_ni_syscall), /* unimplemented (by the kernel) */ // 80
+ GENX_(81, sys_ni_syscall), /* unimplemented (by the kernel) */ // 81
+ GENX_(82, sys_ni_syscall), /* unimplemented (by the kernel) */ // 82
+ GENX_(__NR_symlink, sys_symlink), // 83
+ GENX_(84, sys_ni_syscall), /* unimplemented (by the kernel) */ // 84
+
+ GENX_(__NR_readlink, sys_readlink), // 85
+// ?????(__NR_uselib, ), // 86
+// ?????(__NR_swapon, ), // 87
+// ?????(__NR_reboot, ), // 88
+ GENX_(89, sys_ni_syscall), /* unimplemented (by the kernel) */ // 89
+
+ PLAX_(__NR_mmap, sys_mmap ), // 90
+ GENXY(__NR_munmap, sys_munmap), // 91
+ GENX_(__NR_truncate, sys_truncate), // 92
+ GENX_(__NR_ftruncate, sys_ftruncate), // 93
+ GENX_(__NR_fchmod, sys_fchmod), // 94
+
+ GENX_(95, sys_ni_syscall), /* unimplemented (by the kernel) */ // 95
+ GENX_(__NR_getpriority, sys_getpriority), // 96
+ GENX_(__NR_setpriority, sys_setpriority), // 97
+ GENX_(98, sys_ni_syscall), /* unimplemented (by the kernel) */ // 98
+ GENXY(__NR_statfs, sys_statfs), // 99
+
+ GENXY(__NR_fstatfs, sys_fstatfs), // 100
+ GENX_(101, sys_ni_syscall), /* unimplemented (by the kernel) */ // 101
+ PLAXY(__NR_socketcall, sys_socketcall), // 102
+ LINXY(__NR_syslog, sys_syslog), // 103
+ GENXY(__NR_setitimer, sys_setitimer), // 104
+
+ GENXY(__NR_getitimer, sys_getitimer), ...
[truncated message content] |
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:24
|
This patch adds testcases for complex instructions, or instructions
that causes trouble during testing.
---
none/tests/Makefile.am | 5 +
none/tests/s390x/Makefile.am | 20 ++++++
none/tests/s390x/clcle.c | 71 +++++++++++++++++++++++
none/tests/s390x/clcle.stderr.exp | 2
none/tests/s390x/clcle.stdout.exp | 45 +++++++++++++++
none/tests/s390x/clcle.vgtest | 1
none/tests/s390x/cvb.c | 104 +++++++++++++++++++++++++++++++++++
none/tests/s390x/cvb.stderr.exp | 2
none/tests/s390x/cvb.stdout.exp | 68 ++++++++++++++++++++++
none/tests/s390x/cvb.vgtest | 1
none/tests/s390x/cvd.c | 34 +++++++++++
none/tests/s390x/cvd.stderr.exp | 2
none/tests/s390x/cvd.stdout.exp | 10 +++
none/tests/s390x/cvd.vgtest | 1
none/tests/s390x/ex_clone.c | 60 ++++++++++++++++++++
none/tests/s390x/ex_clone.stderr.exp | 2
none/tests/s390x/ex_clone.stdout.exp | 2
none/tests/s390x/ex_clone.vgtest | 1
none/tests/s390x/ex_sig.c | 46 +++++++++++++++
none/tests/s390x/ex_sig.stderr.exp | 2
none/tests/s390x/ex_sig.stdout.exp | 1
none/tests/s390x/ex_sig.vgtest | 1
none/tests/s390x/filter_stderr | 4 +
none/tests/s390x/flogr.c | 68 ++++++++++++++++++++++
none/tests/s390x/flogr.stderr.exp | 2
none/tests/s390x/flogr.vgtest | 1
none/tests/s390x/lpr.c | 95 +++++++++++++++++++++++++++++++
none/tests/s390x/lpr.stderr.exp | 2
none/tests/s390x/lpr.stdout.exp | 27 +++++++++
none/tests/s390x/lpr.vgtest | 1
none/tests/s390x/tcxb.c | 84 ++++++++++++++++++++++++++++
none/tests/s390x/tcxb.stderr.exp | 2
none/tests/s390x/tcxb.stdout.exp | 64 +++++++++++++++++++++
none/tests/s390x/tcxb.vgtest | 1
34 files changed, 831 insertions(+), 1 deletion(-)
--- valgrind-upstream.orig/none/tests/Makefile.am
+++ valgrind-upstream/none/tests/Makefile.am
@@ -19,6 +19,9 @@ endif
if VGCONF_ARCHS_INCLUDE_ARM
SUBDIRS += arm
endif
+if VGCONF_ARCHS_INCLUDE_S390X
+SUBDIRS += s390x
+endif
# OS-specific tests
if VGCONF_OS_IS_LINUX
@@ -33,7 +36,7 @@ if VGCONF_PLATFORMS_INCLUDE_X86_LINUX
SUBDIRS += x86-linux
endif
-DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm linux darwin x86-linux .
+DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm s390x linux darwin x86-linux .
dist_noinst_SCRIPTS = \
filter_cmdline0 \
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/Makefile.am
@@ -0,0 +1,20 @@
+include $(top_srcdir)/Makefile.tool-tests.am
+
+dist_noinst_SCRIPTS = filter_stderr
+
+INSN_TESTS = clcle cvb cvd lpr flogr tcxb
+
+check_PROGRAMS = $(INSN_TESTS) \
+ ex_sig \
+ ex_clone
+
+EXTRA_DIST = \
+ $(addsuffix .stderr.exp,$(check_PROGRAMS)) \
+ $(addsuffix .stdout.exp,$(check_PROGRAMS)) \
+ $(addsuffix .vgtest,$(check_PROGRAMS))
+
+AM_CFLAGS += @FLAG_M64@
+AM_CXXFLAGS += @FLAG_M64@
+AM_CCASFLAGS += @FLAG_M64@
+
+ex_clone_LDFLAGS = -lpthread
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/clcle.c
@@ -0,0 +1,71 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+char b1[23] ="0123456789abcdefghijklm";
+char b2[23] ="mlkjihgfedcba9876543210";
+char b3[23] ="mmmmmmmmmmmmmmmmmmmmmmm";
+char b4[23] ="00000000000000000000000";
+char longbuf[17000000];
+
+static int clcle(unsigned long *_a1, unsigned long *_l1, unsigned long *_a3, unsigned long *_l3, char _pad)
+{
+ register unsigned long a1 asm ("2") = *_a1;
+ register unsigned long l1 asm ("3") = *_l1;
+ register unsigned long a3 asm ("4") = *_a3;
+ register unsigned long l3 asm ("5") = *_l3;
+ register unsigned long pad asm ("6") = _pad;
+ register unsigned long cc asm ("7");
+
+ asm volatile( "0: clcle 2,4,0(6)\n\t"
+ "jo 0b\n\t"
+ "ipm %0\n\t"
+ "srl %0,28\n\t"
+ :"=d" (cc), "+d" (a1),"+d" (l1), "+d" (a3), "+d" (l3)
+ : "d" (pad)
+ : "memory", "cc");
+ *_a1 = a1;
+ *_a3 = a3;
+ *_l1 = l1;
+ *_l3 = l3;
+
+ return cc;
+}
+
+
+void testrun(void *_a1, unsigned long _l1, void *_a3, unsigned long _l3, char pad)
+{
+ unsigned long a1,a3,l1,l3;
+ int cc;
+
+ a1 = (unsigned long) _a1; l1 = _l1; a3 = (unsigned long) _a3; l3 = _l3;
+ cc = clcle(&a1, &l1, &a3, &l3, pad);
+ printf("cc: %d, l1: %lu(%lu) l3: %lu(%lu) diff1: %lu diff3: %lu\n",
+ cc, l1, _l1, l3, _l3, a1-(unsigned long) _a1, a3-(unsigned long) _a3);
+}
+
+
+void multiplex(unsigned long l1, unsigned long l3, char pad)
+{
+ testrun(b1, l1, b1, l3, pad);
+ testrun(b1, l1, b2, l3, pad);
+ testrun(b1, l1, b3, l3, pad);
+ testrun(b1, l1, b4, l3, pad);
+ testrun(b2, l1, b3, l3, pad);
+ testrun(b2, l1, b4, l3, pad);
+ testrun(b3, l1, b4, l3, pad);
+}
+
+int main()
+{
+ multiplex(0,0,9);
+ multiplex(1,0,9);
+ multiplex(0,1,9);
+ multiplex(1,1,9);
+ multiplex(5,23,9);
+ multiplex(23,5,9);
+ testrun(longbuf,10000,longbuf,100000,0);
+ testrun(longbuf,10000,longbuf,100000,128);
+ testrun(longbuf,10000,longbuf,100000,255);
+ exit(0);
+}
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/clcle.stderr.exp
@@ -0,0 +1,2 @@
+
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/clcle.stdout.exp
@@ -0,0 +1,45 @@
+cc: 0, l1: 0(0) l3: 0(0) diff1: 0 diff3: 0
+cc: 0, l1: 0(0) l3: 0(0) diff1: 0 diff3: 0
+cc: 0, l1: 0(0) l3: 0(0) diff1: 0 diff3: 0
+cc: 0, l1: 0(0) l3: 0(0) diff1: 0 diff3: 0
+cc: 0, l1: 0(0) l3: 0(0) diff1: 0 diff3: 0
+cc: 0, l1: 0(0) l3: 0(0) diff1: 0 diff3: 0
+cc: 0, l1: 0(0) l3: 0(0) diff1: 0 diff3: 0
+cc: 2, l1: 1(1) l3: 0(0) diff1: 0 diff3: 0
+cc: 2, l1: 1(1) l3: 0(0) diff1: 0 diff3: 0
+cc: 2, l1: 1(1) l3: 0(0) diff1: 0 diff3: 0
+cc: 2, l1: 1(1) l3: 0(0) diff1: 0 diff3: 0
+cc: 2, l1: 1(1) l3: 0(0) diff1: 0 diff3: 0
+cc: 2, l1: 1(1) l3: 0(0) diff1: 0 diff3: 0
+cc: 2, l1: 1(1) l3: 0(0) diff1: 0 diff3: 0
+cc: 1, l1: 0(0) l3: 1(1) diff1: 0 diff3: 0
+cc: 1, l1: 0(0) l3: 1(1) diff1: 0 diff3: 0
+cc: 1, l1: 0(0) l3: 1(1) diff1: 0 diff3: 0
+cc: 1, l1: 0(0) l3: 1(1) diff1: 0 diff3: 0
+cc: 1, l1: 0(0) l3: 1(1) diff1: 0 diff3: 0
+cc: 1, l1: 0(0) l3: 1(1) diff1: 0 diff3: 0
+cc: 1, l1: 0(0) l3: 1(1) diff1: 0 diff3: 0
+cc: 0, l1: 0(1) l3: 0(1) diff1: 1 diff3: 1
+cc: 1, l1: 1(1) l3: 1(1) diff1: 0 diff3: 0
+cc: 1, l1: 1(1) l3: 1(1) diff1: 0 diff3: 0
+cc: 0, l1: 0(1) l3: 0(1) diff1: 1 diff3: 1
+cc: 0, l1: 0(1) l3: 0(1) diff1: 1 diff3: 1
+cc: 2, l1: 1(1) l3: 1(1) diff1: 0 diff3: 0
+cc: 2, l1: 1(1) l3: 1(1) diff1: 0 diff3: 0
+cc: 1, l1: 0(5) l3: 18(23) diff1: 5 diff3: 5
+cc: 1, l1: 5(5) l3: 23(23) diff1: 0 diff3: 0
+cc: 1, l1: 5(5) l3: 23(23) diff1: 0 diff3: 0
+cc: 2, l1: 4(5) l3: 22(23) diff1: 1 diff3: 1
+cc: 1, l1: 4(5) l3: 22(23) diff1: 1 diff3: 1
+cc: 2, l1: 5(5) l3: 23(23) diff1: 0 diff3: 0
+cc: 2, l1: 5(5) l3: 23(23) diff1: 0 diff3: 0
+cc: 2, l1: 18(23) l3: 0(5) diff1: 5 diff3: 5
+cc: 1, l1: 23(23) l3: 5(5) diff1: 0 diff3: 0
+cc: 1, l1: 23(23) l3: 5(5) diff1: 0 diff3: 0
+cc: 2, l1: 22(23) l3: 4(5) diff1: 1 diff3: 1
+cc: 1, l1: 22(23) l3: 4(5) diff1: 1 diff3: 1
+cc: 2, l1: 23(23) l3: 5(5) diff1: 0 diff3: 0
+cc: 2, l1: 23(23) l3: 5(5) diff1: 0 diff3: 0
+cc: 0, l1: 0(10000) l3: 0(100000) diff1: 10000 diff3: 100000
+cc: 2, l1: 0(10000) l3: 90000(100000) diff1: 10000 diff3: 10000
+cc: 2, l1: 0(10000) l3: 90000(100000) diff1: 10000 diff3: 10000
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/clcle.vgtest
@@ -0,0 +1 @@
+prog: clcle
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/cvb.c
@@ -0,0 +1,104 @@
+#include <stdio.h>
+
+static unsigned long test[] ={
+ 0x000000000000000a,
+ 0x000000000000001a,
+ 0x000000000000012a,
+ 0x000000000000123a,
+ 0x000000000001234a,
+ 0x000000000012345a,
+ 0x000000000123456a,
+ 0x000000001234567a,
+ 0x000000012345678a,
+ 0x000000123456789a,
+ 0x000001234567890a,
+ 0x000000000000000b,
+ 0x000000000000001b,
+ 0x000000000000012b,
+ 0x000000000000123b,
+ 0x000000000001234b,
+ 0x000000000012345b,
+ 0x000000000123456b,
+ 0x000000001234567b,
+ 0x000000012345678b,
+ 0x000000123456789b,
+ 0x000001234567890b,
+ 0x000000000000000c,
+ 0x000000000000001c,
+ 0x000000000000012c,
+ 0x000000000000123c,
+ 0x000000000001234c,
+ 0x000000000012345c,
+ 0x000000000123456c,
+ 0x000000001234567c,
+ 0x000000012345678c,
+ 0x000000123456789c,
+ 0x000001234567890c,
+ 0x000000000000000d,
+ 0x000000000000001d,
+ 0x000000000000012d,
+ 0x000000000000123d,
+ 0x000000000001234d,
+ 0x000000000012345d,
+ 0x000000000123456d,
+ 0x000000001234567d,
+ 0x000000012345678d,
+ 0x000000123456789d,
+ 0x000001234567890d,
+ 0x000000000000000e,
+ 0x000000000000001e,
+ 0x000000000000012e,
+ 0x000000000000123e,
+ 0x000000000001234e,
+ 0x000000000012345e,
+ 0x000000000123456e,
+ 0x000000001234567e,
+ 0x000000012345678e,
+ 0x000000123456789e,
+ 0x000001234567890e,
+ 0x000000000000000f,
+ 0x000000000000001f,
+ 0x000000000000012f,
+ 0x000000000000123f,
+ 0x000000000001234f,
+ 0x000000000012345f,
+ 0x000000000123456f,
+ 0x000000001234567f,
+ 0x000000012345678f,
+ 0x000000123456789f,
+ 0x000001234567890f,
+ /* min and max */
+ 0x000002147483647c,
+ 0x000002147483648d,
+
+/* fixs390: we also need to check if invalid values cause a fixed-point-devide exception.
+ Not yet implemented. */
+/* 0x000002147483648c,
+ 0x000002147483649d,
+ 0x00000000000000fa, */
+
+};
+
+
+static signed int dec_to_hex(unsigned long *addr)
+{
+ register signed int res asm("2") = 0;
+ register unsigned long *_addr asm("4") = addr;
+
+ asm volatile(
+ " cvb %0,0(0,%1)"
+ : "=d" (res) : "d" (_addr) : "memory");
+ return res & 0xffffffff;
+}
+
+
+
+
+int main()
+{
+ int i;
+
+ for (i = 0; i < sizeof(test) / sizeof(test[0]); i++)
+ printf("%d\n", dec_to_hex(&test[i]));
+ return 0;
+}
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/cvb.stderr.exp
@@ -0,0 +1,2 @@
+
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/cvb.stdout.exp
@@ -0,0 +1,68 @@
+0
+1
+12
+123
+1234
+12345
+123456
+1234567
+12345678
+123456789
+1234567890
+0
+-1
+-12
+-123
+-1234
+-12345
+-123456
+-1234567
+-12345678
+-123456789
+-1234567890
+0
+1
+12
+123
+1234
+12345
+123456
+1234567
+12345678
+123456789
+1234567890
+0
+-1
+-12
+-123
+-1234
+-12345
+-123456
+-1234567
+-12345678
+-123456789
+-1234567890
+0
+1
+12
+123
+1234
+12345
+123456
+1234567
+12345678
+123456789
+1234567890
+0
+1
+12
+123
+1234
+12345
+123456
+1234567
+12345678
+123456789
+1234567890
+2147483647
+-2147483648
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/cvb.vgtest
@@ -0,0 +1 @@
+prog: cvb
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/cvd.c
@@ -0,0 +1,34 @@
+#include <stdio.h>
+
+static signed int test[] ={
+ 0,
+ 1,
+ -1,
+ 0x7fffffff,
+ 0x80000000,
+ 0x12345678,
+ 0x87654321,
+ 0x55555555,
+ 0x11111111,
+ 0xaaaaaaaa,
+};
+
+
+static unsigned long hex_to_dec(signed int num)
+{
+ unsigned long addr = 0;
+
+ asm volatile(
+ " cvd %2,%0"
+ : "=m" (addr) : "a" (&addr) , "d" (num) : "memory");
+ return addr;
+}
+
+int main()
+{
+ int i;
+
+ for (i = 0; i < sizeof(test) / sizeof(test[0]); i++)
+ printf("%lx\n", hex_to_dec(test[i]));
+ return 0;
+}
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/cvd.stderr.exp
@@ -0,0 +1,2 @@
+
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/cvd.stdout.exp
@@ -0,0 +1,10 @@
+c
+1c
+1d
+2147483647c
+2147483648d
+305419896c
+2023406815d
+1431655765c
+286331153c
+1431655766d
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/cvd.vgtest
@@ -0,0 +1 @@
+prog: cvd
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/ex_clone.c
@@ -0,0 +1,60 @@
+#include <features.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+char source[40] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0";
+char target[40] = " \0";
+
+pthread_t thread;
+
+void *threadfunc(void *arg)
+{
+ char buf2[40];
+ int i;
+
+ memset(buf2, 0, sizeof(buf2));
+ for (i=0; i<5000; i++)
+ asm volatile(
+ "lghi 2,0\n"
+ "lghi 3,0\n"
+ "lgr 4,%0\n"
+ "lgr 5,%1\n"
+ "larl 1,1f\n"
+ "0: ex 0,0(1)\n"
+ "j 2f\n"
+ "1: mvc 0(30,4),0(5)\n"
+ "2:\n"
+ ::"a" (buf2), "a" (source)
+ : "1", "2", "3", "4", "5", "memory");
+ printf("%s\n", buf2);
+ pthread_exit(0);
+}
+
+int main()
+{
+ int i;
+
+ pthread_create(&thread, NULL, threadfunc, NULL);
+
+ for (i=0; i<5000; i++)
+ asm volatile(
+ "lghi 4,0\n"
+ "lghi 5,0\n"
+ "lgr 2,%0\n"
+ "lgr 3,%1\n"
+ "larl 1,1f\n"
+ "0: ex 0,0(1)\n"
+ "j 2f\n"
+ "1: mvc 0(20,2),0(3)\n"
+ "2:\n"
+ ::"a" (target), "a" (source)
+ : "1", "2", "3", "4", "5", "memory");
+ pthread_join(thread, NULL);
+ printf("%s\n", target);
+ pthread_exit(0);
+}
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/ex_clone.stderr.exp
@@ -0,0 +1,2 @@
+
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/ex_clone.stdout.exp
@@ -0,0 +1,2 @@
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
+aaaaaaaaaaaaaaaaaaaa
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/ex_clone.vgtest
@@ -0,0 +1 @@
+prog: ex_clone
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/ex_sig.c
@@ -0,0 +1,46 @@
+#include <features.h>
+#include <fpu_control.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ucontext.h>
+#include <unistd.h>
+
+char source[40] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\0";
+char target[40] = " \0";
+
+void handle_SIG(int sig)
+{
+ static int counter;
+ char buf2[40];
+
+ counter++;
+ asm volatile( "larl 1,1f\n"
+ "ex 0,0(1)\n"
+ "j 2f\n"
+ "1: mvc 0(30,%0),0(%1)\n"
+ "2:\n"
+ ::"a" (buf2), "a" (source)
+ : "1");
+ if (counter == 2) {
+ printf("%s\n", target);
+ exit(1);
+ } else
+ alarm(1);
+}
+
+int main()
+{
+ signal(SIGALRM, handle_SIG);
+ alarm(1);
+
+ asm volatile( "larl 1,1f\n"
+ "0: ex 0,0(1)\n"
+ "j 0b\n"
+ "1: mvc 0(20,%0),0(%1)\n"
+ ::"a" (target), "a" (source)
+ : "1");
+ exit(0);
+}
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/ex_sig.stderr.exp
@@ -0,0 +1,2 @@
+
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/ex_sig.stdout.exp
@@ -0,0 +1 @@
+aaaaaaaaaaaaaaaaaaaa
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/ex_sig.vgtest
@@ -0,0 +1 @@
+prog: ex_sig
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/filter_stderr
@@ -0,0 +1,4 @@
+#! /bin/sh
+
+../filter_stderr
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/flogr.c
@@ -0,0 +1,68 @@
+#include <stdio.h>
+
+
+/* Call FLOGR on INPUT. The results are returned through the parms. */
+void
+flogr(unsigned long input, unsigned long *bitpos, unsigned long *modval,
+ unsigned int *cc)
+{
+ unsigned int psw;
+ register unsigned long value asm("4") = input;
+
+ asm volatile ( "flogr 2, %[val]\n\t"
+ "ipm %[psw]\n\t"
+ "stg 2, %[bitpos]\n\t"
+ "stg 3, %[modval]\n\t"
+ : [bitpos]"=m"(*bitpos), [modval]"=m"(*modval),
+ [psw]"=d"(psw)
+ : [val] "d"(value)
+ : "2", "3", "cc");
+
+ *cc = psw >> 28;
+#if 0
+ printf("value = %lx, bitpos = %lu, modval = %lx, cc = %d\n",
+ value, *bitpos, *modval, *cc);
+#endif
+}
+
+void
+runtest(void)
+{
+ unsigned long bitpos, modval, value;
+ unsigned int cc;
+ int i;
+
+ /* Value 0 is special */
+ value = 0;
+ flogr(value, &bitpos, &modval, &cc);
+ if (modval != 0) fprintf(stderr, "modval is wrong for %lx\n", value);
+ if (bitpos != 64) fprintf(stderr, "bitpos is wrong for %lx\n", value);
+ if (cc != 0) fprintf(stderr, "cc is wrong for %lx\n", value);
+
+ /* Test with exactly 1 bit set */
+ for (i = 0; i < 64; ++i) {
+ value = 1ull << i;
+ flogr(value, &bitpos, &modval, &cc);
+ if (modval != 0) fprintf(stderr, "modval is wrong for %lx\n", value);
+ if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value);
+ if (cc != 2) fprintf(stderr, "cc is wrong for %lx\n", value);
+ }
+
+ /* Test with all bits 1 right from first 1 bit */
+ for (i = 1; i < 64; ++i) {
+ value = 1ull << i;
+ value = value | (value - 1);
+ flogr(value, &bitpos, &modval, &cc);
+ if (modval != (value >> 1)) fprintf(stderr, "modval is wrong for %lx\n", value);
+ if (bitpos != 63 - i) fprintf(stderr, "bitpos is wrong for %lx\n", value);
+ if (cc != 2) fprintf(stderr, "cc is wrong for %lx\n", value);
+ }
+}
+
+
+int main()
+{
+ runtest();
+
+ return 0;
+}
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/flogr.stderr.exp
@@ -0,0 +1,2 @@
+
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/flogr.vgtest
@@ -0,0 +1 @@
+prog: flogr
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/lpr.c
@@ -0,0 +1,95 @@
+#include <limits.h>
+#include <stdio.h>
+
+int lpr(int org, int *new)
+{
+ int _new, cc;
+ asm volatile( "lpr %0,%2\n\t"
+ "ipm %1\n\t"
+ "srl %1,28\n\t"
+ : "=d" (_new), "=d" (cc)
+ : "d" (org)
+ : "cc");
+ *new = _new;
+ return cc;
+}
+
+int lpgr(unsigned long org, unsigned long *new)
+{
+ unsigned long _new;
+ int cc;
+ asm volatile( "lpgr %0,%2\n\t"
+ "ipm %1\n\t"
+ "srl %1,28\n\t"
+ : "=d" (_new), "=d" (cc)
+ : "d" (org)
+ : "cc");
+ *new = _new;
+ return cc;
+}
+
+int lpgfr(unsigned long org, unsigned long *new)
+{
+ unsigned long _new;
+ int cc;
+ asm volatile( "lpgfr %0,%2\n\t"
+ "ipm %1\n\t"
+ "srl %1,28\n\t"
+ : "=d" (_new), "=d" (cc)
+ : "d" (org)
+ : "cc");
+ *new = _new;
+ return cc;
+}
+
+
+void t32(int value)
+{
+ int n,cc;
+
+ cc = lpr(value, &n);
+
+ printf("new: %d cc: %d\n", n, cc);
+}
+
+void t64(unsigned long value)
+{
+ int cc;
+ unsigned long n;
+
+ cc = lpgr(value, &n);
+
+ printf("new: %ld cc: %d\n", n, cc);
+}
+
+void t3264(unsigned long value)
+{
+ int cc;
+ unsigned long n;
+
+ cc = lpgfr(value, &n);
+
+ printf("new: %ld cc: %d\n", n, cc);
+}
+
+
+
+int main()
+{
+ printf("lpr\n");
+ t32(0); t32(1); t32(-1);
+ t32(INT_MAX); t32(INT_MIN); t32(UINT_MAX);
+
+ printf("lpgr\n");
+ t64(0); t64(1); t64(-1);
+ t64(INT_MAX); t64(INT_MIN); t64(UINT_MAX);
+ t64(LONG_MAX); t64(LONG_MIN); t64(ULONG_MAX);
+
+ printf("lpgfr\n");
+ t3264(0); t3264(1); t64(-1);
+ t3264(INT_MAX); t3264(INT_MIN); t3264(UINT_MAX);
+ t3264(LONG_MAX); t3264(LONG_MIN); t3264(ULONG_MAX);
+
+ return 0;
+}
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/lpr.stderr.exp
@@ -0,0 +1,2 @@
+
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/lpr.stdout.exp
@@ -0,0 +1,27 @@
+lpr
+new: 0 cc: 0
+new: 1 cc: 2
+new: 1 cc: 2
+new: 2147483647 cc: 2
+new: -2147483648 cc: 3
+new: 1 cc: 2
+lpgr
+new: 0 cc: 0
+new: 1 cc: 2
+new: 1 cc: 2
+new: 2147483647 cc: 2
+new: 2147483648 cc: 2
+new: 4294967295 cc: 2
+new: 9223372036854775807 cc: 2
+new: -9223372036854775808 cc: 3
+new: 1 cc: 2
+lpgfr
+new: 0 cc: 0
+new: 1 cc: 2
+new: 1 cc: 2
+new: 2147483647 cc: 2
+new: 2147483648 cc: 2
+new: 1 cc: 2
+new: 1 cc: 2
+new: 0 cc: 0
+new: 1 cc: 2
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/lpr.vgtest
@@ -0,0 +1 @@
+prog: lpr
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/tcxb.c
@@ -0,0 +1,84 @@
+/* test data class tests for float, double, long double: TCEB, TCDB, TCXB */
+#include <math.h>
+#include <stdio.h>
+
+static int tcxb(long double f, long long num)
+{
+ int match;
+
+ asm volatile(" tcxb %1,0(%2)\n"
+ "ipm %0\n"
+ "srl %0,28\n"
+ : "=d" (match)
+ : "f" (f), "a" (num)
+ : "cc");
+ return match;
+}
+
+static int tcdb(double f, long long num)
+{
+ int match;
+
+ asm volatile(" tcdb %1,0(%2)\n"
+ "ipm %0\n"
+ "srl %0,28\n"
+ : "=d" (match)
+ : "f" (f), "a" (num)
+ : "cc");
+ return match;
+}
+
+static int tceb(float f, long long num)
+{
+ int match;
+
+ asm volatile(" tceb %1,0(%2)\n"
+ "ipm %0\n"
+ "srl %0,28\n"
+ : "=d" (match)
+ : "f" (f), "a" (num)
+ : "cc");
+ return match;
+}
+
+int main()
+{
+ int i;
+
+ for (i = 0; i < 64; i++) {
+ /* long double 128 bit */
+ printf("%d", tcxb(+0.0l, 1UL<<i));
+ printf("%d", tcxb(-0.0l, 1UL<<i));
+ printf("%d", tcxb(+2.2l, 1UL<<i));
+ printf("%d", tcxb(-2.2l, 1UL<<i));
+ printf("%d", tcxb(+INFINITY, 1UL<<i));
+ printf("%d", tcxb(-INFINITY, 1UL<<i));
+ printf("%d", tcxb(+NAN, 1UL<<i));
+ printf("%d", tcxb(-NAN, 1UL<<i));
+
+ /* double 64 bit */
+ printf("%d", tcdb(+0.0, 1UL<<i));
+ printf("%d", tcdb(-0.0, 1UL<<i));
+ printf("%d", tcdb(+2.2, 1UL<<i));
+ printf("%d", tcdb(-2.2, 1UL<<i));
+ printf("%d", tcdb(+INFINITY, 1UL<<i));
+ printf("%d", tcdb(-INFINITY, 1UL<<i));
+ printf("%d", tcdb(+NAN, 1UL<<i));
+ printf("%d", tcdb(-NAN, 1UL<<i));
+
+
+ /* float 32 bit */
+ printf("%d", tceb(+0.0f, 1UL<<i));
+ printf("%d", tceb(-0.0f, 1UL<<i));
+ printf("%d", tceb(+2.2f, 1UL<<i));
+ printf("%d", tceb(-2.2f, 1UL<<i));
+ printf("%d", tceb(+INFINITY, 1UL<<i));
+ printf("%d", tceb(-INFINITY, 1UL<<i));
+ printf("%d", tceb(+NAN, 1UL<<i));
+ printf("%d", tceb(-NAN, 1UL<<i));
+
+ printf("\n");
+
+ }
+ return 0;
+}
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/tcxb.stderr.exp
@@ -0,0 +1,2 @@
+
+
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/tcxb.stdout.exp
@@ -0,0 +1,64 @@
+000000000000000000000000
+000000000000000000000000
+000000010000000100000001
+000000100000001000000010
+000001000000010000000100
+000010000000100000001000
+000000000000000000000000
+000000000000000000000000
+000100000001000000010000
+001000000010000000100000
+010000000100000001000000
+100000001000000010000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
+000000000000000000000000
--- /dev/null
+++ valgrind-upstream/none/tests/s390x/tcxb.vgtest
@@ -0,0 +1 @@
+prog: tcxb
|
|
From: Christian B. <bor...@de...> - 2010-12-16 13:47:23
|
This patch adopts several testcases to work with s390x.
---
cachegrind/tests/filter_stderr | 4
callgrind/tests/filter_stderr | 3
exp-ptrcheck/tests/is_arch_supported | 6
helgrind/tests/annotate_hbefore.c | 19 ++
helgrind/tests/tc03_re_excl.c | 2
helgrind/tests/tc07_hbl1.c | 13 +
helgrind/tests/tc08_hbl2.c | 13 +
helgrind/tests/tc11_XCHG.c | 5
memcheck/tests/Makefile.am | 5
memcheck/tests/atomic_incs.c | 48 ++++++
memcheck/tests/badjump.stderr.exp-s390x | 25 +++
memcheck/tests/badjump2.stderr.exp-s390x | 6
memcheck/tests/linux/capget.c | 3
memcheck/tests/linux/capget.stderr.exp2 | 15 ++
memcheck/tests/linux/timerfd-syscall.c | 5
memcheck/tests/origin5-bz2.stderr.exp-glibc212-s390x | 133 +++++++++++++++++++
memcheck/tests/partiallydefinedeq.c | 7 +
memcheck/tests/partiallydefinedeq.stderr.exp3 | 20 ++
memcheck/tests/partiallydefinedeq.stderr.exp4 | 24 +++
memcheck/tests/sigaltstack.c | 10 +
memcheck/tests/sigprocmask.c | 1
memcheck/tests/supp_unknown.stderr.exp-s390x | 10 +
memcheck/tests/supp_unknown.supp | 7 +
none/tests/faultstatus.c | 9 +
tests/arch_test.c | 4
25 files changed, 386 insertions(+), 11 deletions(-)
--- valgrind-upstream.orig/cachegrind/tests/filter_stderr
+++ valgrind-upstream/cachegrind/tests/filter_stderr
@@ -18,4 +18,6 @@ sed "/warning: Pentium 4 with 12 KB micr
sed "/Simulating a 16 KB I-cache with 32 B lines/d" |
sed "/warning: L3 cache found, using its data for the LL simulation./d" |
sed "/Warning: Cannot auto-detect cache config on PPC.., using one or more defaults/d" |
-sed "/Warning: Cannot auto-detect cache config on ARM, using one or more defaults/d"
+sed "/Warning: Cannot auto-detect cache config on ARM, using one or more defaults/d" |
+sed "/Warning: Cannot auto-detect cache config on s390x, using one or more defaults/d"
+
--- valgrind-upstream.orig/callgrind/tests/filter_stderr
+++ valgrind-upstream/callgrind/tests/filter_stderr
@@ -27,4 +27,5 @@ sed "/warning: Pentium 4 with 12 KB micr
sed "/Simulating a 16 KB I-cache with 32 B lines/d" |
sed "/warning: L3 cache found, using its data for the LL simulation./d" |
sed "/Warning: Cannot auto-detect cache config on PPC.., using one or more defaults/d" |
-sed "/Warning: Cannot auto-detect cache config on ARM, using one or more defaults/d"
+sed "/Warning: Cannot auto-detect cache config on ARM, using one or more defaults/d" |
+sed "/Warning: Cannot auto-detect cache config on s390x, using one or more defaults/d"
--- valgrind-upstream.orig/exp-ptrcheck/tests/is_arch_supported
+++ valgrind-upstream/exp-ptrcheck/tests/is_arch_supported
@@ -1,7 +1,7 @@
#!/bin/sh
#
-# Not all architectures are supported by exp-ptr. Currently, PowerPC and ARM
-# are not supported and will fail these tests as follows:
+# Not all architectures are supported by exp-ptr. Currently, PowerPC, s390x
+# and ARM are not supported and will fail these tests as follows:
# WARNING: exp-ptrcheck on <blah> platforms: stack and global array
# WARNING: checking is not currently supported. Only heap checking is
# WARNING: supported.
@@ -10,6 +10,6 @@
# architectures.
case `uname -i` in
- ppc*|arm*) exit 1;;
+ ppc*|arm*|s390x) exit 1;;
*) exit 0;;
esac
--- valgrind-upstream.orig/helgrind/tests/annotate_hbefore.c
+++ valgrind-upstream/helgrind/tests/annotate_hbefore.c
@@ -167,6 +167,25 @@ UWord do_acasW ( UWord* addr, UWord expe
return success;
}
+#elif defined(VGA_s390x)
+
+// s390x
+/* return 1 if success, 0 if failure */
+UWord do_acasW(UWord* addr, UWord expected, UWord nyu )
+{
+ int cc;
+
+ __asm__ __volatile__ (
+ "csg %2,%3,%1\n\t"
+ "ipm %0\n\t"
+ "srl %0,28\n\t"
+ : /* out */ "=r" (cc)
+ : /* in */ "Q" (*addr), "d" (expected), "d" (nyu)
+ : "memory", "cc"
+ );
+ return cc == 0;
+}
+
#endif
void atomic_incW ( UWord* w )
--- valgrind-upstream.orig/helgrind/tests/tc03_re_excl.c
+++ valgrind-upstream/helgrind/tests/tc03_re_excl.c
@@ -10,7 +10,7 @@
/* A simple function to "use" a value, so that gcc can't
possibly optimise it into nothing. */
static void use ( int x ) {
- __asm__ __volatile__( "nop" : : "r"(x) : "cc","memory" );
+ __asm__ __volatile__( "" : : "r"(x) : "cc","memory" );
}
static void* worker_thread ( void* argV )
--- valgrind-upstream.orig/helgrind/tests/tc07_hbl1.c
+++ valgrind-upstream/helgrind/tests/tc07_hbl1.c
@@ -15,6 +15,7 @@
#undef PLAT_ppc32_linux
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
+#undef PLAT_s390x_linux
#if defined(_AIX) && defined(__64BIT__)
# define PLAT_ppc64_aix5 1
@@ -34,6 +35,8 @@
# define PLAT_ppc64_linux 1
#elif defined(__linux__) && defined(__arm__)
# define PLAT_arm_linux 1
+#elif defined(__linux__) && defined(__s390x__)
+# define PLAT_s390x_linux 1
#endif
#if defined(PLAT_amd64_linux) || defined(PLAT_x86_linux) \
@@ -65,6 +68,16 @@
: /*out*/ : /*in*/ "r"(&(_lval)) \
: /*trash*/ "r8", "r9", "cc", "memory" \
);
+#elif defined(PLAT_s390x_linux)
+# define INC(_lval,_lqual) \
+ __asm__ __volatile__( \
+ "1: l 0,%0\n" \
+ " lr 1,0\n" \
+ " ahi 1,1\n" \
+ " cs 0,1,%0\n" \
+ " jl 1b\n" \
+ : "+m" (_lval) :: "cc", "1","2" \
+ )
#else
# error "Fix Me for this platform"
#endif
--- valgrind-upstream.orig/helgrind/tests/tc08_hbl2.c
+++ valgrind-upstream/helgrind/tests/tc08_hbl2.c
@@ -31,6 +31,7 @@
#undef PLAT_ppc32_linux
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
+#undef PLAT_s390x_linux
#if defined(_AIX) && defined(__64BIT__)
# define PLAT_ppc64_aix5 1
@@ -50,6 +51,8 @@
# define PLAT_ppc64_linux 1
#elif defined(__linux__) && defined(__arm__)
# define PLAT_arm_linux 1
+#elif defined(__linux__) && defined(__s390x__)
+# define PLAT_s390x_linux 1
#endif
@@ -82,6 +85,16 @@
: /*out*/ : /*in*/ "r"(&(_lval)) \
: /*trash*/ "r8", "r9", "cc", "memory" \
);
+#elif defined(PLAT_s390x_linux)
+# define INC(_lval,_lqual) \
+ __asm__ __volatile__( \
+ "1: l 0,%0\n" \
+ " lr 1,0\n" \
+ " ahi 1,1\n" \
+ " cs 0,1,%0\n" \
+ " jl 1b\n" \
+ : "+m" (_lval) :: "cc", "0","1" \
+ )
#else
# error "Fix Me for this platform"
#endif
--- valgrind-upstream.orig/helgrind/tests/tc11_XCHG.c
+++ valgrind-upstream/helgrind/tests/tc11_XCHG.c
@@ -18,6 +18,7 @@
#undef PLAT_ppc32_linux
#undef PLAT_ppc64_linux
#undef PLAT_arm_linux
+#undef PLAT_s390x_linux
#if defined(_AIX) && defined(__64BIT__)
# define PLAT_ppc64_aix5 1
@@ -37,6 +38,8 @@
# define PLAT_ppc64_linux 1
#elif defined(__linux__) && defined(__arm__)
# define PLAT_arm_linux 1
+#elif defined(__linux__) && defined(__s390x__)
+# define PLAT_s390x_linux 1
#endif
@@ -59,7 +62,7 @@
#elif defined(PLAT_ppc32_linux) || defined(PLAT_ppc64_linux) \
|| defined(PLAT_ppc32_aix5) || defined(PLAT_ppc64_aix5) \
- || defined(PLAT_arm_linux)
+ || defined(PLAT_arm_linux) || defined(PLAT_s390x_linux)
# if defined(HAVE_BUILTIN_ATOMIC)
# define XCHG_M_R(_addr,_lval) \
do { \
--- valgrind-upstream.orig/memcheck/tests/Makefile.am
+++ valgrind-upstream/memcheck/tests/Makefile.am
@@ -295,8 +295,9 @@ origin4_many_CFLAGS = $(AM_CFLAGS) -O
origin5_bz2_CFLAGS = $(AM_CFLAGS) -O -Wno-inline
origin6_fp_CFLAGS = $(AM_CFLAGS) -O
-# Don't allow GCC to inline memcpy(), because then we can't intercept it
-overlap_CFLAGS = $(AM_CFLAGS) -fno-builtin-memcpy
+# Don't allow GCC to inline memcpy() and strcpy(),
+# because then we can't intercept it
+overlap_CFLAGS = $(AM_CFLAGS) -fno-builtin-memcpy -fno-builtin-strcpy
str_tester_CFLAGS = $(AM_CFLAGS) -Wno-shadow
--- valgrind-upstream.orig/memcheck/tests/atomic_incs.c
+++ valgrind-upstream/memcheck/tests/atomic_incs.c
@@ -76,6 +76,20 @@ __attribute__((noinline)) void atomic_ad
} while (success != 1);
#elif defined(VGA_arm)
*p += n;
+#elif defined(VGA_s390x)
+ int dummy;
+ __asm__ __volatile__(
+ " l 0,%0\n\t"
+ "0: st 0,%1\n\t"
+ " icm 1,1,%1\n\t"
+ " ar 1,%2\n\t"
+ " stcm 1,1,%1\n\t"
+ " l 1,%1\n\t"
+ " cs 0,1,%0\n\t"
+ " jl 0b\n\t"
+ : "+m" (*p), "+m" (dummy)
+ : "d" (n)
+ : "cc", "memory", "0", "1");
#else
# error "Unsupported arch"
#endif
@@ -140,6 +154,20 @@ __attribute__((noinline)) void atomic_ad
} while (success != 1);
#elif defined(VGA_arm)
*p += n;
+#elif defined(VGA_s390x)
+ int dummy;
+ __asm__ __volatile__(
+ " l 0,%0\n\t"
+ "0: st 0,%1\n\t"
+ " icm 1,3,%1\n\t"
+ " ar 1,%2\n\t"
+ " stcm 1,3,%1\n\t"
+ " l 1,%1\n\t"
+ " cs 0,1,%0\n\t"
+ " jl 0b\n\t"
+ : "+m" (*p), "+m" (dummy)
+ : "d" (n)
+ : "cc", "memory", "0", "1");
#else
# error "Unsupported arch"
#endif
@@ -216,6 +244,16 @@ __attribute__((noinline)) void atomic_ad
: /*trash*/ "memory", "cc", "r5", "r8", "r9", "r10"
);
} while (block[2] != 0);
+#elif defined(VGA_s390x)
+ __asm__ __volatile__(
+ " l 0,%0\n\t"
+ "0: lr 1,0\n\t"
+ " ar 1,%1\n\t"
+ " cs 0,1,%0\n\t"
+ " jl 0b\n\t"
+ : "+m" (*p)
+ : "d" (n)
+ : "cc", "memory", "0", "1");
#else
# error "Unsupported arch"
#endif
@@ -252,6 +290,16 @@ __attribute__((noinline)) void atomic_ad
: /*trash*/ "memory", "cc", "r15"
);
} while (success != 1);
+#elif defined(VGA_s390x)
+ __asm__ __volatile__(
+ " lg 0,%0\n\t"
+ "0: lgr 1,0\n\t"
+ " agr 1,%1\n\t"
+ " csg 0,1,%0\n\t"
+ " jl 0b\n\t"
+ : "+m" (*p)
+ : "d" (n)
+ : "cc", "memory", "0", "1");
#else
# error "Unsupported arch"
#endif
--- /dev/null
+++ valgrind-upstream/memcheck/tests/badjump.stderr.exp-s390x
@@ -0,0 +1,25 @@
+
+Jump to the invalid address stated on the next line
+ at 0x........: ???
+ by 0x........: main (badjump.c:17)
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
+
+Process terminating with default action of signal 11 (SIGSEGV)
+ Access not within mapped region at address 0x........
+ at 0x........: ???
+ by 0x........: main (badjump.c:17)
+ If you believe this happened as a result of a stack
+ overflow in your program's main thread (unlikely but
+ possible), you can try to increase the size of the
+ main thread stack using the --main-stacksize= flag.
+ The main thread stack size used in this run was ....
+
+HEAP SUMMARY:
+ in use at exit: ... bytes in ... blocks
+ total heap usage: ... allocs, ... frees, ... bytes allocated
+
+For a detailed leak analysis, rerun with: --leak-check=full
+
+For counts of detected and suppressed errors, rerun with: -v
+ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
--- /dev/null
+++ valgrind-upstream/memcheck/tests/badjump2.stderr.exp-s390x
@@ -0,0 +1,6 @@
+Jump to the invalid address stated on the next line
+ at 0x........: ???
+ by 0x........: main (badjump2.c:46)
+ Address 0x........ is not stack'd, malloc'd or (recently) free'd
+
+Signal caught, as expected
--- valgrind-upstream.orig/memcheck/tests/linux/capget.c
+++ valgrind-upstream/memcheck/tests/linux/capget.c
@@ -4,6 +4,7 @@
#include <stdio.h> /* printf() */
#include <unistd.h> /* syscall() */
#include <sys/syscall.h> /* __NR_capget */
+#include <sys/types.h> /* uid_t */
#include <linux/capability.h> /* _LINUX_CAPABILITY_VERSION */
@@ -13,6 +14,8 @@ int main()
struct __user_cap_data_struct d;
int syscall_result;
+ if (getuid() == 0)
+ fprintf(stderr, "Running as root\n");
h.version = _LINUX_CAPABILITY_VERSION;
h.pid = 0;
syscall_result = syscall(__NR_capget, &h, &d);
--- /dev/null
+++ valgrind-upstream/memcheck/tests/linux/capget.stderr.exp2
@@ -0,0 +1,15 @@
+
+Running as root
+capget result:
+effective 0x........
+permitted 0x........
+inheritable 0
+
+HEAP SUMMARY:
+ in use at exit: ... bytes in ... blocks
+ total heap usage: ... allocs, ... frees, ... bytes allocated
+
+For a detailed leak analysis, rerun with: --leak-check=full
+
+For counts of detected and suppressed errors, rerun with: -v
+ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
--- valgrind-upstream.orig/memcheck/tests/linux/timerfd-syscall.c
+++ valgrind-upstream/memcheck/tests/linux/timerfd-syscall.c
@@ -61,6 +61,8 @@
#define __NR_timerfd_create 322
#elif defined(__powerpc__)
#define __NR_timerfd_create 306
+#elif defined(__s390x__)
+#define __NR_timerfd_create 319
#else
#error Cannot detect your architecture!
#endif
@@ -76,6 +78,9 @@
#elif defined(__powerpc__)
#define __NR_timerfd_settime 311
#define __NR_timerfd_gettime 312
+#elif defined(__s390x__)
+#define __NR_timerfd_settime 320
+#define __NR_timerfd_gettime 321
#else
#error Cannot detect your architecture!
#endif
--- /dev/null
+++ valgrind-upstream/memcheck/tests/origin5-bz2.stderr.exp-glibc212-s390x
@@ -0,0 +1,133 @@
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: main (origin5-bz2.c:6481)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: handle_compress (origin5-bz2.c:4686)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: handle_compress (origin5-bz2.c:4686)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: handle_compress (origin5-bz2.c:4686)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: mainSort (origin5-bz2.c:2820)
+ by 0x........: BZ2_blockSort (origin5-bz2.c:3105)
+ by 0x........: BZ2_compressBlock (origin5-bz2.c:4034)
+ by 0x........: handle_compress (origin5-bz2.c:4753)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: mainSort (origin5-bz2.c:2823)
+ by 0x........: BZ2_blockSort (origin5-bz2.c:3105)
+ by 0x........: BZ2_compressBlock (origin5-bz2.c:4034)
+ by 0x........: handle_compress (origin5-bz2.c:4753)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: mainSort (origin5-bz2.c:2854)
+ by 0x........: BZ2_blockSort (origin5-bz2.c:3105)
+ by 0x........: BZ2_compressBlock (origin5-bz2.c:4034)
+ by 0x........: handle_compress (origin5-bz2.c:4753)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: mainSort (origin5-bz2.c:2858)
+ by 0x........: BZ2_blockSort (origin5-bz2.c:3105)
+ by 0x........: BZ2_compressBlock (origin5-bz2.c:4034)
+ by 0x........: handle_compress (origin5-bz2.c:4753)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: mainSort (origin5-bz2.c:2859)
+ by 0x........: BZ2_blockSort (origin5-bz2.c:3105)
+ by 0x........: BZ2_compressBlock (origin5-bz2.c:4034)
+ by 0x........: handle_compress (origin5-bz2.c:4753)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: mainSort (origin5-bz2.c:2963)
+ by 0x........: BZ2_blockSort (origin5-bz2.c:3105)
+ by 0x........: BZ2_compressBlock (origin5-bz2.c:4034)
+ by 0x........: handle_compress (origin5-bz2.c:4753)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: mainSort (origin5-bz2.c:2964)
+ by 0x........: BZ2_blockSort (origin5-bz2.c:3105)
+ by 0x........: BZ2_compressBlock (origin5-bz2.c:4034)
+ by 0x........: handle_compress (origin5-bz2.c:4753)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: fallbackSort (origin5-bz2.c:2269)
+ by 0x........: BZ2_blockSort (origin5-bz2.c:3116)
+ by 0x........: BZ2_compressBlock (origin5-bz2.c:4034)
+ by 0x........: handle_compress (origin5-bz2.c:4753)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Use of uninitialised value of size 8
+ at 0x........: fallbackSort (origin5-bz2.c:2275)
+ by 0x........: BZ2_blockSort (origin5-bz2.c:3116)
+ by 0x........: BZ2_compressBlock (origin5-bz2.c:4034)
+ by 0x........: handle_compress (origin5-bz2.c:4753)
+ by 0x........: BZ2_bzCompress (origin5-bz2.c:4822)
+ by 0x........: BZ2_bzBuffToBuffCompress (origin5-bz2.c:5630)
+ by 0x........: main (origin5-bz2.c:6484)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: main (origin5-bz2.c:6512)
+ Uninitialised value was created by a client request
+ at 0x........: main (origin5-bz2.c:6479)
+
--- valgrind-upstream.orig/memcheck/tests/partiallydefinedeq.c
+++ valgrind-upstream/memcheck/tests/partiallydefinedeq.c
@@ -64,9 +64,16 @@ int main ( void )
// and so never appears as a literal, and so the instrumenter
// never spots it and so doesn't use the expensive scheme (for foo).
// Hence also on ARM we get 3 errors, not 2.
+//
+// s390x is even more complicated: Depending on the architecture
+// level we have the 0x80808080 either in the literal pool (3 errors)
+// or with the extended immediate facility in an instruction (2 errors).
static __attribute__((noinline)) void bar ( void )
{
#if defined(__powerpc__) || defined(__powerpc64__) || defined(__arm__)
fprintf(stderr, "Currently running on ppc32/64/arm: this test should give 3 errors, not 2.\n");
#endif
+#if defined(__s390__)
+ fprintf(stderr, "On s390 we might see 2 or 3 errors.\n");
+#endif
}
--- /dev/null
+++ valgrind-upstream/memcheck/tests/partiallydefinedeq.stderr.exp3
@@ -0,0 +1,20 @@
+
+On s390 we might see 2 or 3 errors.
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: foo (partiallydefinedeq.c:15)
+ by 0x........: main (partiallydefinedeq.c:37)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: foo (partiallydefinedeq.c:15)
+ by 0x........: main (partiallydefinedeq.c:52)
+
+
+HEAP SUMMARY:
+ in use at exit: ... bytes in ... blocks
+ total heap usage: ... allocs, ... frees, ... bytes allocated
+
+For a detailed leak analysis, rerun with: --leak-check=full
+
+For counts of detected and suppressed errors, rerun with: -v
+Use --track-origins=yes to see where uninitialised values come from
+ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
--- /dev/null
+++ valgrind-upstream/memcheck/tests/partiallydefinedeq.stderr.exp4
@@ -0,0 +1,24 @@
+
+On s390 we might see 2 or 3 errors.
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: foo (partiallydefinedeq.c:15)
+ by 0x........: main (partiallydefinedeq.c:37)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: foo (partiallydefinedeq.c:15)
+ by 0x........: main (partiallydefinedeq.c:45)
+
+Conditional jump or move depends on uninitialised value(s)
+ at 0x........: foo (partiallydefinedeq.c:15)
+ by 0x........: main (partiallydefinedeq.c:52)
+
+
+HEAP SUMMARY:
+ in use at exit: ... bytes in ... blocks
+ total heap usage: ... allocs, ... frees, ... bytes allocated
+
+For a detailed leak analysis, rerun with: --leak-check=full
+
+For counts of detected and suppressed errors, rerun with: -v
+Use --track-origins=yes to see where uninitialised values come from
+ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
--- valgrind-upstream.orig/memcheck/tests/sigaltstack.c
+++ valgrind-upstream/memcheck/tests/sigaltstack.c
@@ -5,6 +5,14 @@
#include <signal.h>
#include "tests/sys_mman.h"
+#ifdef __s390x__
+/* on some glibc versions on s390x vprintf takes more that 10000 bytes */
+#define STACKSIZE SIGSTKSZ * 3
+#else
+#define STACKSIZE SIGSTKSZ * 2
+#endif
+
+
void sig_handler(int sig){
int var;
fprintf(stderr, "caught signal, local var is on %p\n", &var);
@@ -14,7 +22,7 @@ int main(int argv, char** argc) {
int res, i;
stack_t sigstk;
struct sigaction act;
- static const int size = SIGSTKSZ*2;
+ static const int size = STACKSIZE;
// We give EXEC permissions because this won't work on ppc32 unless you
// ask for an alt stack with EXEC permissions,
// since signal returning requires execution of code on the stack.
--- valgrind-upstream.orig/memcheck/tests/sigprocmask.c
+++ valgrind-upstream/memcheck/tests/sigprocmask.c
@@ -13,6 +13,7 @@ int main(void)
{
#if defined(__NR_sigprocmask) \
&& !defined(__powerpc64__) \
+ && !defined(__s390x__) \
&& !defined(_AIX) \
&& !defined(__arm__)
--- /dev/null
+++ valgrind-upstream/memcheck/tests/supp_unknown.stderr.exp-s390x
@@ -0,0 +1,10 @@
+
+Process terminating with default action of signal 11 (SIGSEGV)
+ Access not within mapped region at address 0x........
+ at 0x........: ???
+ by 0x........: main (badjump.c:17)
+ If you believe this happened as a result of a stack
+ overflow in your program's main thread (unlikely but
+ possible), you can try to increase the size of the
+ main thread stack using the --main-stacksize= flag.
+ The main thread stack size used in this run was ....
--- valgrind-upstream.orig/memcheck/tests/supp_unknown.supp
+++ valgrind-upstream/memcheck/tests/supp_unknown.supp
@@ -6,3 +6,10 @@
fun:(below main)
}
+{
+ <insert a suppression name here>
+ Memcheck:Jump
+ obj:*
+ fun:main
+}
+
--- valgrind-upstream.orig/none/tests/faultstatus.c
+++ valgrind-upstream/none/tests/faultstatus.c
@@ -70,7 +70,13 @@ static int testcode(int code, int want)
static int testaddr(void *addr, volatile void *want)
{
+ /* Some architectures (e.g. s390) just provide enough information to
+ resolve the page fault, but do not provide the offset within a page */
+#if defined(__s390__)
+ if (addr != (void *) ((unsigned long) want & ~0xffful)) {
+#else
if (addr != want) {
+#endif
fprintf(stderr, " FAIL: expected si_addr==%p, not %p\n", want, addr);
return 0;
}
@@ -132,7 +138,8 @@ int main()
for(i = 0; i < sizeof(sigs)/sizeof(*sigs); i++)
sigaction(sigs[i], &sa, NULL);
- fd = open("faultstatus.tmp", O_CREAT|O_TRUNC|O_EXCL, 0600);
+ /* we need O_RDWR for the truncate below */
+ fd = open("faultstatus.tmp", O_CREAT|O_TRUNC|O_EXCL|O_RDWR, 0600);
if (fd == -1) {
perror("tmpfile");
exit(1);
--- valgrind-upstream.orig/tests/arch_test.c
+++ valgrind-upstream/tests/arch_test.c
@@ -28,6 +28,7 @@ char* all_archs[] = {
"ppc32",
"ppc64",
"arm",
+ "s390x",
NULL
};
@@ -47,6 +48,9 @@ static Bool go(char* arch)
if ( 0 == strcmp( arch, "ppc64" ) ) return True;
if ( 0 == strcmp( arch, "ppc32" ) ) return True;
+#elif defined(VGP_s390x_linux)
+ if ( 0 == strcmp( arch, "s390x" ) ) return True;
+
#elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
if (sizeof(void*) == 8) {
/* CPU is in 64-bit mode */
|