Explicit locations: introduce address locations
authorKeith Seitz <keiths@redhat.com>
Wed, 12 Aug 2015 00:09:35 +0000 (17:09 -0700)
committerKeith Seitz <keiths@redhat.com>
Wed, 12 Aug 2015 00:09:35 +0000 (17:09 -0700)
This patch adds support for address locations, of the form "*ADDR".
[Support for address linespecs has been removed/replaced by this "new"
location type.] This patch also converts any existing address locations
from its previous linespec type.

gdb/ChangeLog:

* breakpoint.c (create_thread_event_breakpoint, init_breakpoint_sal):
Convert linespec to address location.
* linespec.c (canonicalize_linespec): Do not handle address
locations here.
(convert_address_location_to_sals): New function; contents moved
from ...
(convert_linespc_to_sals): ... here.
(parse_linespec): Remove address locations from linespec grammar.
Remove handling of address locations.
(linespec_lex_to_end): Remove handling of address linespecs.
(event_location_to_sals): Handle ADDRESS_LOCATION.
(linespec_expression_to_pc): Export.
* linespec.h (linespec_expression_to_pc): Add declaration.
* location.c (struct event_location.u) <address>: New member.
(new_address_location, get_address_location): New functions.
(copy_event_location, delete_event_location, event_location_to_string)
(string_to_event_location, event_location_empty_p): Handle address
locations.
* location.h (enum event_location_type): Add ADDRESS_LOCATION.
(new_address_location, get_address_location): Declare.
* python/py-finishbreakpoint.c (bpfinishpy_init): Convert linespec
to address location.
* spu-tdep.c (spu_catch_start): Likewise.

gdb/ChangeLog
gdb/breakpoint.c
gdb/linespec.c
gdb/linespec.h
gdb/location.c
gdb/location.h
gdb/python/py-finishbreakpoint.c
gdb/spu-tdep.c

index f6dc1b6f3711187dde63847129b0ef3791a1aa81..97da8c5a7052c38d53b6ca30959e61d927395a04 100644 (file)
@@ -1,3 +1,29 @@
+2015-08-11  Keith Seitz  <keiths@redhat.com>
+
+       * breakpoint.c (create_thread_event_breakpoint, init_breakpoint_sal):
+       Convert linespec to address location.
+       * linespec.c (canonicalize_linespec): Do not handle address
+       locations here.
+       (convert_address_location_to_sals): New function; contents moved
+       from ...
+       (convert_linespc_to_sals): ... here.
+       (parse_linespec): Remove address locations from linespec grammar.
+       Remove handling of address locations.
+       (linespec_lex_to_end): Remove handling of address linespecs.
+       (event_location_to_sals): Handle ADDRESS_LOCATION.
+       (linespec_expression_to_pc): Export.
+       * linespec.h (linespec_expression_to_pc): Add declaration.
+       * location.c (struct event_location.u) <address>: New member.
+       (new_address_location, get_address_location): New functions.
+       (copy_event_location, delete_event_location, event_location_to_string)
+       (string_to_event_location, event_location_empty_p): Handle address
+       locations.
+       * location.h (enum event_location_type): Add ADDRESS_LOCATION.
+       (new_address_location, get_address_location): Declare.
+       * python/py-finishbreakpoint.c (bpfinishpy_init): Convert linespec
+       to address location.
+       * spu-tdep.c (spu_catch_start): Likewise.
+
 2015-08-11  Keith Seitz  <keiths@redhat.com>
 
        * ax-gdb.c: Include location.h.
index 395da1f4d36f95e8588e261cecc9648be6b6539c..b05c93acffa94047135502b9e1c4c6b1abbadedb 100644 (file)
@@ -7660,19 +7660,14 @@ delete_std_terminate_breakpoint (void)
 struct breakpoint *
 create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
 {
-  char *tmp;
   struct breakpoint *b;
-  struct cleanup *cleanup;
 
   b = create_internal_breakpoint (gdbarch, address, bp_thread_event,
                                  &internal_breakpoint_ops);
 
   b->enable_state = bp_enabled;
   /* location has to be used or breakpoint_re_set will delete me.  */
-  tmp = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
-  cleanup = make_cleanup (xfree, tmp);
-  b->location = new_linespec_location (&tmp);
-  do_cleanups (cleanup);
+  b->location = new_address_location (b->loc->address);
 
   update_global_location_list_nothrow (UGLL_MAY_INSERT);
 
@@ -9244,16 +9239,7 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
   if (location != NULL)
     b->location = location;
   else
-    {
-      char *tmp;
-      struct cleanup *cleanup;
-
-      tmp = xstrprintf ("*%s",
-                           paddress (b->loc->gdbarch, b->loc->address));
-      cleanup = make_cleanup (xfree, tmp);
-      b->location = new_linespec_location (&tmp);
-      do_cleanups (cleanup);
-   }
+    b->location = new_address_location (b->loc->address);
   b->filter = filter;
 }
 
index 7cebe39fb15730fb3108018a85536e63864e304a..65c55df8c2d13c98034b6537256ad78286913d14 100644 (file)
@@ -312,7 +312,7 @@ static void iterate_over_file_blocks (struct symtab *symtab,
 static void initialize_defaults (struct symtab **default_symtab,
                                 int *default_line);
 
-static CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
+CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
 
 static struct symtabs_and_lines decode_objc (struct linespec_state *self,
                                             linespec_p ls,
@@ -1789,79 +1789,69 @@ static void
 canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
 {
   char *tmp;
+  struct ui_file *buf;
+  int need_colon = 0;
+  struct cleanup *cleanup;
 
   /* If canonicalization was not requested, no need to do anything.  */
   if (!state->canonical)
     return;
 
-  /* Shortcut expressions, which can only appear by themselves.  */
-  if (ls->expression != NULL)
+  buf = mem_fileopen ();
+  cleanup = make_cleanup_ui_file_delete (buf);
+
+  if (ls->source_filename)
     {
-      tmp = ASTRDUP (ls->expression);
-      state->canonical->location = new_linespec_location (&tmp);
+      fputs_unfiltered (ls->source_filename, buf);
+      need_colon = 1;
     }
-  else
-    {
-      struct ui_file *buf;
-      int need_colon = 0;
-      struct cleanup *cleanup;
 
-      buf = mem_fileopen ();
-      cleanup = make_cleanup_ui_file_delete (buf);
+  if (ls->function_name)
+    {
+      if (need_colon)
+       fputc_unfiltered (':', buf);
+      fputs_unfiltered (ls->function_name, buf);
+      need_colon = 1;
+    }
 
-      if (ls->source_filename)
-       {
-         fputs_unfiltered (ls->source_filename, buf);
-         need_colon = 1;
-       }
+  if (ls->label_name)
+    {
+      if (need_colon)
+       fputc_unfiltered (':', buf);
 
-      if (ls->function_name)
+      if (ls->function_name == NULL)
        {
-         if (need_colon)
-           fputc_unfiltered (':', buf);
-         fputs_unfiltered (ls->function_name, buf);
-         need_colon = 1;
+         struct symbol *s;
+
+         /* No function was specified, so add the symbol name.  */
+         gdb_assert (ls->labels.function_symbols != NULL
+                     && (VEC_length (symbolp, ls->labels.function_symbols)
+                         == 1));
+         s = VEC_index (symbolp, ls->labels.function_symbols, 0);
+         fputs_unfiltered (SYMBOL_NATURAL_NAME (s), buf);
+         fputc_unfiltered (':', buf);
        }
 
-      if (ls->label_name)
-       {
-         if (need_colon)
-           fputc_unfiltered (':', buf);
-
-         if (ls->function_name == NULL)
-           {
-             struct symbol *s;
-
-             /* No function was specified, so add the symbol name.  */
-             gdb_assert (ls->labels.function_symbols != NULL
-                         && (VEC_length (symbolp, ls->labels.function_symbols)
-                             == 1));
-             s = VEC_index (symbolp, ls->labels.function_symbols, 0);
-             fputs_unfiltered (SYMBOL_NATURAL_NAME (s), buf);
-             fputc_unfiltered (':', buf);
-           }
-
-         fputs_unfiltered (ls->label_name, buf);
-         need_colon = 1;
-         state->canonical->special_display = 1;
-       }
-
-      if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
-       {
-         if (need_colon)
-           fputc_unfiltered (':', buf);
-         fprintf_filtered (buf, "%s%d",
-                           (ls->line_offset.sign == LINE_OFFSET_NONE ? ""
-                            : (ls->line_offset.sign
-                               == LINE_OFFSET_PLUS ? "+" : "-")),
-                           ls->line_offset.offset);
-       }
+      fputs_unfiltered (ls->label_name, buf);
+      need_colon = 1;
+      state->canonical->special_display = 1;
+    }
 
-      tmp = ui_file_xstrdup (buf, NULL);
-      make_cleanup (xfree, tmp);
-      state->canonical->location = new_linespec_location (&tmp);
-      do_cleanups (cleanup);
+  if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
+    {
+      if (need_colon)
+       fputc_unfiltered (':', buf);
+      fprintf_filtered (buf, "%s%d",
+                       (ls->line_offset.sign == LINE_OFFSET_NONE ? ""
+                        : (ls->line_offset.sign
+                           == LINE_OFFSET_PLUS ? "+" : "-")),
+                       ls->line_offset.offset);
     }
+
+  tmp = ui_file_xstrdup (buf, NULL);
+  make_cleanup (xfree, tmp);
+  state->canonical->location = new_linespec_location (&tmp);
+  do_cleanups (cleanup);
 }
 
 /* Given a line offset in LS, construct the relevant SALs.  */
@@ -2015,6 +2005,24 @@ create_sals_line_offset (struct linespec_state *self,
   return values;
 }
 
+/* Convert the given ADDRESS into SaLs.  */
+
+static struct symtabs_and_lines
+convert_address_location_to_sals (struct linespec_state *self,
+                                 CORE_ADDR address)
+{
+  struct symtab_and_line sal;
+  struct symtabs_and_lines sals = {NULL, 0};
+
+  sal = find_pc_line (address, 0);
+  sal.pc = address;
+  sal.section = find_pc_overlay (address);
+  sal.explicit_pc = 1;
+  add_sal_to_sals (self, &sals, &sal, core_addr_to_string (address), 1);
+
+  return sals;
+}
+
 /* Create and return SALs from the linespec LS.  */
 
 static struct symtabs_and_lines
@@ -2022,18 +2030,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 {
   struct symtabs_and_lines sals = {NULL, 0};
 
-  if (ls->expression != NULL)
-    {
-      struct symtab_and_line sal;
-
-      /* We have an expression.  No other attribute is allowed.  */
-      sal = find_pc_line (ls->expr_pc, 0);
-      sal.pc = ls->expr_pc;
-      sal.section = find_pc_overlay (ls->expr_pc);
-      sal.explicit_pc = 1;
-      add_sal_to_sals (state, &sals, &sal, ls->expression, 1);
-    }
-  else if (ls->labels.label_symbols != NULL)
+  if (ls->labels.label_symbols != NULL)
     {
       /* We have just a bunch of functions/methods or labels.  */
       int i;
@@ -2131,8 +2128,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 
    The basic grammar of linespecs:
 
-   linespec -> expr_spec | var_spec | basic_spec
-   expr_spec -> '*' STRING
+   linespec -> var_spec | basic_spec
    var_spec -> '$' (STRING | NUMBER)
 
    basic_spec -> file_offset_spec | function_spec | label_spec
@@ -2223,33 +2219,7 @@ parse_linespec (linespec_parser *parser, const char *arg)
   token = linespec_lexer_lex_one (parser);
 
   /* It must be either LSTOKEN_STRING or LSTOKEN_NUMBER.  */
-  if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '*')
-    {
-      char *expr;
-      const char *copy;
-
-      /* User specified an expression, *EXPR.  */
-      copy = expr = copy_token_string (token);
-      cleanup = make_cleanup (xfree, expr);
-      PARSER_RESULT (parser)->expr_pc = linespec_expression_to_pc (&copy);
-      discard_cleanups (cleanup);
-      PARSER_RESULT (parser)->expression = expr;
-
-      /* This is a little hacky/tricky.  If linespec_expression_to_pc
-        did not evaluate the entire token, then we must find the
-        string COPY inside the original token buffer.  */
-      if (*copy != '\0')
-       {
-         PARSER_STREAM (parser) = strstr (parser->lexer.saved_arg, copy);
-         gdb_assert (PARSER_STREAM (parser) != NULL);
-       }
-
-      /* Consume the token.  */
-      linespec_lexer_consume_token (parser);
-
-      goto convert_to_sals;
-    }
-  else if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '$')
+  if (token.type == LSTOKEN_STRING && *LS_TOKEN_STOKEN (token).ptr == '$')
     {
       char *var;
 
@@ -2470,20 +2440,6 @@ linespec_lex_to_end (char **stringp)
       token = linespec_lexer_peek_token (&parser);
       if (token.type == LSTOKEN_COMMA)
        break;
-
-      /* For addresses advance the parser stream past
-        any parsed input and stop lexing.  */
-      if (token.type == LSTOKEN_STRING
-         && *LS_TOKEN_STOKEN (token).ptr == '*')
-       {
-         const char *arg;
-
-         arg = *stringp;
-         (void) linespec_expression_to_pc (&arg);
-         PARSER_STREAM (&parser) = arg;
-         break;
-       }
-
       token = linespec_lexer_consume_token (&parser);
     }
   while (token.type != LSTOKEN_EOI && token.type != LSTOKEN_KEYWORD);
@@ -2517,6 +2473,12 @@ event_location_to_sals (linespec_parser *parser,
       }
       break;
 
+    case ADDRESS_LOCATION:
+      result
+       = convert_address_location_to_sals (PARSER_STATE (parser),
+                                           get_address_location (location));
+      break;
+
     default:
       gdb_assert_not_reached ("unhandled event location type");
     }
@@ -2702,7 +2664,7 @@ initialize_defaults (struct symtab **default_symtab, int *default_line)
 /* Evaluate the expression pointed to by EXP_PTR into a CORE_ADDR,
    advancing EXP_PTR past any parsed text.  */
 
-static CORE_ADDR
+CORE_ADDR
 linespec_expression_to_pc (const char **exp_ptr)
 {
   if (current_program_space->executing_startup)
index 840bae5e4957e3c739118311d18d65e74bc9c9c7..391ed2638654aa0bd12c50d6c72955937754c840 100644 (file)
@@ -161,4 +161,9 @@ extern const char *linespec_lexer_lex_keyword (const char *p);
    STRINGP will be advanced to this point.  */
 
 extern void linespec_lex_to_end (char **stringp);
+
+/* Evaluate the expression pointed to by EXP_PTR into a CORE_ADDR,
+   advancing EXP_PTR past any parsed text.  */
+
+extern CORE_ADDR linespec_expression_to_pc (const char **exp_ptr);
 #endif /* defined (LINESPEC_H) */
index 44f3dc6e7a6eb549f5fd6632116d5b304282e3df..eea88fa9e21eee23ae8b9e29b30754f23b386dff 100644 (file)
@@ -45,6 +45,10 @@ struct event_location
        probes.  */
     char *addr_string;
 #define EL_LINESPEC(PTR) ((PTR)->u.addr_string)
+
+    /* An address in the inferior.  */
+    CORE_ADDR address;
+#define EL_ADDRESS(PTR) (PTR)->u.address
   } u;
 
   /* Cached string representation of this location.  This is used, e.g., to
@@ -94,6 +98,28 @@ get_linespec_location (const struct event_location *location)
 
 /* See description in location.h.  */
 
+struct event_location *
+new_address_location (CORE_ADDR addr)
+{
+  struct event_location *location;
+
+  location = XCNEW (struct event_location);
+  EL_TYPE (location) = ADDRESS_LOCATION;
+  EL_ADDRESS (location) = addr;
+  return location;
+}
+
+/* See description in location.h.  */
+
+CORE_ADDR
+get_address_location (const struct event_location *location)
+{
+  gdb_assert (EL_TYPE (location) == ADDRESS_LOCATION);
+  return EL_ADDRESS (location);
+}
+
+/* See description in location.h.  */
+
 struct event_location *
 copy_event_location (const struct event_location *src)
 {
@@ -111,6 +137,10 @@ copy_event_location (const struct event_location *src)
        EL_LINESPEC (dst) = xstrdup (EL_LINESPEC (src));
       break;
 
+    case ADDRESS_LOCATION:
+      EL_ADDRESS (dst) = EL_ADDRESS (src);
+      break;
+
     default:
       gdb_assert_not_reached ("unknown event location type");
     }
@@ -151,6 +181,10 @@ delete_event_location (struct event_location *location)
          xfree (EL_LINESPEC (location));
          break;
 
+       case ADDRESS_LOCATION:
+         /* Nothing to do.  */
+         break;
+
        default:
          gdb_assert_not_reached ("unknown event location type");
        }
@@ -173,6 +207,12 @@ event_location_to_string (struct event_location *location)
            EL_STRING (location) = xstrdup (EL_LINESPEC (location));
          break;
 
+       case ADDRESS_LOCATION:
+         EL_STRING (location)
+           = xstrprintf ("*%s",
+                         core_addr_to_string (EL_ADDRESS (location)));
+         break;
+
        default:
          gdb_assert_not_reached ("unknown event location type");
        }
@@ -189,7 +229,23 @@ string_to_event_location (char **stringp,
 {
   struct event_location *location;
 
-  location = new_linespec_location (stringp);
+  /* First, check if the string is an address location.  */
+  if (*stringp != NULL && **stringp == '*')
+    {
+      const char *arg, *orig;
+      CORE_ADDR addr;
+
+      orig = arg = *stringp;
+      addr = linespec_expression_to_pc (&arg);
+      location = new_address_location (addr);
+      *stringp += arg - orig;
+    }
+  else
+    {
+      /* Everything else is a linespec.  */
+      location = new_linespec_location (stringp);
+    }
+
   return location;
 }
 
@@ -204,6 +260,9 @@ event_location_empty_p (const struct event_location *location)
       /* Linespecs are never "empty."  (NULL is a valid linespec)  */
       return 0;
 
+    case ADDRESS_LOCATION:
+      return 0;
+
     default:
       gdb_assert_not_reached ("unknown event location type");
     }
index d35fecbf08c2e1082a232344541146f236105c93..7b9741b77aed9b362137a5faa9140d972b89a8ba 100644 (file)
@@ -28,7 +28,10 @@ struct event_location;
 enum event_location_type
 {
   /* A traditional linespec.  */
-  LINESPEC_LOCATION
+  LINESPEC_LOCATION,
+
+  /* An address in the inferior.  */
+  ADDRESS_LOCATION
 };
 
 /* Return the type of the given event location.  */
@@ -57,6 +60,18 @@ extern struct event_location *
 extern const char *
   get_linespec_location (const struct event_location *location);
 
+/* Create a new address location.  The return result is malloc'd
+   and should be freed with delete_event_location.  */
+
+extern struct event_location *
+  new_address_location (CORE_ADDR addr);
+
+/* Return the address location (a CORE_ADDR) of the given event_location
+   (which must be of type ADDRESS_LOCATION).  */
+
+extern CORE_ADDR
+  get_address_location (const struct event_location *location);
+
 /* Free an event location and any associated data.  */
 
 extern void delete_event_location (struct event_location *location);
index 671fd234c38d9ff39d618c34116827f19acdd73d..e543bb32dd1fd769b8d9e4b4dc909aaeefc8335b 100644 (file)
@@ -169,8 +169,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
   struct frame_id frame_id;
   PyObject *internal = NULL;
   int internal_bp = 0;
-  CORE_ADDR finish_pc, pc;
-  char small_buf[100], *p;
+  CORE_ADDR pc;
   struct symbol *function;
 
   if (!PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
@@ -301,10 +300,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
       struct cleanup *back_to;
 
       /* Set a breakpoint on the return address.  */
-      finish_pc = get_frame_pc (prev_frame);
-      xsnprintf (small_buf, sizeof (small_buf), "*%s", hex_string (finish_pc));
-      p = small_buf;
-      location = new_linespec_location (&p);
+      location = new_address_location (get_frame_pc (prev_frame));
       back_to = make_cleanup_delete_event_location (location);
       create_breakpoint (python_gdbarch,
                          location, NULL, thread, NULL,
index 58d66710c40c23c2aa5ed2d491bb2524fd91a7da..75372df47a75bb61b85168cc7f90f9e6924c6744 100644 (file)
@@ -1953,7 +1953,6 @@ spu_catch_start (struct objfile *objfile)
 {
   struct bound_minimal_symbol minsym;
   struct compunit_symtab *cust;
-  char buf[32], *p;
   CORE_ADDR pc;
   struct event_location *location;
   struct cleanup *back_to;
@@ -2000,9 +1999,7 @@ spu_catch_start (struct objfile *objfile)
 
   /* Use a numerical address for the set_breakpoint command to avoid having
      the breakpoint re-set incorrectly.  */
-  xsnprintf (buf, sizeof buf, "*%s", core_addr_to_string (pc));
-  p = buf;
-  location = new_linespec_location (&p);
+  location = new_address_location (pc);
   back_to = make_cleanup_delete_event_location (location);
   create_breakpoint (get_objfile_arch (objfile), location,
                     NULL /* cond_string */, -1 /* thread */,