Hi Mark, jankratochvil/ynonx86base-attach-firstreg-ppc-s390
I have left ebl API extensions together with s390 and s390x all in one. Thanks, Jan unwinder: s390 and s390x backends/ 2013-11-10 Jan Kratochvil <[email protected]> unwinder: s390 and s390x * Makefile.am (s390_SRCS): Add s390_initreg.c and s390_unwind.c. * s390_init.c (s390_init): Initialize frame_nregs, core_pc_offset, set_initial_registers_tid, normalize_pc and unwind. * s390_initreg.c: New file. * s390_unwind.c: New file. libdwfl/ 2013-11-10 Jan Kratochvil <[email protected]> unwinder: s390 and s390x * dwfl_frame_pc.c (dwfl_frame_pc): Call ebl_normalize_pc. * frame_unwind.c (new_unwound): New function from ... (handle_cfi): ... here. Call it. Call also ebl_dwarf_to_regno. (setfunc, getfunc, readfunc): New functions. (__libdwfl_frame_unwind): Call ebl_unwind with those functions. libebl/ 2013-11-10 Jan Kratochvil <[email protected]> unwinder: s390 and s390x * Makefile.am (gen_SOURCES): Add eblnormalizepc.c and eblunwind.c. * ebl-hooks.h (normalize_pc, unwind): New. * eblnormalizepc.c: New file. * eblunwind.c: New file. * libebl.h (ebl_normalize_pc): New declaration. (ebl_tid_registers_get_t, ebl_pid_memory_read_t): New definitions. (ebl_unwind): New declaration. tests/ 2013-11-10 Jan Kratochvil <[email protected]> unwinder: s390 and s390x * Makefile.am (EXTRA_DIST): Add backtrace.s390.core.bz2, backtrace.s390.exec.bz2, backtrace.s390x.core.bz2 and backtrace.s390x.exec.bz2. * backtrace.s390.core.bz2: New file. * backtrace.s390.exec.bz2: New file. * backtrace.s390x.core.bz2: New file. * backtrace.s390x.exec.bz2: New file. * run-backtrace.sh: Test also s390 and s390x. Signed-off-by: Jan Kratochvil <[email protected]> --- a/backends/Makefile.am +++ b/backends/Makefile.am @@ -99,7 +99,8 @@ libebl_ppc64_pic_a_SOURCES = $(ppc64_SRCS) am_libebl_ppc64_pic_a_OBJECTS = $(ppc64_SRCS:.c=.os) s390_SRCS = s390_init.c s390_symbol.c s390_regs.c s390_retval.c \ - s390_corenote.c s390x_corenote.c s390_cfi.c + s390_corenote.c s390x_corenote.c s390_cfi.c s390_initreg.c \ + s390_unwind.c libebl_s390_pic_a_SOURCES = $(s390_SRCS) am_libebl_s390_pic_a_OBJECTS = $(s390_SRCS:.c=.os) --- a/backends/s390_init.c +++ b/backends/s390_init.c @@ -62,6 +62,16 @@ s390_init (elf, machine, eh, ehlen) else HOOK (eh, core_note); HOOK (eh, abi_cfi); + /* gcc/config/ #define DWARF_FRAME_REGISTERS 34. + But from the gcc/config/s390/s390.h "Register usage." comment it looks as + if #32 (Argument pointer) and #33 (Condition code) are not used for + unwinding. */ + eh->frame_nregs = 32; + eh->core_pc_offset = eh->class == ELFCLASS64 ? 0x78 : 0x4c; + HOOK (eh, set_initial_registers_tid); + if (eh->class == ELFCLASS32) + HOOK (eh, normalize_pc); + HOOK (eh, unwind); /* Only the 64-bit format uses the incorrect hash table entry size. */ if (eh->class == ELFCLASS64) --- /dev/null +++ b/backends/s390_initreg.c @@ -0,0 +1,92 @@ +/* Fetch live process registers from TID. + Copyright (C) 2013 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * 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 + + or both in parallel, as here. + + elfutils 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <assert.h> +#ifdef __s390__ +# include <sys/user.h> +# include <asm/ptrace.h> +# include <sys/ptrace.h> +#endif + +#define BACKEND s390_ +#include "libebl_CPU.h" + +bool +s390_set_initial_registers_tid (pid_t tid __attribute__ ((unused)), + ebl_tid_registers_t *setfunc __attribute__ ((unused)), + void *arg __attribute__ ((unused))) +{ +#ifndef __s390__ + return false; +#else /* __s390__ */ + struct user user_regs; + ptrace_area parea; + parea.process_addr = (uintptr_t) &user_regs; + parea.kernel_addr = 0; + parea.len = sizeof (user_regs); + if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea, NULL) != 0) + return false; + /* If we run as s390x we get the 64-bit registers of tid. + But -m31 executable seems to use only the 32-bit parts of its + registers so we ignore the upper half. */ + Dwarf_Word dwarf_regs[16]; + for (unsigned u = 0; u < 16; u++) + dwarf_regs[u] = user_regs.regs.gprs[u]); + return setfunc (0, 16, dwarf_regs, arg); + /* Avoid conversion double -> integer. */ + eu_static_assert (sizeof user_regs.regs.fp_regs.fprs[0] + == sizeof state->regs[0]); + for (unsigned u = 0; u < 16; u++) + dwarf_regs[u] = *((const __typeof (*state->regs) *) + &user_regs.regs.fp_regs.fprs[u])); + if (! setfunc (0, 16, dwarf_regs, arg)) + return false; + for (unsigned u = 0; u < 16; u++) + dwarf_frame_state_reg_set (state, 16 + u, + *((const __typeof (*state->regs) *) + &user_regs.regs.fp_regs.fprs[u])); + if (! setfunc (16, 16, dwarf_regs, arg)) + return false; + dwarf_regs[0] = user_regs.regs.psw.addr; + return setfunc (-1, 1, dwarf_regs, arg)) + return false; +#endif /* __s390__ */ +} + +void +s390_normalize_pc (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr *pc) +{ + assert (ebl->class == ELFCLASS32); + + /* Clear S390 bit 31. */ + *pc &= (1U << 31) - 1; +} --- /dev/null +++ b/backends/s390_unwind.c @@ -0,0 +1,133 @@ +/* Get previous frame state for an existing frame state. + Copyright (C) 2013 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * 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 + + or both in parallel, as here. + + elfutils 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <stdlib.h> +#include <assert.h> + +#define BACKEND s390_ +#include "libebl_CPU.h" + +bool +s390_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc, + ebl_tid_registers_get_t *getfunc, ebl_pid_memory_read_t *readfunc, + void *arg, bool *signal_framep) +{ + /* Caller already assumed caller adjustment but S390 instructions are 4 bytes + long. Undo it. */ + if ((pc & 0x3) != 0x3) + return false; + pc++; + /* We can assume big-endian read here. */ + Dwarf_Word instr; + if (! readfunc (pc, &instr, arg)) + return false; + /* Fetch only the very first two bytes. */ + instr = (instr >> (ebl->class == ELFCLASS64 ? 48 : 16)) & 0xffff; + /* See GDB s390_sigtramp_frame_sniffer. */ + /* Check for 'svc'. */ + if (((instr >> 8) & 0xff) != 0x0a) + return false; + /* Check for 'sigreturn' or 'rt_sigreturn'. */ + if ((instr & 0xff) != 119 && (instr & 0xff) != 173) + return false; + /* See GDB s390_sigtramp_frame_unwind_cache. */ +# define S390_SP_REGNUM (0 + 15) /* S390_R15_REGNUM */ + Dwarf_Word this_sp; + if (! getfunc (S390_SP_REGNUM, 1, &this_sp, arg)) + return false; + unsigned word_size = ebl->class == ELFCLASS64 ? 8 : 4; + Dwarf_Addr next_cfa = this_sp + 16 * word_size + 32; + /* "New-style RT frame" is not supported, + assuming "Old-style RT frame and all non-RT frames". */ + Dwarf_Word sigreg_ptr; + if (! readfunc (next_cfa + 8, &sigreg_ptr, arg)) + return false; + /* Skip PSW mask. */ + sigreg_ptr += word_size; + /* Read PSW address. */ + Dwarf_Word val; + if (! readfunc (sigreg_ptr, &val, arg)) + return false; + if (! setfunc (-1, 1, &val, arg)) + return false; + sigreg_ptr += word_size; + /* Then the GPRs. */ + Dwarf_Word gprs[16]; + for (int i = 0; i < 16; i++) + { + if (! readfunc (sigreg_ptr, &gprs[i], arg)) + return false; + sigreg_ptr += word_size; + } + /* Then the ACRs. Skip them, they are not used in CFI. */ + for (int i = 0; i < 16; i++) + sigreg_ptr += 4; + /* The floating-point control word. */ + sigreg_ptr += 8; + /* And finally the FPRs. */ + Dwarf_Word fprs[16]; + for (int i = 0; i < 16; i++) + { + if (! readfunc (sigreg_ptr, &val, arg)) + return false; + if (ebl->class == ELFCLASS32) + { + Dwarf_Addr val_low; + if (! readfunc (sigreg_ptr + 4, &val_low, arg)) + return false; + val = (val << 32) | val_low; + } + fprs[i] = val; + sigreg_ptr += 8; + } + /* If we have them, the GPR upper halves are appended at the end. */ + if (ebl->class == ELFCLASS32) + { + unsigned sigreg_high_off = 4; + sigreg_ptr += sigreg_high_off; + for (int i = 0; i < 16; i++) + { + if (! readfunc (sigreg_ptr, &val, arg)) + return false; + Dwarf_Word val_low = gprs[i]; + val = (val << 32) | val_low; + gprs[i] = val; + sigreg_ptr += 4; + } + } + if (! setfunc (0, 16, gprs, arg)) + return false; + if (! setfunc (16, 16, fprs, arg)) + return false; + *signal_framep = true; + return true; +} --- a/libdwfl/dwfl_frame_pc.c +++ b/libdwfl/dwfl_frame_pc.c @@ -37,6 +37,7 @@ dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation) { assert (state->pc_state == DWFL_FRAME_STATE_PC_SET); *pc = state->pc; + ebl_normalize_pc (state->thread->process->ebl, pc); if (isactivation) { /* Bottom frame? */ --- a/libdwfl/frame_unwind.c +++ b/libdwfl/frame_unwind.c @@ -494,6 +494,26 @@ expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops, return true; } +static void +new_unwound (Dwfl_Frame *state) +{ + assert (state->unwound == NULL); + Dwfl_Thread *thread = state->thread; + Dwfl_Process *process = thread->process; + Ebl *ebl = process->ebl; + size_t nregs = ebl_frame_nregs (ebl); + assert (nregs > 0); + Dwfl_Frame *unwound; + unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs); + state->unwound = unwound; + unwound->thread = thread; + unwound->unwound = NULL; + unwound->signal_frame = false; + unwound->initial_frame = false; + unwound->pc_state = DWFL_FRAME_STATE_ERROR; + memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); +} + /* The logic is to call __libdwfl_seterrno for any CFI bytecode interpretation error so one can easily catch the problem with a debugger. Still there are archs with invalid CFI for some registers where the registers are never used @@ -508,20 +528,14 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) __libdwfl_seterrno (DWFL_E_LIBDW); return; } + new_unwound (state); + Dwfl_Frame *unwound = state->unwound; + unwound->signal_frame = frame->fde->cie->signal_frame; Dwfl_Thread *thread = state->thread; Dwfl_Process *process = thread->process; Ebl *ebl = process->ebl; size_t nregs = ebl_frame_nregs (ebl); assert (nregs > 0); - Dwfl_Frame *unwound; - unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs); - state->unwound = unwound; - unwound->thread = thread; - unwound->unwound = NULL; - unwound->signal_frame = frame->fde->cie->signal_frame; - unwound->initial_frame = false; - unwound->pc_state = DWFL_FRAME_STATE_ERROR; - memset (unwound->regs_set, 0, sizeof (unwound->regs_set)); for (unsigned regno = 0; regno < nregs; regno++) { Dwarf_Op reg_ops_mem[3], *reg_ops; @@ -539,7 +553,7 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) { /* REGNO is undefined. */ unsigned ra = frame->fde->cie->return_address_register; - if (regno == ra) + if (ebl_dwarf_to_regno (ebl, &ra) && regno == ra) unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; continue; } @@ -582,6 +596,58 @@ handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias) } } +static bool +setfunc (int firstreg, unsigned nregs, const Dwarf_Word *regs, void *arg) +{ + Dwfl_Frame *state = arg; + Dwfl_Frame *unwound = state->unwound; + if (firstreg < 0) + { + assert (firstreg == -1); + assert (nregs > 0); + assert (unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED); + unwound->pc = *regs; + unwound->pc_state = DWFL_FRAME_STATE_PC_SET; + firstreg++; + nregs--; + regs++; + } + while (nregs--) + if (! __libdwfl_frame_reg_set (unwound, firstreg++, *regs++)) + return false; + return true; +} + +static bool +getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg) +{ + Dwfl_Frame *state = arg; + if (firstreg < 0) + { + assert (firstreg == -1); + assert (nregs > 0); + assert (state->pc_state == DWFL_FRAME_STATE_PC_SET); + *regs = state->pc; + firstreg++; + nregs--; + regs++; + } + while (nregs--) + if (! __libdwfl_frame_reg_get (state, firstreg++, regs++)) + return false; + return true; +} + +static bool +readfunc (Dwarf_Addr addr, Dwarf_Word *datap, void *arg) +{ + Dwfl_Frame *state = arg; + Dwfl_Thread *thread = state->thread; + Dwfl_Process *process = thread->process; + return process->callbacks->memory_read (process->dwfl, addr, datap, + process->callbacks_arg); +} + void internal_function __libdwfl_frame_unwind (Dwfl_Frame *state) @@ -618,4 +684,20 @@ __libdwfl_frame_unwind (Dwfl_Frame *state) return; } } + assert (state->unwound == NULL); + Dwfl_Thread *thread = state->thread; + Dwfl_Process *process = thread->process; + Ebl *ebl = process->ebl; + new_unwound (state); + state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED; + // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield. + bool signal_frame = false; + if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame)) + { + state->unwound->pc_state = DWFL_FRAME_STATE_ERROR; + // __libdwfl_seterrno has been called above. + return; + } + assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET); + state->unwound->signal_frame = signal_frame; } --- a/libebl/Makefile.am +++ b/libebl/Makefile.am @@ -54,7 +54,8 @@ gen_SOURCES = eblopenbackend.c eblclosebackend.c eblstrtab.c \ eblreginfo.c eblnonerelocp.c eblrelativerelocp.c \ eblsysvhashentrysize.c eblauxvinfo.c eblcheckobjattr.c \ ebl_check_special_section.c ebl_syscall_abi.c eblabicfi.c \ - eblstother.c eblinitreg.c eblgetsymbol.c ebldwarftoregno.c + eblstother.c eblinitreg.c eblgetsymbol.c ebldwarftoregno.c \ + eblnormalizepc.c eblunwind.c libebl_a_SOURCES = $(gen_SOURCES) --- a/libebl/ebl-hooks.h +++ b/libebl/ebl-hooks.h @@ -184,5 +184,21 @@ const char *EBLHOOK(get_symbol) (Ebl *ebl, size_t ndx, GElf_Sym *symp, Dwarf_Frame->REGS indexing. */ bool EBLHOOK(dwarf_to_regno) (Ebl *ebl, unsigned *regno); +/* Optionally modify *PC as fetched from inferior data into valid PC + instruction pointer. */ +void EBLHOOK(normalize_pc) (Ebl *ebl, Dwarf_Addr *pc); + +/* Get previous frame state for an existing frame state. PC is for the + existing frame. SETFUNC sets register in the previous frame. GETFUNC gets + register from the existing frame. Note that GETFUNC vs. SETFUNC act on + a disjunct set of registers. READFUNC reads memory. ARG has to be passed + for SETFUNC, GETFUNC and READFUNC. *SIGNAL_FRAMEP is initialized to false, + it can be set to true if existing frame is a signal frame. SIGNAL_FRAMEP is + never NULL. */ +bool EBLHOOK(unwind) (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc, + ebl_tid_registers_get_t *getfunc, + ebl_pid_memory_read_t *readfunc, void *arg, + bool *signal_framep); + /* Destructor for ELF backend handle. */ void EBLHOOK(destr) (struct ebl *); --- /dev/null +++ b/libebl/eblnormalizepc.c @@ -0,0 +1,40 @@ +/* Modify PC as fetched from inferior data into valid PC. + Copyright (C) 2013 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * 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 + + or both in parallel, as here. + + elfutils 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libeblP.h> + +void +ebl_normalize_pc (Ebl *ebl, Dwarf_Addr *pc) +{ + if (ebl != NULL && ebl->normalize_pc != NULL) + ebl->normalize_pc (ebl, pc); +} --- /dev/null +++ b/libebl/eblunwind.c @@ -0,0 +1,43 @@ +/* Get previous frame state for an existing frame state. + Copyright (C) 2013 Red Hat, Inc. + This file is part of elfutils. + + This file is free software; you can redistribute it and/or modify + it under the terms of either + + * the GNU Lesser General Public License as published by the Free + Software Foundation; either version 3 of the License, or (at + your option) any later version + + or + + * 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 + + or both in parallel, as here. + + elfutils 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 copies of the GNU General Public License and + the GNU Lesser General Public License along with this program. If + not, see <http://www.gnu.org/licenses/>. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +#include <libeblP.h> + +bool +ebl_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc, + ebl_tid_registers_get_t *getfunc, ebl_pid_memory_read_t *readfunc, + void *arg, bool *signal_framep) +{ + if (ebl == NULL || ebl->unwind == NULL) + return false; + return ebl->unwind (ebl, pc, setfunc, getfunc, readfunc, arg, signal_framep); +} --- a/libebl/libebl.h +++ b/libebl/libebl.h @@ -433,6 +433,33 @@ extern const char *ebl_get_symbol (Ebl *ebl, size_t ndx, GElf_Sym *symp, extern bool ebl_dwarf_to_regno (Ebl *ebl, unsigned *regno) __nonnull_attribute__ (1, 2); +/* Modify PC as fetched from inferior data into valid PC. */ +extern void ebl_normalize_pc (Ebl *ebl, Dwarf_Addr *pc) + __nonnull_attribute__ (1, 2); + +/* Callback type for FIXME. + Register -1 is mapped to PC (if arch PC has no DWARF number). */ +typedef bool (ebl_tid_registers_get_t) (int firstreg, unsigned nregs, + Dwarf_Word *regs, void *arg) + __nonnull_attribute__ (3); + +typedef bool (ebl_pid_memory_read_t) (Dwarf_Addr addr, Dwarf_Word *data, + void *arg) + __nonnull_attribute__ (3); + +/* Get previous frame state for an existing frame state. PC is for the + existing frame. SETFUNC sets register in the previous frame. GETFUNC gets + register from the existing frame. Note that GETFUNC vs. SETFUNC act on + a disjunct set of registers. READFUNC reads memory. ARG has to be passed + for SETFUNC, GETFUNC and READFUNC. *SIGNAL_FRAMEP is initialized to false, + it can be set to true if existing frame is a signal frame. SIGNAL_FRAMEP is + never NULL. */ +extern bool ebl_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc, + ebl_tid_registers_get_t *getfunc, + ebl_pid_memory_read_t *readfunc, void *arg, + bool *signal_framep) + __nonnull_attribute__ (1, 3, 4, 5, 7); + #ifdef __cplusplus } #endif --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -231,7 +231,9 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh \ testfile_implicit_value.c testfile_implicit_value.bz2 \ testfile66.bz2 run-backtrace.sh \ backtrace.ppc.core.bz2 backtrace.ppc.exec.bz2 \ - backtrace.ppc64.core.bz2 backtrace.ppc64.exec.bz2 + backtrace.ppc64.core.bz2 backtrace.ppc64.exec.bz2 \ + backtrace.s390.core.bz2 backtrace.s390.exec.bz2 \ + backtrace.s390x.core.bz2 backtrace.s390x.exec.bz2 if USE_VALGRIND valgrind_cmd='valgrind -q --trace-children=yes --error-exitcode=1 --run-libc-freeres=no' Binary files /dev/null and b/tests/backtrace.s390.core.bz2 differ Binary files /dev/null and b/tests/backtrace.s390.exec.bz2 differ Binary files /dev/null and b/tests/backtrace.s390x.core.bz2 differ Binary files /dev/null and b/tests/backtrace.s390x.exec.bz2 differ --- a/tests/run-backtrace.sh +++ b/tests/run-backtrace.sh @@ -91,7 +91,7 @@ for child in backtrace-child{,-biarch}; do done -for arch in ppc ppc64; do +for arch in ppc ppc64 s390 s390x; do testfiles backtrace.$arch.{exec,core} tempfiles backtrace.$arch.{bt,err} echo ./backtrace ./backtrace.$arch.{exec,core}
