Index: gdb/arm-linux-tdep.c |
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c |
index f4eaa5cc422e84a8799f64bbf4ee94b044057481..9deed1084e46e589616c2fc3ffaa11a7b83a1c63 100644 |
--- a/gdb/arm-linux-tdep.c |
+++ b/gdb/arm-linux-tdep.c |
@@ -1,6 +1,6 @@ |
/* GNU/Linux on ARM target support. |
- Copyright (C) 1999-2012 Free Software Foundation, Inc. |
+ Copyright (C) 1999-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -33,6 +33,7 @@ |
#include "tramp-frame.h" |
#include "breakpoint.h" |
#include "auxv.h" |
+#include "xml-syscall.h" |
#include "arm-tdep.h" |
#include "arm-linux-tdep.h" |
@@ -48,11 +49,8 @@ |
#include "parser-defs.h" |
#include "user-regs.h" |
#include <ctype.h> |
- |
-#include "gdb_string.h" |
- |
-/* This is defined in <elf.h> on ARM GNU/Linux systems. */ |
-#define AT_HWCAP 16 |
+#include "elf/common.h" |
+#include <string.h> |
extern int arm_apcs_32; |
@@ -62,9 +60,9 @@ extern int arm_apcs_32; |
of the software interrupt the kernel stops the inferior with a |
SIGTRAP, and wakes the debugger. */ |
-static const char arm_linux_arm_le_breakpoint[] = { 0x01, 0x00, 0x9f, 0xef }; |
+static const gdb_byte arm_linux_arm_le_breakpoint[] = { 0x01, 0x00, 0x9f, 0xef }; |
-static const char arm_linux_arm_be_breakpoint[] = { 0xef, 0x9f, 0x00, 0x01 }; |
+static const gdb_byte arm_linux_arm_be_breakpoint[] = { 0xef, 0x9f, 0x00, 0x01 }; |
/* However, the EABI syscall interface (new in Nov. 2005) does not look at |
the operand of the swi if old-ABI compatibility is disabled. Therefore, |
@@ -72,24 +70,24 @@ static const char arm_linux_arm_be_breakpoint[] = { 0xef, 0x9f, 0x00, 0x01 }; |
version 2.5.70 (May 2003), so should be a safe assumption for EABI |
binaries. */ |
-static const char eabi_linux_arm_le_breakpoint[] = { 0xf0, 0x01, 0xf0, 0xe7 }; |
+static const gdb_byte eabi_linux_arm_le_breakpoint[] = { 0xf0, 0x01, 0xf0, 0xe7 }; |
-static const char eabi_linux_arm_be_breakpoint[] = { 0xe7, 0xf0, 0x01, 0xf0 }; |
+static const gdb_byte eabi_linux_arm_be_breakpoint[] = { 0xe7, 0xf0, 0x01, 0xf0 }; |
/* All the kernels which support Thumb support using a specific undefined |
instruction for the Thumb breakpoint. */ |
-static const char arm_linux_thumb_be_breakpoint[] = {0xde, 0x01}; |
+static const gdb_byte arm_linux_thumb_be_breakpoint[] = {0xde, 0x01}; |
-static const char arm_linux_thumb_le_breakpoint[] = {0x01, 0xde}; |
+static const gdb_byte arm_linux_thumb_le_breakpoint[] = {0x01, 0xde}; |
/* Because the 16-bit Thumb breakpoint is affected by Thumb-2 IT blocks, |
we must use a length-appropriate breakpoint for 32-bit Thumb |
instructions. See also thumb_get_next_pc. */ |
-static const char arm_linux_thumb2_be_breakpoint[] = { 0xf7, 0xf0, 0xa0, 0x00 }; |
+static const gdb_byte arm_linux_thumb2_be_breakpoint[] = { 0xf7, 0xf0, 0xa0, 0x00 }; |
-static const char arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa0 }; |
+static const gdb_byte arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa0 }; |
/* Description of the longjmp buffer. The buffer is treated as an array of |
elements of size ARM_LINUX_JB_ELEMENT_SIZE. |
@@ -794,6 +792,59 @@ arm_linux_sigreturn_return_addr (struct frame_info *frame, |
return 0; |
} |
+/* At a ptrace syscall-stop, return the syscall number. This either |
+ comes from the SWI instruction (OABI) or from r7 (EABI). |
+ |
+ When the function fails, it should return -1. */ |
+ |
+static LONGEST |
+arm_linux_get_syscall_number (struct gdbarch *gdbarch, |
+ ptid_t ptid) |
+{ |
+ struct regcache *regs = get_thread_regcache (ptid); |
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
+ |
+ ULONGEST pc; |
+ ULONGEST cpsr; |
+ ULONGEST t_bit = arm_psr_thumb_bit (gdbarch); |
+ int is_thumb; |
+ ULONGEST svc_number = -1; |
+ |
+ regcache_cooked_read_unsigned (regs, ARM_PC_REGNUM, &pc); |
+ regcache_cooked_read_unsigned (regs, ARM_PS_REGNUM, &cpsr); |
+ is_thumb = (cpsr & t_bit) != 0; |
+ |
+ if (is_thumb) |
+ { |
+ regcache_cooked_read_unsigned (regs, 7, &svc_number); |
+ } |
+ else |
+ { |
+ enum bfd_endian byte_order_for_code = |
+ gdbarch_byte_order_for_code (gdbarch); |
+ |
+ /* PC gets incremented before the syscall-stop, so read the |
+ previous instruction. */ |
+ unsigned long this_instr = |
+ read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code); |
+ |
+ unsigned long svc_operand = (0x00ffffff & this_instr); |
+ |
+ if (svc_operand) |
+ { |
+ /* OABI */ |
+ svc_number = svc_operand - 0x900000; |
+ } |
+ else |
+ { |
+ /* EABI */ |
+ regcache_cooked_read_unsigned (regs, 7, &svc_number); |
+ } |
+ } |
+ |
+ return svc_number; |
+} |
+ |
/* When FRAME is at a syscall instruction, return the PC of the next |
instruction to be executed. */ |
@@ -1088,6 +1139,7 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch, |
{ |
/* Temporary holder for lookahead. */ |
const char *tmp = p->arg; |
+ char *endp; |
/* Used to save the register name. */ |
const char *start; |
char *regname; |
@@ -1140,7 +1192,8 @@ arm_stap_parse_special_token (struct gdbarch *gdbarch, |
got_minus = 1; |
} |
- displacement = strtol (tmp, (char **) &tmp, 10); |
+ displacement = strtol (tmp, &endp, 10); |
+ tmp = endp; |
/* Skipping last `]'. */ |
if (*tmp++ != ']') |
@@ -1292,6 +1345,10 @@ arm_linux_init_abi (struct gdbarch_info info, |
tdep->syscall_next_pc = arm_linux_syscall_next_pc; |
+ /* `catch syscall' */ |
+ set_xml_syscall_file_name ("syscalls/arm-linux.xml"); |
+ set_gdbarch_get_syscall_number (gdbarch, arm_linux_get_syscall_number); |
+ |
/* Syscall record. */ |
tdep->arm_swi_record = NULL; |
} |