/* Target-dependent code for GDB, the GNU debugger.
- Copyright (C) 2001-2013 Free Software Foundation, Inc.
+ Copyright (C) 2001-2014 Free Software Foundation, Inc.
Contributed by D.J. Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
for IBM Deutschland Entwicklung GmbH, IBM Corporation.
#include "arch-utils.h"
#include "frame.h"
#include "inferior.h"
+#include "infrun.h"
#include "symtab.h"
#include "target.h"
#include "gdbcore.h"
#include "linux-tdep.h"
#include "s390-linux-tdep.h"
#include "auxv.h"
+#include "xml-syscall.h"
#include "stap-probe.h"
#include "ax.h"
#include "features/s390x-linux64v2.c"
#include "features/s390x-te-linux64.c"
+#define XML_SYSCALL_FILENAME_S390 "syscalls/s390-linux.xml"
+#define XML_SYSCALL_FILENAME_S390X "syscalls/s390x-linux.xml"
+
/* The tdep structure. */
struct gdbarch_tdep
registers, even though we are otherwise a big-endian platform. */
static struct value *
-s390_value_from_register (struct type *type, int regnum,
- struct frame_info *frame)
+s390_value_from_register (struct gdbarch *gdbarch, struct type *type,
+ int regnum, struct frame_id frame_id)
{
- struct value *value = default_value_from_register (type, regnum, frame);
-
+ struct value *value = default_value_from_register (gdbarch, type,
+ regnum, frame_id);
check_typedef (type);
if (regnum >= S390_F0_REGNUM && regnum <= S390_F15_REGNUM
op1_brxhg= 0xec, op2_brxhg= 0x44,
op_brxle = 0x85,
op1_brxlg= 0xec, op2_brxlg= 0x45,
+ op_svc = 0x0a,
};
s390_frame_unwind_cache (struct frame_info *this_frame,
void **this_prologue_cache)
{
+ volatile struct gdb_exception ex;
struct s390_unwind_cache *info;
+
if (*this_prologue_cache)
return *this_prologue_cache;
info->frame_base = -1;
info->local_base = -1;
- /* Try to use prologue analysis to fill the unwind cache.
- If this fails, fall back to reading the stack backchain. */
- if (!s390_prologue_frame_unwind_cache (this_frame, info))
- s390_backchain_frame_unwind_cache (this_frame, info);
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
+ {
+ /* Try to use prologue analysis to fill the unwind cache.
+ If this fails, fall back to reading the stack backchain. */
+ if (!s390_prologue_frame_unwind_cache (this_frame, info))
+ s390_backchain_frame_unwind_cache (this_frame, info);
+ }
+ if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR)
+ throw_exception (ex);
return info;
}
if (target_read_memory (pc, sigreturn, 2))
return 0;
- if (sigreturn[0] != 0x0a /* svc */)
+ if (sigreturn[0] != op_svc)
return 0;
if (sigreturn[1] != 119 /* sigreturn */
s390_sigtramp_frame_sniffer
};
+/* Retrieve the syscall number at a ptrace syscall-stop. Return -1
+ upon error. */
+
+static LONGEST
+s390_linux_get_syscall_number (struct gdbarch *gdbarch,
+ ptid_t ptid)
+{
+ struct regcache *regs = get_thread_regcache (ptid);
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ ULONGEST pc;
+ ULONGEST svc_number = -1;
+ unsigned opcode;
+
+ /* Assume that the PC points after the 2-byte SVC instruction. We
+ don't currently support SVC via EXECUTE. */
+ regcache_cooked_read_unsigned (regs, tdep->pc_regnum, &pc);
+ pc -= 2;
+ opcode = read_memory_unsigned_integer ((CORE_ADDR) pc, 1, byte_order);
+ if (opcode != op_svc)
+ return -1;
+
+ svc_number = read_memory_unsigned_integer ((CORE_ADDR) pc + 1, 1,
+ byte_order);
+ if (svc_number == 0)
+ regcache_cooked_read_unsigned (regs, S390_R1_REGNUM, &svc_number);
+
+ return svc_number;
+}
+
/* Frame base handling. */
}
/* Otherwise create a new gdbarch for the specified machine type. */
- tdep = XCALLOC (1, struct gdbarch_tdep);
+ tdep = XCNEW (struct gdbarch_tdep);
tdep->abi = tdep_abi;
gdbarch = gdbarch_alloc (&info, tdep);
set_gdbarch_frame_align (gdbarch, s390_frame_align);
set_gdbarch_return_value (gdbarch, s390_return_value);
+ /* Syscall handling. */
+ set_gdbarch_get_syscall_number (gdbarch, s390_linux_get_syscall_number);
+
/* Frame handling. */
dwarf2_frame_set_init_reg (gdbarch, s390_dwarf2_frame_init_reg);
dwarf2_frame_set_adjust_regnum (gdbarch, s390_adjust_frame_regnum);
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ set_xml_syscall_file_name (XML_SYSCALL_FILENAME_S390);
+
if (have_upper)
{
if (have_linux_v2)
set_gdbarch_address_class_name_to_type_flags (gdbarch,
s390_address_class_name_to_type_flags);
+ set_xml_syscall_file_name (XML_SYSCALL_FILENAME_S390);
+
if (have_linux_v2)
set_gdbarch_core_regset_sections (gdbarch,
s390x_linux64v2_regset_sections);