You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
213 lines
6.6 KiB
213 lines
6.6 KiB
commit 08248ca9fe11040e9a4126cefebc5023d1d67222 |
|
Author: Sergio Durigan Junior <sergiodj@redhat.com> |
|
Date: Sat Dec 28 14:14:11 2013 -0200 |
|
|
|
Implement SystemTap SDT probe support for AArch64 |
|
|
|
This commit implements the needed bits for SystemTap SDT probe support |
|
on AArch64 architectures. |
|
|
|
First, I started by looking at AArch64 assembly specification and |
|
filling the necessary options on gdbarch's stap machinery in order to |
|
make the generic asm parser (implemented in stap-probe.c) recognize |
|
AArch64's asm. |
|
|
|
After my last patch for the SystemTap SDT API, which extends it in order |
|
to accept multiple prefixes and suffixes, this patch became simpler. I |
|
also followed Marcus suggestion and did not shared code between 32- and |
|
64-bit ARM. |
|
|
|
Tom asked me in a previous message how I did my tests. I believe I |
|
replied that, but just in case: I ran the tests on |
|
gdb.base/stap-probe.exp by hand. I also managed to run the tests on |
|
real hardware, and they pass without regressions. |
|
|
|
2013-12-28 Sergio Durigan Junior <sergiodj@redhat.com> |
|
|
|
PR tdep/15653 |
|
* NEWS: Mention SystemTap SDT probe support for AArch64 GNU/Linux. |
|
* aarch64-linux-tdep.c: Include necessary headers for parsing of |
|
SystemTap SDT probes. |
|
(aarch64_stap_is_single_operand): New function. |
|
(aarch64_stap_parse_special_token): Likewise. |
|
(aarch64_linux_init_abi): Declare SystemTap SDT probe argument |
|
prefixes and suffixes. Initialize gdbarch with them. |
|
|
|
Index: gdb-7.6.1/gdb/NEWS |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/NEWS |
|
+++ gdb-7.6.1/gdb/NEWS |
|
@@ -30,6 +30,8 @@ qXfer:libraries-svr4:read's annex |
|
|
|
*** Changes in GDB 7.6 |
|
|
|
+* GDB now supports SystemTap SDT probes on AArch64 GNU/Linux. |
|
+ |
|
* Target record has been renamed to record-full. |
|
Record/replay is now enabled with the "record full" command. |
|
This also affects settings that are associated with full record/replay |
|
Index: gdb-7.6.1/gdb/aarch64-linux-tdep.c |
|
=================================================================== |
|
--- gdb-7.6.1.orig/gdb/aarch64-linux-tdep.c |
|
+++ gdb-7.6.1/gdb/aarch64-linux-tdep.c |
|
@@ -35,6 +35,12 @@ |
|
#include "regcache.h" |
|
#include "regset.h" |
|
|
|
+#include "cli/cli-utils.h" |
|
+#include "stap-probe.h" |
|
+#include "parser-defs.h" |
|
+#include "user-regs.h" |
|
+#include <ctype.h> |
|
+ |
|
/* The general-purpose regset consists of 31 X registers, plus SP, PC, |
|
and PSTATE registers, as defined in the AArch64 port of the Linux |
|
kernel. */ |
|
@@ -268,9 +274,129 @@ aarch64_linux_regset_from_core_section ( |
|
return NULL; |
|
} |
|
|
|
+/* Implementation of `gdbarch_stap_is_single_operand', as defined in |
|
+ gdbarch.h. */ |
|
+ |
|
+static int |
|
+aarch64_stap_is_single_operand (struct gdbarch *gdbarch, const char *s) |
|
+{ |
|
+ return (*s == '#' || isdigit (*s) /* Literal number. */ |
|
+ || *s == '[' /* Register indirection. */ |
|
+ || isalpha (*s)); /* Register value. */ |
|
+} |
|
+ |
|
+/* This routine is used to parse a special token in AArch64's assembly. |
|
+ |
|
+ The special tokens parsed by it are: |
|
+ |
|
+ - Register displacement (e.g, [fp, #-8]) |
|
+ |
|
+ It returns one if the special token has been parsed successfully, |
|
+ or zero if the current token is not considered special. */ |
|
+ |
|
+static int |
|
+aarch64_stap_parse_special_token (struct gdbarch *gdbarch, |
|
+ struct stap_parse_info *p) |
|
+{ |
|
+ if (*p->arg == '[') |
|
+ { |
|
+ /* Temporary holder for lookahead. */ |
|
+ const char *tmp = p->arg; |
|
+ char *endp; |
|
+ /* Used to save the register name. */ |
|
+ const char *start; |
|
+ char *regname; |
|
+ int len; |
|
+ int got_minus = 0; |
|
+ long displacement; |
|
+ struct stoken str; |
|
+ |
|
+ ++tmp; |
|
+ start = tmp; |
|
+ |
|
+ /* Register name. */ |
|
+ while (isalnum (*tmp)) |
|
+ ++tmp; |
|
+ |
|
+ if (*tmp != ',') |
|
+ return 0; |
|
+ |
|
+ len = tmp - start; |
|
+ regname = alloca (len + 2); |
|
+ |
|
+ strncpy (regname, start, len); |
|
+ regname[len] = '\0'; |
|
+ |
|
+ if (user_reg_map_name_to_regnum (gdbarch, regname, len) == -1) |
|
+ error (_("Invalid register name `%s' on expression `%s'."), |
|
+ regname, p->saved_arg); |
|
+ |
|
+ ++tmp; |
|
+ tmp = skip_spaces_const (tmp); |
|
+ /* Now we expect a number. It can begin with '#' or simply |
|
+ a digit. */ |
|
+ if (*tmp == '#') |
|
+ ++tmp; |
|
+ |
|
+ if (*tmp == '-') |
|
+ { |
|
+ ++tmp; |
|
+ got_minus = 1; |
|
+ } |
|
+ else if (*tmp == '+') |
|
+ ++tmp; |
|
+ |
|
+ if (!isdigit (*tmp)) |
|
+ return 0; |
|
+ |
|
+ displacement = strtol (tmp, &endp, 10); |
|
+ tmp = endp; |
|
+ |
|
+ /* Skipping last `]'. */ |
|
+ if (*tmp++ != ']') |
|
+ return 0; |
|
+ |
|
+ /* The displacement. */ |
|
+ write_exp_elt_opcode (OP_LONG); |
|
+ write_exp_elt_type (builtin_type (gdbarch)->builtin_long); |
|
+ write_exp_elt_longcst (displacement); |
|
+ write_exp_elt_opcode (OP_LONG); |
|
+ if (got_minus) |
|
+ write_exp_elt_opcode (UNOP_NEG); |
|
+ |
|
+ /* The register name. */ |
|
+ write_exp_elt_opcode (OP_REGISTER); |
|
+ str.ptr = regname; |
|
+ str.length = len; |
|
+ write_exp_string (str); |
|
+ write_exp_elt_opcode (OP_REGISTER); |
|
+ |
|
+ write_exp_elt_opcode (BINOP_ADD); |
|
+ |
|
+ /* Casting to the expected type. */ |
|
+ write_exp_elt_opcode (UNOP_CAST); |
|
+ write_exp_elt_type (lookup_pointer_type (p->arg_type)); |
|
+ write_exp_elt_opcode (UNOP_CAST); |
|
+ |
|
+ write_exp_elt_opcode (UNOP_IND); |
|
+ |
|
+ p->arg = tmp; |
|
+ } |
|
+ else |
|
+ return 0; |
|
+ |
|
+ return 1; |
|
+} |
|
+ |
|
static void |
|
aarch64_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
|
{ |
|
+ static const char *const stap_integer_prefixes[] = { "#", "", NULL }; |
|
+ static const char *const stap_register_prefixes[] = { "", NULL }; |
|
+ static const char *const stap_register_indirection_prefixes[] = { "[", |
|
+ NULL }; |
|
+ static const char *const stap_register_indirection_suffixes[] = { "]", |
|
+ NULL }; |
|
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
|
|
|
tdep->lowest_pc = 0x8000; |
|
@@ -295,6 +421,17 @@ aarch64_linux_init_abi (struct gdbarch_i |
|
|
|
set_gdbarch_regset_from_core_section (gdbarch, |
|
aarch64_linux_regset_from_core_section); |
|
+ |
|
+ /* SystemTap related. */ |
|
+ set_gdbarch_stap_integer_prefixes (gdbarch, stap_integer_prefixes); |
|
+ set_gdbarch_stap_register_prefixes (gdbarch, stap_register_prefixes); |
|
+ set_gdbarch_stap_register_indirection_prefixes (gdbarch, |
|
+ stap_register_indirection_prefixes); |
|
+ set_gdbarch_stap_register_indirection_suffixes (gdbarch, |
|
+ stap_register_indirection_suffixes); |
|
+ set_gdbarch_stap_is_single_operand (gdbarch, aarch64_stap_is_single_operand); |
|
+ set_gdbarch_stap_parse_special_token (gdbarch, |
|
+ aarch64_stap_parse_special_token); |
|
} |
|
|
|
/* Provide a prototype to silence -Wmissing-prototypes. */
|
|
|