Blame SOURCES/gdb-rhbz1247107-backport-aarch64-stap-sdt-support-2of2.patch

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