From f68f11b76de09dcb0d399814127fbf5227fe8245 Mon Sep 17 00:00:00 2001 From: Yao Qi Date: Wed, 18 Mar 2015 10:47:45 +0000 Subject: [PATCH] Support catch syscall on aarch64 linux Hi, This patch is to support catch syscall on aarch64 linux. We implement gdbarch method get_syscall_number for aarch64-linux, and add aarch64-linux.xml file, which looks straightforward, however the changes to test case doesn't. First of all, we enable catch-syscall.exp on aarch64-linux target, but skip the multi_arch testing on current stage. I plan to touch multi arch debugging on aarch64-linux later. Then, when I run catch-syscall.exp on aarch64-linux, gcc errors that SYS_pipe isn't defined. We find that aarch64 kernel only has pipe2 syscall and libc already convert pipe to pipe2. As a result, I change catch-syscall.c to use SYS_pipe if it is defined, otherwise use SYS_pipe2 instead. The vector all_syscalls in catch-syscall.exp can't be pre-determined, so I add a new proc setup_all_syscalls to fill it, according to the availability of SYS_pipe. Regression tested on {x86_64, aarch64}-linux x {native, gdbserver}. gdb: 2015-03-18 Yao Qi PR tdep/18107 * aarch64-linux-tdep.c: Include xml-syscall.h (aarch64_linux_get_syscall_number): New function. (aarch64_linux_init_abi): Call set_gdbarch_get_syscall_number. * syscalls/aarch64-linux.xml: New file. gdb/testsuite: 2015-03-18 Yao Qi PR tdep/18107 * gdb.base/catch-syscall.c [!SYS_pipe] (pipe2_syscall): New variable. * gdb.base/catch-syscall.exp: Don't skip it on aarch64*-*-linux* target. Remove elements in all_syscalls. (test_catch_syscall_multi_arch): Skip it on aarch64*-linux* target. (setup_all_syscalls): New proc. --- gdb/ChangeLog | 9 + gdb/aarch64-linux-tdep.c | 27 +++ gdb/syscalls/aarch64-linux.xml | 271 +++++++++++++++++++++++ gdb/testsuite/ChangeLog | 11 + gdb/testsuite/gdb.base/catch-syscall.c | 4 + gdb/testsuite/gdb.base/catch-syscall.exp | 41 +++- 6 files changed, 359 insertions(+), 4 deletions(-) create mode 100644 gdb/syscalls/aarch64-linux.xml diff --git a/gdb/ChangeLog b/gdb/ChangeLog index ca8bbaf4efb..9578a9e7da6 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2015-03-11 Yao Qi + + PR tdep/18107 + * aarch64-linux-tdep.c: Include xml-syscall.h + (aarch64_linux_get_syscall_number): New function. + (aarch64_linux_init_abi): Call + set_gdbarch_get_syscall_number. + * syscalls/aarch64-linux.xml: New file. + 2015-03-17 Yurij Grechishhev * ser-base.h (ser_base_setstopbits): Change second argument name diff --git a/gdb/aarch64-linux-tdep.c b/gdb/aarch64-linux-tdep.c index 1e1ca366e34..0ee5ecbeb21 100644 --- a/gdb/aarch64-linux-tdep.c +++ b/gdb/aarch64-linux-tdep.c @@ -39,6 +39,7 @@ #include "stap-probe.h" #include "parser-defs.h" #include "user-regs.h" +#include "xml-syscall.h" #include /* Signal frame handling. @@ -341,6 +342,28 @@ aarch64_stap_parse_special_token (struct gdbarch *gdbarch, return 1; } +/* Implement the "get_syscall_number" gdbarch method. */ + +static LONGEST +aarch64_linux_get_syscall_number (struct gdbarch *gdbarch, + ptid_t ptid) +{ + struct regcache *regs = get_thread_regcache (ptid); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + + /* The content of register x8. */ + gdb_byte buf[X_REGISTER_SIZE]; + /* The result. */ + LONGEST ret; + + /* Getting the system call number from the register x8. */ + regcache_cooked_read (regs, AARCH64_DWARF_X0 + 8, buf); + + ret = extract_signed_integer (buf, X_REGISTER_SIZE, byte_order); + + return ret; +} + static void aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -385,6 +408,10 @@ aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand); set_gdbarch_stap_parse_special_token (gdbarch, aarch64_stap_parse_special_token); + + /* `catch syscall' */ + set_xml_syscall_file_name (gdbarch, "syscalls/aarch64-linux.xml"); + set_gdbarch_get_syscall_number (gdbarch, aarch64_linux_get_syscall_number); } /* Provide a prototype to silence -Wmissing-prototypes. */ diff --git a/gdb/syscalls/aarch64-linux.xml b/gdb/syscalls/aarch64-linux.xml new file mode 100644 index 00000000000..537d7891c94 --- /dev/null +++ b/gdb/syscalls/aarch64-linux.xml @@ -0,0 +1,271 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index c182e7cd574..a2cf7effa07 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,14 @@ +2015-03-18 Yao Qi + + PR tdep/18107 + * gdb.base/catch-syscall.c [!SYS_pipe] (pipe2_syscall): New + variable. + * gdb.base/catch-syscall.exp: Don't skip it on + aarch64*-*-linux* target. Remove elements in all_syscalls. + (test_catch_syscall_multi_arch): Skip it on aarch64*-linux* + target. + (setup_all_syscalls): New proc. + 2015-03-16 Yao Qi * gdb.base/watchpoint-reuse-slot.exp (valid_addr_p): New proc. diff --git a/gdb/testsuite/gdb.base/catch-syscall.c b/gdb/testsuite/gdb.base/catch-syscall.c index ea33b938391..4d0131c0d73 100644 --- a/gdb/testsuite/gdb.base/catch-syscall.c +++ b/gdb/testsuite/gdb.base/catch-syscall.c @@ -21,7 +21,11 @@ int chroot_syscall = SYS_chroot; restart_syscall, which can't be called from userspace. However, the "read" syscall is zero on x86_64. */ int read_syscall = SYS_read; +#ifdef SYS_pipe int pipe_syscall = SYS_pipe; +#else +int pipe2_syscall = SYS_pipe2; +#endif int write_syscall = SYS_write; int exit_group_syscall = SYS_exit_group; diff --git a/gdb/testsuite/gdb.base/catch-syscall.exp b/gdb/testsuite/gdb.base/catch-syscall.exp index 29e8109a3c6..df0004a2d3c 100644 --- a/gdb/testsuite/gdb.base/catch-syscall.exp +++ b/gdb/testsuite/gdb.base/catch-syscall.exp @@ -29,7 +29,7 @@ if { ![istarget "x86_64-*-linux*"] && ![istarget "i\[34567\]86-*-linux*"] && ![istarget "powerpc-*-linux*"] && ![istarget "powerpc64-*-linux*"] && ![istarget "sparc-*-linux*"] && ![istarget "sparc64-*-linux*"] && ![istarget "mips*-linux*"] && ![istarget "arm*-linux*"] - && ![istarget "s390*-linux*"] } { + && ![istarget "s390*-linux*"] && ![istarget "aarch64*-*-linux*"] } { continue } @@ -40,9 +40,9 @@ if { [prepare_for_testing ${testfile}.exp $testfile ${testfile}.c] } { return -1 } -# All (but the last) syscalls from the example code -# They are ordered according to the file, so do not change this. -set all_syscalls { "close" "chroot" "pipe" "write" "read" } +# All (but the last) syscalls from the example code. It is filled in +# proc setup_all_syscalls. +set all_syscalls { } set all_syscalls_numbers { } # The last syscall (exit()) does not return, so @@ -402,6 +402,9 @@ proc test_catch_syscall_multi_arch {} { # catch syscall supports only 32-bit ARM for now. verbose "Not testing ARM for multi-arch syscall support" return + } elseif { [istarget "aarch64*-linux*"] } { + verbose "Not testing AARCH64 for multi-arch syscall support" + return } elseif { [istarget "s390*-linux*"] } { set arch1 "s390:31-bit" set arch2 "s390:64-bit" @@ -469,6 +472,36 @@ proc fill_all_syscalls_numbers {} { set last_syscall_number [get_integer_valueof "exit_group_syscall" -1] } +# Set up the vector all_syscalls. + +proc setup_all_syscalls {} { + global all_syscalls + global gdb_prompt + + # They are ordered according to the file, so do not change this. + lappend all_syscalls "close" + lappend all_syscalls "chroot" + + # SYS_pipe doesn't exist on aarch64 kernel. + set test "check SYS_pipe" + gdb_test_multiple "p pipe_syscall" $test { + -re " = .*$gdb_prompt $" { + pass $test + lappend all_syscalls "pipe" + } + -re "No symbol .*$gdb_prompt $" { + pass $test + # SYS_pipe isn't defined, use SYS_pipe2 instead. + lappend all_syscalls "pipe2" + } + } + + lappend all_syscalls "write" + lappend all_syscalls "read" +} + +setup_all_syscalls + # Fill all the syscalls numbers before starting anything. fill_all_syscalls_numbers -- 2.30.2