This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[RFA 1/4] Explicit locations


Hi,

This is a reboot of a series of patches I submitted several months ago. The feature I am attempting to introduce will essentially allow users to bypass the linespec parser.

To accomplish this, I've refactored the breakpoint API a bit so that instead of taking an address string (char *), it will take a structure (struct event_location *).

At the end of the series, the supported event locations (as I settled on calling them) will be "linespec", "address", and "explicit". [I have made (almost) no attempt at converting probes into their own location type (yet?).]

I think the three location types are pretty self-explanatory:

o Address locations are of the form *ADDRESS. I've split these from traditional linespecs.

o Linespec locations are what we have today (minus address locations -- although I've left that processing alone for now)

o Explicit locations are of the form "-source FILENAME -line LINE -function FUNC -label LABEL" (for the CLI; similar for MI). If the user specifies -func FOO and he really meant -label FOO, the location decoder (nee decode_line_*) will error. [Contrast this with the linespec parser, where this might succeed or find an actual function called FOO.]

I've split this feature up into four patches:

1: Refactor breakpoint api; addr_string -> struct event_location (this patch)

2: Introduce explicit locations, and use them internally

3: Add explicit locations to CLI/MI. [no python yet]

4: Documentation update*

* Yes, probably better with/alongside #3, but not for me. :-P

While I have split these patches so that earlier patches may be applied/committed independently of later patches, it is not my intention to actually do so. I am treating them as all-or-nothing.

I have tested these on x86_64-linux native, native-gdbserver, and cc-with-tweaks (-i), and there are no regressions. Or at least, there are no regressions which are tested in the test suite.

In the end, too, this patch set will also fix several (current) problems with saving breakpoints. [See tests in patch #3.]

With that said...

This first patch removes addr_string and introduces struct event_location and some additional bits, including utility functions to create/initialize/delete these locations, convert from/to strings, and so on.

While most of the changes are fairly mechanical, such as renaming a bunch of functions in breakpoint.c, there is one "big" change in this patch: the extra_string parameter to create_breakpoint may now be non-NULL. [Right now, every caller of create_breakpoint passes in NULL.]

In the patch (as you'll read), extra_string will be passed to find_condition_and_thread for non-linespec locations. This permits commands like "break -func main if argc > 2" to work.

Keith

2013-03-21  Keith Seitz  <keiths@redhat.com>

	* breakpoint.h (enum event_location_type): New enum.
	(struct event_location): New struct.
	(struct breakpoint_ops.create_sals_from_address): Rename to ...
	(struct breakpoint_ops.create_sals_from_location): ... this.
	Change ADDR_STRING to struct event_location.
	(struct breakpoint_ops.decode_linespec): Rename to ...
	(struct breakpoint_ops.decode_location): .. this.
	Change char ** to struct event_location *.
	(struct breakpoint): Use locations instead of address strings.
	Likewise for FILTER and ADDR_STRING_RANGE_END.
	(create_breakpoint): Likewise.
	(event_location_to_string): Declare new function.
	(delete_event_location): Declare new function.
	(initialize_event_location): Declare new function.
	* breakpoint.c (create_overlay_event_breakpoint): Use locations
	instead of address strings.
	(create_longjmp_master_breakpoint): Likewise.
	(create_std_terminate_master_breakpoint): Likewise.
	(create_exception_master_breakpoint): Likewise.
	(update_breakpoints_after_exec): Likewise.
	(print_breakpoint_location): Use locations and
	event_location_to_string.
	(print_one_breakpoint_location): Likewise.
	(init_raw_breakpoint_without_location): Initialize
	b->location.
	(create_thread_event_breakpoint): Use locations instead of
	address strings.
	(copy_event_location): New function.
	(delete_event_location): New function.
	(initialize_event_location): New function.
	(new_event_location): New function.
	(init_breakpoint_sal): Change "addr_string" and "filter" to
	locations.
	If "extra_string" is not empty, save it into the breakpoint;
	otherwise, set the extra_string member to NULL.
	Use event_location_to_string instead of "addr_string".
	Change "p" to const char *.
	Use skip_spaces_const.
	Copy the location into the breakpoint.
	Fall back to saving an address location into the breakpoint instead
	of an address string.
	(create_breakpoint_sal): Change "addr_string" and "filter" to
	locations.
	(create_breakpoints_sal): Change "addr_string" and "filter_string" to
	locations.
	(parse_breakpoint_sals): Use locations instead of address strings.
	Guard against NULL address string when not using the default
	breakpoint.
	Pass event_location to decode_line_full.
	(create_breakpoint): Change "arg" to struct event_location and rename.
	Pass location to breakpoint_ops method create_sals_from_location.
	Save the SAVE_SPEC of the location for pending breakpoints.
	For non-linespec locations, pass extra_string to
	find_condition_and_thread.
	Copy the location into the breakpoint instead of an address string.
	If "extra_string" is not empty, copy it into the breakpoint;
	otherwise, set the extra_string member to NULL.
	(break_command_1): Use string_to_event_location and pass this to
	create_breakpoint instead of an address string.
	(dprintf_command): Likewise.
	(print_recreate_ranged_breakpoint): Use the location's SAVE_SPEC for
	recreating the breakpoint.
	(break_range_command): Use locations instead of address strings.
	(until_break_command): Likewise.
	(print_it_exception_catchpoint): Use event_location_to_string on
	the location instead of an address string.
	(print_mention_exception_catchpoint): Likewise.
	(print_recreate_exception_catchpoint): Use the location's SAVE_SPEC.
	(handle_gnu_v3_exceptions): Use locations instead of address strings.
	(init_ada_exception_breakpoint): Likewise.
	(say_where): Likewise.
	(base_breakpoint_dtor): Delete location, filter, and
	location_range_end.
	(base_breakpoint_create_sals_from_address): Rename to ...
	(base_breakpoint_create_sals_from_location): ... this.
	(base_breakpoint_decode_linespec): Rename to ...
	(base_breakpoint_decode_location): ... this.
	Use locations instead of address strings.
	Update method names.
	(breakpoint_re_set): Use locations instead of address strings.
	(bkpt_print_recreate): Use the location's SAVE_SPEC instead of
	an address string.
	(bkpt_create_sals_from_address): Rename to ...
	(bkpt_create_sals_from_location): ... this.
	Use a location instead of an address string.
	(bkpt_deocde_linespec): Rename to ...
	(bkpt_decode_location): ... this.
	Use a location instead of an address string.
	(bkpt_probe_create_sals_from_address): Rename to...
	(bkpt_probe_create_sals_from_location): ... this.
	Use a location instead of an address string.
	(bkpt_probe_decode_linespec): Rename to ...
	(bkpt_probe_decode_location): ... this.
	Use a location instead of an address string.
	(tracepoint_print_recreate): Use the SAVE_SPEC of the location
	instead of an address string.
	(tracepoint_create_sals_from_address): Rename to ...
	(tracepoint_create_sals_from_location): ... this.
	Use a location instead of an address string.
	(tracepoint_decode_linespec): Rename to ...
	(tracepoint_decode_location): ... this.
	Use a location instead of an address string.
	(tracepoint_probe_create_sals_from_address): Rename to ...
	(tracepoint_probe_create_sals_from_location): ... this.
	Use a location instead of an address string.
	(tracepoint_probe_decode_linespec): Rename to ...
	(tracepoint_probe_decode_location): ... this.
	Use locations instead of address strings.
	(strace_marker_create_sals_from_address): Rename to ...
	(strace_marker_create_sals_from_location): ... this.
	Use locations instead of address strings.
	(strace_marker_create_breakpoints_sal): Use locations
	instead of address strings.
	(strace_marker_decode_linespec): Rename to ...
	(strace_marker_decode_location): ... this.
	Use linespec locations instead of address strings.
	(update_static_tracepoint): Use locations instead of
	address strings.
	(addr_string_to_sals): Rename to ...
	(location_to_sals): ... this.
	Use locations instead of address strings.
	Pass extra_string to find_condition_and_thread for non-linespec
	locations.
	When a pending breakpoint has been resolved, set a
	new SAVE_SPEC for the location.
	(breakpoint_re_set_default): Use locations instead of
	address strings.
	(create_sals_from_address_default): Rename to ...
	(create_sals_from_location_default): ... this.
	Use locations instead of address strings.
	(decode_linespec_default): Rename to ...
	(decode_location_default): ... this.
	Use locations instead of address strings.
	(trace_command): Use locations instead of address strings.
	(ftrace_command): Likewise.
	(create_tracepoint_from_upload): Likewise.
	(event_location_to_string): New function.
	(initialize_breakpoint_ops): Rename all "address" methods
	to "location".
	* ax-gdb.c (agent_command_1): Use locations instead of
	address strings.
	* cli/cli-cmds.c (edit_command): Likewise.
	(list_command): Likewise.
	* elfread.c (elf_gnu_ifunc_resolver_return_stop): Use
	event_location_to_string on the breakpoint's location.
	* linespec.c (filter_results): Use linespec locations instead of
	address strings.
	(canonicalize_linespec): Save a canonical address location
	for expressions; linespec locations for everything else.
	Create and save a SAVE_SPEC for the location.
	(convert_address_location_to_sals): Moved here from ...
	(convert_linespec_to_sals): ... here.
	(parse_linespec): Add comment about address locations being handled
	elsewhere.
	(linespec_parser_new): Initialize "parser".
	(event_location_to_sals): New function.
	(decode_line_full): Use locations instead of address strings.
	Call event_location_to_sals instead of parse_linespec.
	Filter results for linespec filters.
	(decode_line_1): Use locations instead of address strings.
	Call event_location_to_sals instead of parse_linespec.
	(decode_line_with_current_source): Use locations instead
	of address strings.
	(decode_line_with_last_displayed): Likewise.
	(decode_obj): Use locations instead of address strings.
	(destroy_linespec_result): Instead of freeing address
	strings, delete the locations.
	(string_to_event_location): New function.
	* linespec.h (struct linespec_sals): Make "canonical" a
	struct event_location.
	Likewise with "addr_string".
	(decode_line_1): Use locations instead of address strings.
	(decode_line_full): Likewise.
	(string_to_event_location): Declare.
	* mi/mi-cmd-break.c: Include linespec.h and language.h.
	(mi_cmd_break_insert): Use locations instead of address
	strings.
	* probe.c: Include breakpoint.h.
	(parse_probes): Use linespec locations instead of address strings.
	* probe.h (parse_probes): Likewise.
	* python/py-breakpoint.c (bppy_get_location): Constify "str"
	and use event_location_to_string.
	(bppy_init): Use locations instead of address strings.
	* python/py-finishbreakpoint.c (bpfinishpy_init): Likewise.
	Remove unnecessary variable finish_pc.
	* python.c (gdbpy_decode_line): Use locations instead of
	address strings.
	* remote.c (remote_download_tracepoint): Likewise.
	* spu-tdep.c (spu_catch_start): Likewise.
	* tracepoint.c (scope_info): Likewise.
	(encode_source_string): Make "src" const.
	* tracepoint.h (encode_source_string): Likewise.



diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 68f3ed9..bae5d7c 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -478,6 +478,47 @@ struct bp_location
   struct symtab *symtab;
 };
 
+/* An enumeration of the various ways to specify a stop event
+   location (used with create_breakpoint).  */
+
+enum event_location_type
+  {
+    /* A traditional linespec.  */
+    EVENT_LOCATION_LINESPEC,
+
+    /* An address in the inferior.  */
+    EVENT_LOCATION_ADDRESS,
+  };
+
+/* An event location used to set a stop event in the inferior.
+   This structure is an amalgam of the various ways
+   to specify a where a stop event should be set.  */
+
+struct event_location
+{
+  /* The type of this breakpoint specification.  */
+  enum event_location_type type;
+#define EVENT_LOCATION_TYPE(S) ((S)->type)
+
+  union
+  {
+    /* A "normal" linespec which must be parsed by the
+       linespec parser.  */
+    char *addr_string;
+#define EVENT_LOCATION_LINESPEC(S) ((S)->u.addr_string)
+
+    /* An address in the inferior.  */
+    CORE_ADDR address;
+#define EVENT_LOCATION_ADDRESS(S) ((S)->u.address)
+  } u;
+
+  /* A string representation of how this location may be
+     saved.  This is used to save stop event locations to file.
+     Malloc'd.  */
+  char *save_spec;
+#define EVENT_LOCATION_SAVE_SPEC(S) ((S)->save_spec)
+};
+
 /* Return values for bpstat_explains_signal.  Note that the order of
    the constants is important here; they are compared directly in
    bpstat_explains_signal.  */
@@ -577,14 +618,15 @@ struct breakpoint_ops
   /* Print to FP the CLI command that recreates this breakpoint.  */
   void (*print_recreate) (struct breakpoint *, struct ui_file *fp);
 
-  /* Create SALs from address string, storing the result in linespec_result.
+  /* Create SALs from location, storing the result in linespec_result.
 
      For an explanation about the arguments, see the function
-     `create_sals_from_address_default'.
+     `create_sals_from_location_default'.
 
      This function is called inside `create_breakpoint'.  */
-  void (*create_sals_from_address) (char **, struct linespec_result *,
-				    enum bptype, char *, char **);
+  void (*create_sals_from_location) (struct event_location *location,
+				     struct linespec_result *canonical,
+				     enum bptype type_wanted);
 
   /* This method will be responsible for creating a breakpoint given its SALs.
      Usually, it just calls `create_breakpoints_sal' (for ordinary
@@ -605,9 +647,10 @@ struct breakpoint_ops
      and provides the SAL locations related to it.  For ordinary breakpoints,
      it calls `decode_line_full'.
 
-     This function is called inside `addr_string_to_sals'.  */
-  void (*decode_linespec) (struct breakpoint *, char **,
-			   struct symtabs_and_lines *);
+     This function is called inside `location_to_sals'.  */
+  void (*decode_location) (struct breakpoint *b,
+			   struct event_location *location,
+			   struct symtabs_and_lines *sals);
 
   /* Return true if this breakpoint explains a signal, but the signal
      should still be delivered to the inferior.  This is used to make
@@ -704,17 +747,17 @@ struct breakpoint
        non-thread-specific ordinary breakpoints this is NULL.  */
     struct program_space *pspace;
 
-    /* String we used to set the breakpoint (malloc'd).  */
-    char *addr_string;
+    /* Location we used to set the breakpoint (malloc'd).  */
+    struct event_location *location;
 
     /* The filter that should be passed to decode_line_full when
        re-setting this breakpoint.  This may be NULL, but otherwise is
-       allocated with xmalloc.  */
-    char *filter;
+       allocated with new_event_location.  */
+    struct event_location *filter;
 
-    /* For a ranged breakpoint, the string we used to find
+    /* For a ranged breakpoint, the location we used to find
        the end of the range (malloc'd).  */
-    char *addr_string_range_end;
+    struct event_location *location_range_end;
 
     /* Architecture we used to set the breakpoint.  */
     struct gdbarch *gdbarch;
@@ -1266,7 +1309,8 @@ enum breakpoint_create_flags
     CREATE_BREAKPOINT_FLAGS_INSERTED = 1 << 0
   };
 
-extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
+extern int create_breakpoint (struct gdbarch *gdbarch,
+			      struct event_location *location,
 			      char *cond_string, int thread,
 			      char *extra_string,
 			      int parse_condition_and_thread,
@@ -1278,6 +1322,27 @@ extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
 			      int enabled,
 			      int internal, unsigned flags);
 
+/* Return a string representation of the LOCATION.
+   This function may return NULL for unspecified linespecs,
+   e.g, EVENT_LOCATION_LINESPEC and addr_string is NULL.  */
+
+extern const char *
+  event_location_to_string (const struct event_location *location);
+
+/* Free an event location and any associated data.  */
+
+extern void delete_event_location (void *data);
+
+/* Create a new event location with the given TYPE.  */
+
+extern struct event_location *
+  new_event_location (enum event_location_type type);
+
+/* Initialize the given LOCATION.  */
+
+extern void initialize_event_location (struct event_location *location,
+				       enum event_location_type type);
+
 extern void insert_breakpoints (void);
 
 extern int remove_breakpoints (void);
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 3aa3b68..3d6155f 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -111,10 +111,10 @@ static int breakpoint_re_set_one (void *);
 
 static void breakpoint_re_set_default (struct breakpoint *);
 
-static void create_sals_from_address_default (char **,
-					      struct linespec_result *,
-					      enum bptype, char *,
-					      char **);
+static void
+  create_sals_from_location_default (struct event_location *location,
+				     struct linespec_result *canonical,
+				     enum bptype type_wanted);
 
 static void create_breakpoints_sal_default (struct gdbarch *,
 					    struct linespec_result *,
@@ -125,8 +125,9 @@ static void create_breakpoints_sal_default (struct gdbarch *,
 					    const struct breakpoint_ops *,
 					    int, int, int, unsigned);
 
-static void decode_linespec_default (struct breakpoint *, char **,
-				     struct symtabs_and_lines *);
+static void decode_location_default (struct breakpoint *b,
+				     struct event_location *location,
+				     struct symtabs_and_lines *sals);
 
 static void clear_command (char *, int);
 
@@ -3155,7 +3156,8 @@ create_overlay_event_breakpoint (void)
       b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
                                       bp_overlay_event,
 				      &internal_breakpoint_ops);
-      b->addr_string = xstrdup (func_name);
+      b->location = new_event_location (EVENT_LOCATION_LINESPEC);
+      EVENT_LOCATION_LINESPEC (b->location) = xstrdup (func_name);
 
       if (overlay_debugging == ovly_auto)
         {
@@ -3221,7 +3223,9 @@ create_longjmp_master_breakpoint (void)
 	      b = create_internal_breakpoint (gdbarch, probe->address,
 					      bp_longjmp_master,
 					      &internal_breakpoint_ops);
-	      b->addr_string = xstrdup ("-probe-stap libc:longjmp");
+	      b->location = new_event_location (EVENT_LOCATION_LINESPEC);
+	      EVENT_LOCATION_LINESPEC (b->location)
+		= xstrdup ("-probe-stap libc:longjmp");
 	      b->enable_state = bp_disabled;
 	    }
 
@@ -3255,7 +3259,8 @@ create_longjmp_master_breakpoint (void)
 	  addr = SYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
 	  b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
 					  &internal_breakpoint_ops);
-	  b->addr_string = xstrdup (func_name);
+	  b->location = new_event_location (EVENT_LOCATION_LINESPEC);
+	  EVENT_LOCATION_LINESPEC (b->location) = xstrdup (func_name);
 	  b->enable_state = bp_disabled;
 	}
     }
@@ -3311,7 +3316,8 @@ create_std_terminate_master_breakpoint (void)
       b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
                                       bp_std_terminate_master,
 				      &internal_breakpoint_ops);
-      b->addr_string = xstrdup (func_name);
+      b->location = new_event_location (EVENT_LOCATION_LINESPEC);
+      EVENT_LOCATION_LINESPEC (b->location) = xstrdup (func_name);
       b->enable_state = bp_disabled;
     }
   }
@@ -3363,7 +3369,9 @@ create_exception_master_breakpoint (void)
 	      b = create_internal_breakpoint (gdbarch, probe->address,
 					      bp_exception_master,
 					      &internal_breakpoint_ops);
-	      b->addr_string = xstrdup ("-probe-stap libgcc:unwind");
+	      b->location = new_event_location (EVENT_LOCATION_LINESPEC);
+	      EVENT_LOCATION_LINESPEC (b->location)
+		= xstrdup ("-probe-stap libgcc:unwind");
 	      b->enable_state = bp_disabled;
 	    }
 
@@ -3396,7 +3404,8 @@ create_exception_master_breakpoint (void)
 						 &current_target);
       b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
 				      &internal_breakpoint_ops);
-      b->addr_string = xstrdup (func_name);
+      b->location = new_event_location (EVENT_LOCATION_LINESPEC);
+      EVENT_LOCATION_LINESPEC (b->location) = xstrdup (func_name);
       b->enable_state = bp_disabled;
     }
 
@@ -3510,7 +3519,7 @@ update_breakpoints_after_exec (void)
     /* Without a symbolic address, we have little hope of the
        pre-exec() address meaning the same thing in the post-exec()
        a.out.  */
-    if (b->addr_string == NULL)
+    if (EVENT_LOCATION_LINESPEC (b->location) == NULL)
       {
 	delete_breakpoint (b);
 	continue;
@@ -5694,7 +5703,8 @@ print_breakpoint_location (struct breakpoint *b,
     set_current_program_space (loc->pspace);
 
   if (b->display_canonical)
-    ui_out_field_string (uiout, "what", b->addr_string);
+    ui_out_field_string (uiout, "what",
+			 event_location_to_string (b->location));
   else if (loc && loc->symtab)
     {
       struct symbol *sym 
@@ -5730,7 +5740,8 @@ print_breakpoint_location (struct breakpoint *b,
       do_cleanups (stb_chain);
     }
   else
-    ui_out_field_string (uiout, "pending", b->addr_string);
+    ui_out_field_string (uiout, "pending",
+			 event_location_to_string (b->location));
 
   if (loc && is_breakpoint (b)
       && breakpoint_condition_evaluation_mode () == condition_evaluation_target
@@ -6198,8 +6209,10 @@ print_one_breakpoint_location (struct breakpoint *b,
 
 	  ui_out_field_string (uiout, "original-location", w->exp_string);
 	}
-      else if (b->addr_string)
-	ui_out_field_string (uiout, "original-location", b->addr_string);
+      else if (b->location != NULL
+	       && event_location_to_string (b->location) != NULL)
+	ui_out_field_string (uiout, "original-location",
+			     event_location_to_string (b->location));
     }
 }
 
@@ -6963,6 +6976,7 @@ init_raw_breakpoint_without_location (struct breakpoint *b,
   b->condition_not_parsed = 0;
   b->py_bp_object = NULL;
   b->related_breakpoint = b;
+  b->location = NULL;
 }
 
 /* Helper to set_raw_breakpoint below.  Creates a breakpoint
@@ -7307,9 +7321,9 @@ create_thread_event_breakpoint (struct gdbarch *gdbarch, CORE_ADDR address)
 				  &internal_breakpoint_ops);
 
   b->enable_state = bp_enabled;
-  /* addr_string has to be used or breakpoint_re_set will delete me.  */
-  b->addr_string
-    = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+  /* location has to be used or breakpoint_re_set will delete me.  */
+  b->location = new_event_location (EVENT_LOCATION_ADDRESS);
+  EVENT_LOCATION_ADDRESS (b->location) = b->loc->address;
 
   update_global_location_list_nothrow (1);
 
@@ -8989,14 +9003,93 @@ update_dprintf_commands (char *args, int from_tty,
     }
 }
 
-/* Create a breakpoint with SAL as location.  Use ADDR_STRING
-   as textual description of the location, and COND_STRING
+/* Return a copy the given SRC location.  */
+
+static struct event_location *
+copy_event_location (struct event_location *src)
+{
+  struct event_location *dst;
+
+  dst = XCNEW (struct event_location);
+  EVENT_LOCATION_TYPE (dst) = EVENT_LOCATION_TYPE (src);
+  if (EVENT_LOCATION_SAVE_SPEC (src) != NULL)
+    EVENT_LOCATION_SAVE_SPEC (dst) = xstrdup (EVENT_LOCATION_SAVE_SPEC (src));
+
+  switch (EVENT_LOCATION_TYPE (src))
+    {
+    case EVENT_LOCATION_LINESPEC:
+      EVENT_LOCATION_LINESPEC (dst) = xstrdup (EVENT_LOCATION_LINESPEC (src));
+      break;
+
+    case EVENT_LOCATION_ADDRESS:
+      EVENT_LOCATION_ADDRESS (dst) = EVENT_LOCATION_ADDRESS (src);
+      break;
+
+    default:
+      gdb_assert_not_reached ("unknown event location type");
+    }
+
+  return dst;
+}
+
+/* Free LOCATION and any associated data.  */
+
+void
+delete_event_location (void *data)
+{
+  struct event_location *location
+    = (struct event_location *) data;
+
+  if (location != NULL)
+    {
+      xfree (EVENT_LOCATION_SAVE_SPEC (location));
+
+      switch (EVENT_LOCATION_TYPE (location))
+	{
+	case EVENT_LOCATION_LINESPEC:
+	  xfree (EVENT_LOCATION_LINESPEC (location));
+	  break;
+
+	case EVENT_LOCATION_ADDRESS:
+	  /* Nothing to do.  */
+	  break;
+	}
+
+      xfree (location);
+    }
+}
+
+/* Initialize the given LOCATION.  */
+
+void
+initialize_event_location (struct event_location *location,
+			  enum event_location_type type)
+{
+  memset (location, 0, sizeof (struct event_location));
+  EVENT_LOCATION_TYPE (location) = type;
+}
+
+/* Create a new user location with the given TYPE.  */
+
+struct event_location *
+new_event_location (enum event_location_type type)
+{
+  struct event_location *location;
+
+  location = XNEW (struct event_location);
+  initialize_event_location (location, type);
+  return location;
+}
+
+/* Create a breakpoint with SAL as location.  Use LOCATION
+   as a description of the location, and COND_STRING
    as condition expression.  */
 
 static void
 init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
-		     struct symtabs_and_lines sals, char *addr_string,
-		     char *filter, char *cond_string,
+		     struct symtabs_and_lines sals,
+		     struct event_location *location,
+		     struct event_location *filter, char *cond_string,
 		     char *extra_string,
 		     enum bptype type, enum bpdisp disposition,
 		     int thread, int task, int ignore_count,
@@ -9044,7 +9137,10 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
 	  b->task = task;
 
 	  b->cond_string = cond_string;
-	  b->extra_string = extra_string;
+	  if (extra_string != NULL && *extra_string != '\0')
+	    b->extra_string = extra_string;
+	  else
+	    b->extra_string = NULL;
 	  b->ignore_count = ignore_count;
 	  b->enable_state = enabled ? bp_enabled : bp_disabled;
 	  b->disposition = disposition;
@@ -9061,13 +9157,13 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
 		{
 		  /* We already know the marker exists, otherwise, we
 		     wouldn't see a sal for it.  */
-		  char *p = &addr_string[3];
-		  char *endp;
+		  const char *p = &event_location_to_string (b->location)[3];
+		  const char *endp;
 		  char *marker_str;
 
-		  p = skip_spaces (p);
+		  p = skip_spaces_const (p);
 
-		  endp = skip_to_space (p);
+		  endp = skip_to_space_const (p);
 
 		  marker_str = savestring (p, endp - p);
 		  t->static_trace_marker_id = marker_str;
@@ -9126,20 +9222,23 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
     }
 
   b->display_canonical = display_canonical;
-  if (addr_string)
-    b->addr_string = addr_string;
+  if (location != NULL)
+    b->location = location;
   else
-    /* addr_string has to be used or breakpoint_re_set will delete
-       me.  */
-    b->addr_string
-      = xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+    {
+      b->location = new_event_location (EVENT_LOCATION_ADDRESS);
+      EVENT_LOCATION_ADDRESS (b->location) = b->loc->address;
+      EVENT_LOCATION_SAVE_SPEC (b->location) =
+	xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+   }
   b->filter = filter;
 }
 
 static void
 create_breakpoint_sal (struct gdbarch *gdbarch,
-		       struct symtabs_and_lines sals, char *addr_string,
-		       char *filter, char *cond_string,
+		       struct symtabs_and_lines sals,
+		       struct event_location *location,
+		       struct event_location *filter, char *cond_string,
 		       char *extra_string,
 		       enum bptype type, enum bpdisp disposition,
 		       int thread, int task, int ignore_count,
@@ -9163,7 +9262,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
   old_chain = make_cleanup (xfree, b);
 
   init_breakpoint_sal (b, gdbarch,
-		       sals, addr_string,
+		       sals, location,
 		       filter, cond_string, extra_string,
 		       type, disposition,
 		       thread, task, ignore_count,
@@ -9207,18 +9306,19 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
 
   for (i = 0; VEC_iterate (linespec_sals, canonical->sals, i, lsal); ++i)
     {
-      /* Note that 'addr_string' can be NULL in the case of a plain
+      /* Note that 'location' can be NULL in the case of a plain
 	 'break', without arguments.  */
-      char *addr_string = (canonical->addr_string
-			   ? xstrdup (canonical->addr_string)
-			   : NULL);
-      char *filter_string = lsal->canonical ? xstrdup (lsal->canonical) : NULL;
-      struct cleanup *inner = make_cleanup (xfree, addr_string);
-
-      make_cleanup (xfree, filter_string);
+      struct event_location *location
+	= (canonical->location
+	   ? copy_event_location (canonical->location) : NULL);
+      struct event_location *filter
+	= lsal->canonical ? copy_event_location (lsal->canonical) : NULL;
+      struct cleanup *inner
+	= make_cleanup (delete_event_location, location);
+
+      make_cleanup (delete_event_location, filter);
       create_breakpoint_sal (gdbarch, lsal->sals,
-			     addr_string,
-			     filter_string,
+			     location, filter,
 			     cond_string, extra_string,
 			     type, disposition,
 			     thread, task, ignore_count, ops,
@@ -9228,22 +9328,25 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
     }
 }
 
-/* Parse ADDRESS which is assumed to be a SAL specification possibly
+/* Parse LOCATION which is assumed to be a SAL specification possibly
    followed by conditionals.  On return, SALS contains an array of SAL
-   addresses found.  ADDR_STRING contains a vector of (canonical)
-   address strings.  ADDRESS points to the end of the SAL.
+   addresses found.  LOCATION points to the end of the SAL (for
+   linespec locations).
 
    The array and the line spec strings are allocated on the heap, it is
    the caller's responsibility to free them.  */
 
 static void
-parse_breakpoint_sals (char **address,
+parse_breakpoint_sals (struct event_location *location,
 		       struct linespec_result *canonical)
 {
+  const char *address = event_location_to_string (location);
+
   /* If no arg given, or if first arg is 'if ', use the default
      breakpoint.  */
-  if ((*address) == NULL
-      || (strncmp ((*address), "if", 2) == 0 && isspace ((*address)[2])))
+  if (EVENT_LOCATION_TYPE (location) == EVENT_LOCATION_LINESPEC
+      && (address == NULL
+	  || (strncmp (address, "if", 2) == 0 && isspace (address[2]))))
     {
       /* The last displayed codepoint, if it's valid, is our default breakpoint
          address.  */
@@ -9296,14 +9399,15 @@ parse_breakpoint_sals (char **address,
 	 may have a '+' or '-' succeeded by a '['.  */
       if (last_displayed_sal_is_valid ()
 	  && (!cursal.symtab
-	      || ((strchr ("+-", (*address)[0]) != NULL)
-		  && ((*address)[1] != '['))))
-	decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
+	      || (address != NULL
+		  && strchr ("+-", address[0]) != NULL
+		  && address[1] != '[')))
+	decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
 			  get_last_displayed_symtab (),
 			  get_last_displayed_line (),
 			  canonical, NULL, NULL);
       else
-	decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
+	decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
 			  cursal.symtab, cursal.line, canonical, NULL, NULL);
     }
 }
@@ -9508,7 +9612,7 @@ decode_static_tracepoint_spec (char **arg_p)
 
 int
 create_breakpoint (struct gdbarch *gdbarch,
-		   char *arg, char *cond_string,
+		   struct event_location *location, char *cond_string,
 		   int thread, char *extra_string,
 		   int parse_condition_and_thread,
 		   int tempflag, enum bptype type_wanted,
@@ -9519,23 +9623,22 @@ create_breakpoint (struct gdbarch *gdbarch,
 		   unsigned flags)
 {
   volatile struct gdb_exception e;
-  char *copy_arg = NULL;
-  char *addr_start = arg;
   struct linespec_result canonical;
   struct cleanup *old_chain;
   struct cleanup *bkpt_chain = NULL;
   int pending = 0;
   int task = 0;
   int prev_bkpt_count = breakpoint_count;
+  struct event_location copy_location;
 
   gdb_assert (ops != NULL);
 
   init_linespec_result (&canonical);
 
+  copy_location = *location;
   TRY_CATCH (e, RETURN_MASK_ALL)
     {
-      ops->create_sals_from_address (&arg, &canonical, type_wanted,
-				     addr_start, &copy_arg);
+      ops->create_sals_from_location (&copy_location, &canonical, type_wanted);
     }
 
   /* If caller is interested in rc value from parse, set value.  */
@@ -9572,8 +9675,17 @@ create_breakpoint (struct gdbarch *gdbarch,
 	  {
 	    struct linespec_sals lsal;
 
-	    copy_arg = xstrdup (addr_start);
-	    lsal.canonical = xstrdup (copy_arg);
+	    /* If the location has a string representation,
+	       save it to the location's save spec, since this
+	       may be used to save the breakpoint to a file.  */
+	    if (EVENT_LOCATION_SAVE_SPEC (location) == NULL
+		&& event_location_to_string (location) != NULL)
+	      {
+		EVENT_LOCATION_SAVE_SPEC (location)
+		  = xstrdup (event_location_to_string (location));
+	      }
+
+	    lsal.canonical = copy_event_location (location);
 	    lsal.sals.nelts = 1;
 	    lsal.sals.sals = XNEW (struct symtab_and_line);
 	    init_sal (&lsal.sals.sals[0]);
@@ -9630,20 +9742,30 @@ create_breakpoint (struct gdbarch *gdbarch,
 
       if (parse_condition_and_thread)
         {
-	    char *rest;
-            /* Here we only parse 'arg' to separate condition
-               from thread number, so parsing in context of first
-               sal is OK.  When setting the breakpoint we'll 
-               re-parse it in context of each sal.  */
-
-            find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
-                                       &thread, &task, &rest);
-            if (cond_string)
-                make_cleanup (xfree, cond_string);
-	    if (rest)
-	      make_cleanup (xfree, rest);
-	    if (rest)
-	      extra_string = rest;
+	  char *rest;
+	  const char *arg;
+
+	  if (EVENT_LOCATION_TYPE (&copy_location) == EVENT_LOCATION_LINESPEC)
+	    arg = EVENT_LOCATION_LINESPEC (&copy_location);
+	  else
+	    {
+	      arg = extra_string;
+	      extra_string = NULL;
+	    }
+
+	  /* Here we only parse the location to separate condition
+	     from thread number, so parsing in context of first
+	     sal is OK.  When setting the breakpoint we'll
+	     re-parse it in context of each sal.  */
+	  find_condition_and_thread (arg, lsal->sals.sals[0].pc,
+				     &cond_string, &thread, &task, &rest);
+
+	  if (cond_string)
+	    make_cleanup (xfree, cond_string);
+	  if (rest)
+	    make_cleanup (xfree, rest);
+	  if (rest)
+	    extra_string = rest;
         }
       else
         {
@@ -9671,8 +9793,6 @@ create_breakpoint (struct gdbarch *gdbarch,
     {
       struct breakpoint *b;
 
-      make_cleanup (xfree, copy_arg);
-
       if (is_tracepoint_type (type_wanted))
 	{
 	  struct tracepoint *t;
@@ -9684,8 +9804,8 @@ create_breakpoint (struct gdbarch *gdbarch,
 	b = XNEW (struct breakpoint);
 
       init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
+      b->location = copy_event_location (location);
 
-      b->addr_string = copy_arg;
       if (parse_condition_and_thread)
 	b->cond_string = NULL;
       else
@@ -9698,7 +9818,13 @@ create_breakpoint (struct gdbarch *gdbarch,
 	    }
 	  b->cond_string = cond_string;
 	}
-      b->extra_string = NULL;
+      if (extra_string != NULL && *extra_string != '\0')
+	{
+	  b->extra_string = xstrdup (extra_string);
+	  make_cleanup (xfree, b->extra_string);
+	}
+      else
+	b->extra_string = NULL;
       b->ignore_count = ignore_count;
       b->disposition = tempflag ? disp_del : disp_donttouch;
       b->condition_not_parsed = 1;
@@ -9745,6 +9871,8 @@ break_command_1 (char *arg, int flag, int from_tty)
 			     : bp_breakpoint);
   struct breakpoint_ops *ops;
   const char *arg_cp = arg;
+  struct event_location *location;
+  struct cleanup *cleanup;
 
   /* Matching breakpoints on probes.  */
   if (arg && probe_linespec_to_ops (&arg_cp) != NULL)
@@ -9752,9 +9880,12 @@ break_command_1 (char *arg, int flag, int from_tty)
   else
     ops = &bkpt_breakpoint_ops;
 
+  location = string_to_event_location (&arg, current_language);
+  cleanup = make_cleanup (delete_event_location, location);
+
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     tempflag, type_wanted,
 		     0 /* Ignore count */,
 		     pending_break_support,
@@ -9763,6 +9894,7 @@ break_command_1 (char *arg, int flag, int from_tty)
 		     1 /* enabled */,
 		     0 /* internal */,
 		     0);
+  do_cleanups (cleanup);
 }
 
 /* Helper function for break_command_1 and disassemble_command.  */
@@ -9927,9 +10059,15 @@ stopat_command (char *arg, int from_tty)
 static void
 dprintf_command (char *arg, int from_tty)
 {
+  struct event_location *location;
+  struct cleanup *cleanup;
+
+  location = string_to_event_location (&arg, current_language);
+  cleanup = make_cleanup (delete_event_location, location);
+
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     0, bp_dprintf,
 		     0 /* Ignore count */,
 		     pending_break_support,
@@ -9938,6 +10076,7 @@ dprintf_command (char *arg, int from_tty)
 		     1 /* enabled */,
 		     0 /* internal */,
 		     0);
+  do_cleanups (cleanup);
 }
 
 static void
@@ -10082,8 +10221,9 @@ print_mention_ranged_breakpoint (struct breakpoint *b)
 static void
 print_recreate_ranged_breakpoint (struct breakpoint *b, struct ui_file *fp)
 {
-  fprintf_unfiltered (fp, "break-range %s, %s", b->addr_string,
-		      b->addr_string_range_end);
+  fprintf_unfiltered (fp, "break-range %s, %s",
+		      EVENT_LOCATION_SAVE_SPEC (b->location),
+		      EVENT_LOCATION_SAVE_SPEC (b->location_range_end));
   print_recreate_thread (b, fp);
 }
 
@@ -10134,6 +10274,7 @@ break_range_command (char *arg, int from_tty)
   struct symtab_and_line sal_start, sal_end;
   struct cleanup *cleanup_bkpt;
   struct linespec_sals *lsal_start, *lsal_end;
+  struct event_location *start_location, *end_location, copy_location;
 
   /* We don't support software ranged breakpoints.  */
   if (target_ranged_break_num_registers () < 0)
@@ -10153,9 +10294,13 @@ break_range_command (char *arg, int from_tty)
   init_linespec_result (&canonical_start);
 
   arg_start = arg;
-  parse_breakpoint_sals (&arg, &canonical_start);
-
-  cleanup_bkpt = make_cleanup_destroy_linespec_result (&canonical_start);
+  start_location = string_to_event_location (&arg, current_language);
+  cleanup_bkpt = make_cleanup (delete_event_location, start_location);
+  copy_location = *start_location;
+  parse_breakpoint_sals (&copy_location, &canonical_start);
+  make_cleanup_destroy_linespec_result (&canonical_start);
+  if (EVENT_LOCATION_TYPE (&copy_location) == EVENT_LOCATION_LINESPEC)
+    arg = EVENT_LOCATION_LINESPEC (&copy_location);
 
   if (arg[0] != ',')
     error (_("Too few arguments."));
@@ -10185,7 +10330,10 @@ break_range_command (char *arg, int from_tty)
      symtab and line as the default symtab and line for the end of the
      range.  This makes it possible to have ranges like "foo.c:27, +14",
      where +14 means 14 lines from the start location.  */
-  decode_line_full (&arg, DECODE_LINE_FUNFIRSTLINE,
+  end_location = string_to_event_location (&arg, current_language);
+  make_cleanup (delete_event_location, end_location);
+  copy_location = *end_location;
+  decode_line_full (&copy_location, DECODE_LINE_FUNFIRSTLINE,
 		    sal_start.symtab, sal_start.line,
 		    &canonical_end, NULL, NULL);
 
@@ -10200,8 +10348,6 @@ break_range_command (char *arg, int from_tty)
     error (_("Cannot create a ranged breakpoint with multiple locations."));
 
   sal_end = lsal_end->sals.sals[0];
-  addr_string_end = savestring (arg_start, arg - arg_start);
-  make_cleanup (xfree, addr_string_end);
 
   end = find_breakpoint_range_end (sal_end);
   if (sal_start.pc > end)
@@ -10228,8 +10374,8 @@ break_range_command (char *arg, int from_tty)
   set_breakpoint_count (breakpoint_count + 1);
   b->number = breakpoint_count;
   b->disposition = disp_donttouch;
-  b->addr_string = xstrdup (addr_string_start);
-  b->addr_string_range_end = xstrdup (addr_string_end);
+  b->location = copy_event_location (start_location);
+  b->location_range_end = copy_event_location (end_location);
   b->loc->length = length;
 
   do_cleanups (cleanup_bkpt);
@@ -11333,26 +11479,34 @@ until_break_command (char *arg, int from_tty, int anywhere)
   struct frame_id caller_frame_id;
   struct breakpoint *breakpoint;
   struct breakpoint *breakpoint2 = NULL;
-  struct cleanup *old_chain;
+  struct cleanup *old_chain, *cleanup;
   int thread;
   struct thread_info *tp;
+  struct event_location *location, copy_location;
 
   clear_proceed_status ();
 
   /* Set a breakpoint where the user wants it and at return from
      this function.  */
 
+  location = string_to_event_location (&arg, current_language);
+  copy_location = *location;
+  cleanup = make_cleanup (delete_event_location, location);
+
   if (last_displayed_sal_is_valid ())
-    sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
+    sals = decode_line_1 (&copy_location, DECODE_LINE_FUNFIRSTLINE,
 			  get_last_displayed_symtab (),
 			  get_last_displayed_line ());
   else
-    sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
+    sals = decode_line_1 (&copy_location, DECODE_LINE_FUNFIRSTLINE,
 			  (struct symtab *) NULL, 0);
 
   if (sals.nelts != 1)
     error (_("Couldn't get information on specified line."));
 
+  if (EVENT_LOCATION_TYPE (&copy_location) == EVENT_LOCATION_LINESPEC)
+    arg = EVENT_LOCATION_LINESPEC (&copy_location);
+
   sal = sals.sals[0];
   xfree (sals.sals);	/* malloc'd, so freed.  */
 
@@ -11433,6 +11587,8 @@ until_break_command (char *arg, int from_tty, int anywhere)
     }
   else
     do_cleanups (old_chain);
+
+  do_cleanups (cleanup);
 }
 
 /* This function attempts to parse an optional "if <cond>" clause
@@ -11565,7 +11721,8 @@ print_it_exception_catchpoint (bpstat bs)
 
   annotate_catchpoint (b->number);
 
-  bp_throw = strstr (b->addr_string, "throw") != NULL;
+  bp_throw
+    = strstr (event_location_to_string (b->location), "throw") != NULL;
   if (b->loc->address != b->loc->requested_address)
     breakpoint_adjustment_warning (b->loc->requested_address,
 	                           b->loc->address,
@@ -11609,7 +11766,7 @@ print_one_exception_catchpoint (struct breakpoint *b,
   annotate_field (5);
   if (b->loc)
     *last_loc = b->loc;
-  if (strstr (b->addr_string, "throw") != NULL)
+  if (strstr (event_location_to_string (b->location), "throw") != NULL)
     {
       ui_out_field_string (uiout, "what", "exception throw");
       if (ui_out_is_mi_like_p (uiout))
@@ -11631,7 +11788,8 @@ print_mention_exception_catchpoint (struct breakpoint *b)
   int bp_throw;
 
   bp_temp = b->disposition == disp_del;
-  bp_throw = strstr (b->addr_string, "throw") != NULL;
+  bp_throw
+    = strstr (event_location_to_string (b->location), "throw") != NULL;
   ui_out_text (uiout, bp_temp ? _("Temporary catchpoint ")
 			      : _("Catchpoint "));
   ui_out_field_int (uiout, "bkptno", b->number);
@@ -11650,7 +11808,8 @@ print_recreate_exception_catchpoint (struct breakpoint *b,
   int bp_throw;
 
   bp_temp = b->disposition == disp_del;
-  bp_throw = strstr (b->addr_string, "throw") != NULL;
+  bp_throw
+    = strstr (EVENT_LOCATION_SAVE_SPEC (b->location), "throw") != NULL;
   fprintf_unfiltered (fp, bp_temp ? "tcatch " : "catch ");
   fprintf_unfiltered (fp, bp_throw ? "throw" : "catch");
   print_recreate_thread (b, fp);
@@ -11662,15 +11821,16 @@ static int
 handle_gnu_v3_exceptions (int tempflag, char *cond_string,
 			  enum exception_event_kind ex_event, int from_tty)
 {
-  char *trigger_func_name;
+  struct event_location location;
  
+  initialize_event_location (&location, EVENT_LOCATION_LINESPEC);
   if (ex_event == EX_EVENT_CATCH)
-    trigger_func_name = "__cxa_begin_catch";
+    EVENT_LOCATION_LINESPEC (&location) = "__cxa_begin_catch";
   else
-    trigger_func_name = "__cxa_throw";
+    EVENT_LOCATION_LINESPEC (&location) = "__cxa_throw";
 
   create_breakpoint (get_current_arch (),
-		     trigger_func_name, cond_string, -1, NULL,
+		     &location, cond_string, -1, NULL,
 		     0 /* condition and thread are valid.  */,
 		     tempflag, bp_breakpoint,
 		     0,
@@ -11761,7 +11921,8 @@ init_ada_exception_breakpoint (struct breakpoint *b,
 
   b->enable_state = bp_enabled;
   b->disposition = tempflag ? disp_del : disp_donttouch;
-  b->addr_string = addr_string;
+  b->location = string_to_event_location (&addr_string,
+					  language_def (language_ada));
   b->language = language_ada;
 }
 
@@ -12728,7 +12889,8 @@ say_where (struct breakpoint *b)
      single string.  */
   if (b->loc == NULL)
     {
-      printf_filtered (_(" (%s) pending."), b->addr_string);
+      printf_filtered (_(" (%s) pending."),
+		       event_location_to_string (b->location));
     }
   else
     {
@@ -12750,7 +12912,8 @@ say_where (struct breakpoint *b)
 	    /* This is not ideal, but each location may have a
 	       different file name, and this at least reflects the
 	       real situation somewhat.  */
-	    printf_filtered (": %s.", b->addr_string);
+	    printf_filtered (": %s.",
+			     event_location_to_string (b->location));
 	}
 
       if (b->loc->next)
@@ -12789,9 +12952,9 @@ base_breakpoint_dtor (struct breakpoint *self)
   decref_counted_command_line (&self->commands);
   xfree (self->cond_string);
   xfree (self->extra_string);
-  xfree (self->addr_string);
-  xfree (self->filter);
-  xfree (self->addr_string_range_end);
+  delete_event_location (self->filter);
+  delete_event_location (self->location);
+  delete_event_location (self->location_range_end);
 }
 
 static struct bp_location *
@@ -12884,11 +13047,9 @@ base_breakpoint_print_recreate (struct breakpoint *b, struct ui_file *fp)
 }
 
 static void
-base_breakpoint_create_sals_from_address (char **arg,
-					  struct linespec_result *canonical,
-					  enum bptype type_wanted,
-					  char *addr_start,
-					  char **copy_arg)
+base_breakpoint_create_sals_from_location (struct event_location *location,
+					   struct linespec_result *canonical,
+					   enum bptype type_wanted)
 {
   internal_error_pure_virtual_called ();
 }
@@ -12911,7 +13072,8 @@ base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-base_breakpoint_decode_linespec (struct breakpoint *b, char **s,
+base_breakpoint_decode_location (struct breakpoint *b,
+				 struct event_location *location,
 				 struct symtabs_and_lines *sals)
 {
   internal_error_pure_virtual_called ();
@@ -12941,9 +13103,9 @@ struct breakpoint_ops base_breakpoint_ops =
   base_breakpoint_print_one_detail,
   base_breakpoint_print_mention,
   base_breakpoint_print_recreate,
-  base_breakpoint_create_sals_from_address,
+  base_breakpoint_create_sals_from_location,
   base_breakpoint_create_breakpoints_sal,
-  base_breakpoint_decode_linespec,
+  base_breakpoint_decode_location,
   base_breakpoint_explains_signal
 };
 
@@ -12953,7 +13115,8 @@ static void
 bkpt_re_set (struct breakpoint *b)
 {
   /* FIXME: is this still reachable?  */
-  if (b->addr_string == NULL)
+  if (EVENT_LOCATION_TYPE (b->location) == EVENT_LOCATION_LINESPEC
+       && EVENT_LOCATION_LINESPEC (b->location) == NULL)
     {
       /* Anything without a string can't be re-set.  */
       delete_breakpoint (b);
@@ -13094,18 +13257,17 @@ bkpt_print_recreate (struct breakpoint *tp, struct ui_file *fp)
     internal_error (__FILE__, __LINE__,
 		    _("unhandled breakpoint type %d"), (int) tp->type);
 
-  fprintf_unfiltered (fp, " %s", tp->addr_string);
+  fprintf_unfiltered (fp, " %s",
+		      EVENT_LOCATION_SAVE_SPEC (tp->location));
   print_recreate_thread (tp, fp);
 }
 
 static void
-bkpt_create_sals_from_address (char **arg,
-			       struct linespec_result *canonical,
-			       enum bptype type_wanted,
-			       char *addr_start, char **copy_arg)
+bkpt_create_sals_from_location (struct event_location *location,
+				struct linespec_result *canonical,
+				enum bptype type_wanted)
 {
-  create_sals_from_address_default (arg, canonical, type_wanted,
-				    addr_start, copy_arg);
+  create_sals_from_location_default (location, canonical, type_wanted);
 }
 
 static void
@@ -13131,10 +13293,11 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-bkpt_decode_linespec (struct breakpoint *b, char **s,
+bkpt_decode_location (struct breakpoint *b,
+		      struct event_location *location,
 		      struct symtabs_and_lines *sals)
 {
-  decode_linespec_default (b, s, sals);
+  decode_location_default (b, location, sals);
 }
 
 /* Virtual table for internal breakpoints.  */
@@ -13329,26 +13492,23 @@ bkpt_probe_remove_location (struct bp_location *bl)
 }
 
 static void
-bkpt_probe_create_sals_from_address (char **arg,
-				     struct linespec_result *canonical,
-				     enum bptype type_wanted,
-				     char *addr_start, char **copy_arg)
+bkpt_probe_create_sals_from_location (struct event_location *location,
+				      struct linespec_result *canonical,
+				      enum bptype type_wanted)
 {
   struct linespec_sals lsal;
 
-  lsal.sals = parse_probes (arg, canonical);
-
-  *copy_arg = xstrdup (canonical->addr_string);
-  lsal.canonical = xstrdup (*copy_arg);
-
+  lsal.sals = parse_probes (location, canonical);
+  lsal.canonical = copy_event_location (canonical->location);
   VEC_safe_push (linespec_sals, canonical->sals, &lsal);
 }
 
 static void
-bkpt_probe_decode_linespec (struct breakpoint *b, char **s,
+bkpt_probe_decode_location (struct breakpoint *b,
+			    struct event_location *location,
 			    struct symtabs_and_lines *sals)
 {
-  *sals = parse_probes (s, NULL);
+  *sals = parse_probes (location, NULL);
   if (!sals->sals)
     error (_("probe not found"));
 }
@@ -13430,7 +13590,8 @@ tracepoint_print_recreate (struct breakpoint *self, struct ui_file *fp)
     internal_error (__FILE__, __LINE__,
 		    _("unhandled tracepoint type %d"), (int) self->type);
 
-  fprintf_unfiltered (fp, " %s", self->addr_string);
+  fprintf_unfiltered (fp, " %s",
+		      EVENT_LOCATION_SAVE_SPEC (self->location));
   print_recreate_thread (self, fp);
 
   if (tp->pass_count)
@@ -13438,13 +13599,11 @@ tracepoint_print_recreate (struct breakpoint *self, struct ui_file *fp)
 }
 
 static void
-tracepoint_create_sals_from_address (char **arg,
-				     struct linespec_result *canonical,
-				     enum bptype type_wanted,
-				     char *addr_start, char **copy_arg)
+tracepoint_create_sals_from_location (struct event_location *location,
+				      struct linespec_result *canonical,
+				      enum bptype type_wanted)
 {
-  create_sals_from_address_default (arg, canonical, type_wanted,
-				    addr_start, copy_arg);
+  create_sals_from_location_default (location, canonical, type_wanted);
 }
 
 static void
@@ -13470,10 +13629,11 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-tracepoint_decode_linespec (struct breakpoint *b, char **s,
+tracepoint_decode_location (struct breakpoint *b,
+			    struct event_location *location,
 			    struct symtabs_and_lines *sals)
 {
-  decode_linespec_default (b, s, sals);
+  decode_location_default (b, location, sals);
 }
 
 struct breakpoint_ops tracepoint_breakpoint_ops;
@@ -13482,22 +13642,21 @@ struct breakpoint_ops tracepoint_breakpoint_ops;
    static probe.  */
 
 static void
-tracepoint_probe_create_sals_from_address (char **arg,
-					   struct linespec_result *canonical,
-					   enum bptype type_wanted,
-					   char *addr_start, char **copy_arg)
+tracepoint_probe_create_sals_from_location (struct event_location *location,
+					    struct linespec_result *canonical,
+					    enum bptype type_wanted)
 {
   /* We use the same method for breakpoint on probes.  */
-  bkpt_probe_create_sals_from_address (arg, canonical, type_wanted,
-				       addr_start, copy_arg);
+  bkpt_probe_create_sals_from_location (location, canonical, type_wanted);
 }
 
 static void
-tracepoint_probe_decode_linespec (struct breakpoint *b, char **s,
+tracepoint_probe_decode_location (struct breakpoint *b,
+				  struct event_location *location,
 				  struct symtabs_and_lines *sals)
 {
   /* We use the same method for breakpoint on probes.  */
-  bkpt_probe_decode_linespec (b, s, sals);
+  bkpt_probe_decode_location (b, location, sals);
 }
 
 static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
@@ -13506,19 +13665,25 @@ static struct breakpoint_ops tracepoint_probe_breakpoint_ops;
    markers (`-m').  */
 
 static void
-strace_marker_create_sals_from_address (char **arg,
-					struct linespec_result *canonical,
-					enum bptype type_wanted,
-					char *addr_start, char **copy_arg)
+strace_marker_create_sals_from_location (struct event_location *location,
+					 struct linespec_result *canonical,
+					 enum bptype type_wanted)
 {
   struct linespec_sals lsal;
+  char *arg_start, *arg;
 
-  lsal.sals = decode_static_tracepoint_spec (arg);
+  arg = arg_start = EVENT_LOCATION_LINESPEC (location);
+  lsal.sals = decode_static_tracepoint_spec (&arg);
 
-  *copy_arg = savestring (addr_start, *arg - addr_start);
+  if (canonical != NULL)
+    {
+      canonical->location = new_event_location (EVENT_LOCATION_LINESPEC);
+      EVENT_LOCATION_LINESPEC (canonical->location)
+	= savestring (arg_start, arg - arg_start);
+    }
 
-  canonical->addr_string = xstrdup (*copy_arg);
-  lsal.canonical = xstrdup (*copy_arg);
+  EVENT_LOCATION_LINESPEC (location) = arg;
+  lsal.canonical = copy_event_location (canonical->location);
   VEC_safe_push (linespec_sals, canonical->sals, &lsal);
 }
 
@@ -13550,17 +13715,17 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
       struct symtabs_and_lines expanded;
       struct tracepoint *tp;
       struct cleanup *old_chain;
-      char *addr_string;
+      struct event_location *location;
 
       expanded.nelts = 1;
       expanded.sals = &lsal->sals.sals[i];
 
-      addr_string = xstrdup (canonical->addr_string);
-      old_chain = make_cleanup (xfree, addr_string);
+      location = copy_event_location (canonical->location);
+      old_chain = make_cleanup (delete_event_location, location);
 
       tp = XCNEW (struct tracepoint);
       init_breakpoint_sal (&tp->base, gdbarch, expanded,
-			   addr_string, NULL,
+			   location, NULL,
 			   cond_string, extra_string,
 			   type_wanted, disposition,
 			   thread, task, ignore_count, ops,
@@ -13581,12 +13746,14 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
 }
 
 static void
-strace_marker_decode_linespec (struct breakpoint *b, char **s,
+strace_marker_decode_location (struct breakpoint *b,
+			       struct event_location *location,
 			       struct symtabs_and_lines *sals)
 {
   struct tracepoint *tp = (struct tracepoint *) b;
+  char *s = EVENT_LOCATION_LINESPEC (location);
 
-  *sals = decode_static_tracepoint_spec (s);
+  *sals = decode_static_tracepoint_spec (&s);
   if (sals->nelts > tp->static_trace_marker_id_idx)
     {
       sals->sals[0] = sals->sals[tp->static_trace_marker_id_idx];
@@ -13962,10 +14129,12 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
 	  b->loc->line_number = sal2.line;
 	  b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
 
-	  xfree (b->addr_string);
-	  b->addr_string = xstrprintf ("%s:%d",
-				   symtab_to_filename_for_display (sal2.symtab),
-				       b->loc->line_number);
+	  delete_event_location (b->location);
+	  b->location = new_event_location (EVENT_LOCATION_LINESPEC);
+	  EVENT_LOCATION_LINESPEC (b->location)
+	    = xstrprintf ("%s:%d",
+			  symtab_to_filename_for_display (sal2.symtab),
+			  b->loc->line_number);
 
 	  /* Might be nice to check if function changed, and warn if
 	     so.  */
@@ -14126,22 +14295,24 @@ update_breakpoint_locations (struct breakpoint *b,
   update_global_location_list (1);
 }
 
-/* Find the SaL locations corresponding to the given ADDR_STRING.
+/* Find the SaL locations corresponding to the given LOCATION.
    On return, FOUND will be 1 if any SaL was found, zero otherwise.  */
 
 static struct symtabs_and_lines
-addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
+location_to_sals (struct breakpoint *b, struct event_location *location,
+		  int *found)
 {
-  char *s;
   struct symtabs_and_lines sals = {0};
   volatile struct gdb_exception e;
+  const char *prev;
 
   gdb_assert (b->ops != NULL);
-  s = addr_string;
+
+  prev = event_location_to_string (location);
 
   TRY_CATCH (e, RETURN_MASK_ERROR)
     {
-      b->ops->decode_linespec (b, &s, &sals);
+      b->ops->decode_location (b, location, &sals);
     }
   if (e.reason < 0)
     {
@@ -14176,25 +14347,56 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
   if (e.reason == 0 || e.error != NOT_FOUND_ERROR)
     {
       int i;
+      const char *s;
 
       for (i = 0; i < sals.nelts; ++i)
 	resolve_sal_pc (&sals.sals[i]);
-      if (b->condition_not_parsed && s && s[0])
+      if (b->condition_not_parsed)
 	{
-	  char *cond_string, *extra_string;
-	  int thread, task;
+	  if (EVENT_LOCATION_TYPE (location) == EVENT_LOCATION_LINESPEC)
+	    s = EVENT_LOCATION_LINESPEC (location);
+	  else
+	    {
+	      s = b->extra_string;
+	      b->extra_string = NULL;
+	    }
 
-	  find_condition_and_thread (s, sals.sals[0].pc,
-				     &cond_string, &thread, &task,
-				     &extra_string);
-	  if (cond_string)
-	    b->cond_string = cond_string;
-	  b->thread = thread;
-	  b->task = task;
+	  if (s != NULL && *s != '\0')
+	    {
+	      char *cond_string, *extra_string;
+	      int thread, task;
+	      const char *orig = s;
+
+	      find_condition_and_thread (s, sals.sals[0].pc,
+					 &cond_string, &thread, &task,
+					 &extra_string);
+	      if (cond_string != NULL)
+		b->cond_string = cond_string;
+	      b->thread = thread;
+	      b->task = task;
+	      if (extra_string != NULL)
+		{
+		  xfree (b->extra_string);
+		  b->extra_string = extra_string;
+		}
+	      b->condition_not_parsed = 0;
 
-	  if (extra_string)
-	    b->extra_string = extra_string;
-	  b->condition_not_parsed = 0;
+	      /* For pending breakpoints which were just resolved, reset the
+		 location's save spec.  */
+	      if (b->loc == NULL)
+		{
+		  size_t len;
+		  char *p, *str;
+		  char *old = EVENT_LOCATION_SAVE_SPEC (location);
+
+		  len = orig - prev;
+		  str = savestring (prev, len);
+		  p = remove_trailing_whitespace (str, str + len);
+		  *p = '\0';
+		  EVENT_LOCATION_SAVE_SPEC (b->location) = str;
+		  xfree (old);
+		}
+	    }
 	}
 
       if (b->type == bp_static_tracepoint && !strace_marker_p (b))
@@ -14219,17 +14421,20 @@ breakpoint_re_set_default (struct breakpoint *b)
   struct symtabs_and_lines sals, sals_end;
   struct symtabs_and_lines expanded = {0};
   struct symtabs_and_lines expanded_end = {0};
+  struct event_location location;
 
-  sals = addr_string_to_sals (b, b->addr_string, &found);
+  location = *b->location;
+  sals = location_to_sals (b, &location, &found);
   if (found)
     {
       make_cleanup (xfree, sals.sals);
       expanded = sals;
     }
 
-  if (b->addr_string_range_end)
+  if (b->location_range_end != NULL)
     {
-      sals_end = addr_string_to_sals (b, b->addr_string_range_end, &found);
+      location = *b->location_range_end;
+      sals_end = location_to_sals (b, &location, &found);
       if (found)
 	{
 	  make_cleanup (xfree, sals_end.sals);
@@ -14244,12 +14449,11 @@ breakpoint_re_set_default (struct breakpoint *b)
    calls parse_breakpoint_sals.  Return 1 for success, zero for failure.  */
 
 static void
-create_sals_from_address_default (char **arg,
-				  struct linespec_result *canonical,
-				  enum bptype type_wanted,
-				  char *addr_start, char **copy_arg)
+create_sals_from_location_default (struct event_location *location,
+				   struct linespec_result *canonical,
+				   enum bptype type_wanted)
 {
-  parse_breakpoint_sals (arg, canonical);
+  parse_breakpoint_sals (location, canonical);
 }
 
 /* Call create_breakpoints_sal for the given arguments.  This is the default
@@ -14278,16 +14482,17 @@ create_breakpoints_sal_default (struct gdbarch *gdbarch,
 }
 
 /* Decode the line represented by S by calling decode_line_full.  This is the
-   default function for the `decode_linespec' method of breakpoint_ops.  */
+   default function for the `decode_location' method of breakpoint_ops.  */
 
 static void
-decode_linespec_default (struct breakpoint *b, char **s,
+decode_location_default (struct breakpoint *b,
+			 struct event_location *location,
 			 struct symtabs_and_lines *sals)
 {
   struct linespec_result canonical;
 
   init_linespec_result (&canonical);
-  decode_line_full (s, DECODE_LINE_FUNFIRSTLINE,
+  decode_line_full (location, DECODE_LINE_FUNFIRSTLINE,
 		    (struct symtab *) NULL, 0,
 		    &canonical, multiple_symbols_all,
 		    b->filter);
@@ -15111,6 +15316,8 @@ static void
 trace_command (char *arg, int from_tty)
 {
   struct breakpoint_ops *ops;
+  struct event_location *location, copy_location;
+  struct cleanup *back_to;
   const char *arg_cp = arg;
 
   if (arg && probe_linespec_to_ops (&arg_cp))
@@ -15118,9 +15325,12 @@ trace_command (char *arg, int from_tty)
   else
     ops = &tracepoint_breakpoint_ops;
 
+  location = string_to_event_location (&arg, current_language);
+  back_to = make_cleanup (delete_event_location, location);
+  copy_location = *location;
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     &copy_location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     0 /* tempflag */,
 		     bp_tracepoint /* type_wanted */,
 		     0 /* Ignore count */,
@@ -15129,14 +15339,21 @@ trace_command (char *arg, int from_tty)
 		     from_tty,
 		     1 /* enabled */,
 		     0 /* internal */, 0);
+  do_cleanups (back_to);
 }
 
 static void
 ftrace_command (char *arg, int from_tty)
 {
+  struct event_location *location, copy_location;
+  struct cleanup *back_to;
+
+  location = string_to_event_location (&arg, current_language);
+  back_to = make_cleanup (delete_event_location, location);
+  copy_location = *location;
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     &copy_location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     0 /* tempflag */,
 		     bp_fast_tracepoint /* type_wanted */,
 		     0 /* Ignore count */,
@@ -15145,6 +15362,7 @@ ftrace_command (char *arg, int from_tty)
 		     from_tty,
 		     1 /* enabled */,
 		     0 /* internal */, 0);
+  do_cleanups (back_to);
 }
 
 /* strace command implementation.  Creates a static tracepoint.  */
@@ -15153,6 +15371,8 @@ static void
 strace_command (char *arg, int from_tty)
 {
   struct breakpoint_ops *ops;
+  struct event_location *location, copy_location;
+  struct cleanup *back_to;
 
   /* Decide if we are dealing with a static tracepoint marker (`-m'),
      or with a normal static tracepoint.  */
@@ -15161,9 +15381,12 @@ strace_command (char *arg, int from_tty)
   else
     ops = &tracepoint_breakpoint_ops;
 
+  location = string_to_event_location (&arg, current_language);
+  back_to = make_cleanup (delete_event_location, location);
+  copy_location = *location;
   create_breakpoint (get_current_arch (),
-		     arg,
-		     NULL, 0, NULL, 1 /* parse arg */,
+		     &copy_location,
+		     NULL, 0, arg, 1 /* parse arg */,
 		     0 /* tempflag */,
 		     bp_static_tracepoint /* type_wanted */,
 		     0 /* Ignore count */,
@@ -15172,6 +15395,7 @@ strace_command (char *arg, int from_tty)
 		     from_tty,
 		     1 /* enabled */,
 		     0 /* internal */, 0);
+  do_cleanups (back_to);
 }
 
 /* Set up a fake reader function that gets command lines from a linked
@@ -15203,6 +15427,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
 {
   char *addr_str, small_buf[100];
   struct tracepoint *tp;
+  struct event_location *location;
+  struct cleanup *cleanup;
 
   if (utp->at_string)
     addr_str = utp->at_string;
@@ -15225,8 +15451,10 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
 	       "has no source form, ignoring it"),
 	     utp->number);
 
+  location = string_to_event_location (&addr_str, current_language);
+  cleanup = make_cleanup (delete_event_location, location);
   if (!create_breakpoint (get_current_arch (),
-			  addr_str,
+			  location,
 			  utp->cond_string, -1, NULL,
 			  0 /* parse cond/thread */,
 			  0 /* tempflag */,
@@ -15238,7 +15466,12 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
 			  utp->enabled /* enabled */,
 			  0 /* internal */,
 			  CREATE_BREAKPOINT_FLAGS_INSERTED))
-    return NULL;
+    {
+      do_cleanups (cleanup);
+      return NULL;
+    }
+
+  do_cleanups (cleanup);
 
   /* Get the tracepoint we just created.  */
   tp = get_tracepoint (tracepoint_count);
@@ -15796,6 +16029,32 @@ pc_at_non_inline_function (struct address_space *aspace, CORE_ADDR pc,
   return 0;
 }
 
+/* Return a string representation of the LOCATION.
+   This function may return NULL for unspecified linespecs,
+   e.g, EVENT_LOCATION_LINESPEC and addr_string is NULL.  */
+
+const char *
+event_location_to_string (const struct event_location *location)
+{
+  const char *result = NULL;
+
+  switch (EVENT_LOCATION_TYPE (location))
+    {
+    case EVENT_LOCATION_LINESPEC:
+      result = EVENT_LOCATION_LINESPEC (location);
+      break;
+
+    case EVENT_LOCATION_ADDRESS:
+      result = EVENT_LOCATION_SAVE_SPEC (location);
+      break;
+
+    default:
+      gdb_assert_not_reached ("unknown event location type");
+    }
+
+  return result;
+}
+
 /* Remove any references to OBJFILE which is going to be freed.  */
 
 void
@@ -15828,9 +16087,9 @@ initialize_breakpoint_ops (void)
   ops->insert_location = bkpt_insert_location;
   ops->remove_location = bkpt_remove_location;
   ops->breakpoint_hit = bkpt_breakpoint_hit;
-  ops->create_sals_from_address = bkpt_create_sals_from_address;
+  ops->create_sals_from_location = bkpt_create_sals_from_location;
   ops->create_breakpoints_sal = bkpt_create_breakpoints_sal;
-  ops->decode_linespec = bkpt_decode_linespec;
+  ops->decode_location = bkpt_decode_location;
 
   /* The breakpoint_ops structure to be used in regular breakpoints.  */
   ops = &bkpt_breakpoint_ops;
@@ -15878,8 +16137,8 @@ initialize_breakpoint_ops (void)
   *ops = bkpt_breakpoint_ops;
   ops->insert_location = bkpt_probe_insert_location;
   ops->remove_location = bkpt_probe_remove_location;
-  ops->create_sals_from_address = bkpt_probe_create_sals_from_address;
-  ops->decode_linespec = bkpt_probe_decode_linespec;
+  ops->create_sals_from_location = bkpt_probe_create_sals_from_location;
+  ops->decode_location = bkpt_probe_decode_location;
 
   /* GNU v3 exception catchpoints.  */
   ops = &gnu_v3_exception_catchpoint_ops;
@@ -15924,22 +16183,22 @@ initialize_breakpoint_ops (void)
   ops->print_one_detail = tracepoint_print_one_detail;
   ops->print_mention = tracepoint_print_mention;
   ops->print_recreate = tracepoint_print_recreate;
-  ops->create_sals_from_address = tracepoint_create_sals_from_address;
+  ops->create_sals_from_location = tracepoint_create_sals_from_location;
   ops->create_breakpoints_sal = tracepoint_create_breakpoints_sal;
-  ops->decode_linespec = tracepoint_decode_linespec;
+  ops->decode_location = tracepoint_decode_location;
 
   /* Probe tracepoints.  */
   ops = &tracepoint_probe_breakpoint_ops;
   *ops = tracepoint_breakpoint_ops;
-  ops->create_sals_from_address = tracepoint_probe_create_sals_from_address;
-  ops->decode_linespec = tracepoint_probe_decode_linespec;
+  ops->create_sals_from_location = tracepoint_probe_create_sals_from_location;
+  ops->decode_location = tracepoint_probe_decode_location;
 
   /* Static tracepoints with marker (`-m').  */
   ops = &strace_marker_breakpoint_ops;
   *ops = tracepoint_breakpoint_ops;
-  ops->create_sals_from_address = strace_marker_create_sals_from_address;
+  ops->create_sals_from_location = strace_marker_create_sals_from_location;
   ops->create_breakpoints_sal = strace_marker_create_breakpoints_sal;
-  ops->decode_linespec = strace_marker_decode_linespec;
+  ops->decode_location = strace_marker_decode_location;
 
   /* Fork catchpoints.  */
   ops = &catch_fork_breakpoint_ops;
diff --git a/gdb/ax-gdb.c b/gdb/ax-gdb.c
index 4196655..c2115fd 100644
--- a/gdb/ax-gdb.c
+++ b/gdb/ax-gdb.c
@@ -2643,13 +2643,19 @@ agent_command_1 (char *exp, int eval)
       int ix;
       struct linespec_sals *iter;
       struct cleanup *old_chain;
+      struct event_location *location, copy_location;
 
       exp = skip_spaces (exp);
       init_linespec_result (&canonical);
-      decode_line_full (&exp, DECODE_LINE_FUNFIRSTLINE,
+      location = string_to_event_location (&exp, current_language);
+      copy_location = *location;
+      old_chain = make_cleanup (delete_event_location, location);
+      decode_line_full (&copy_location, DECODE_LINE_FUNFIRSTLINE,
 			(struct symtab *) NULL, 0, &canonical,
 			NULL, NULL);
-      old_chain = make_cleanup_destroy_linespec_result (&canonical);
+      make_cleanup_destroy_linespec_result (&canonical);
+      if (EVENT_LOCATION_TYPE (&copy_location) == EVENT_LOCATION_LINESPEC)
+	exp = EVENT_LOCATION_LINESPEC (&copy_location);
       exp = skip_spaces (exp);
       if (exp[0] == ',')
         {
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index c05f77f..313cb8e 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -751,7 +751,6 @@ edit_command (char *arg, int from_tty)
   struct symtabs_and_lines sals;
   struct symtab_and_line sal;
   struct symbol *sym;
-  char *arg1;
   char *editor;
   char *p;
   const char *fn;
@@ -773,21 +772,32 @@ edit_command (char *arg, int from_tty)
     }
   else
     {
-      /* Now should only be one argument -- decode it in SAL.  */
+      struct cleanup *cleanup;
+      struct event_location *location, copy_location;
+      char *arg1;
 
+      /* Now should only be one argument -- decode it in SAL.  */
       arg1 = arg;
-      sals = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, 0, 0);
+      location = string_to_event_location (&arg1, current_language);
+      cleanup = make_cleanup (delete_event_location, location);
+      copy_location = *location;
+      sals = decode_line_1 (&copy_location, DECODE_LINE_LIST_MODE, 0, 0);
+
+      if (EVENT_LOCATION_TYPE (&copy_location) == EVENT_LOCATION_LINESPEC)
+	arg1 = EVENT_LOCATION_LINESPEC (&copy_location);
 
       filter_sals (&sals);
       if (! sals.nelts)
 	{
 	  /*  C++  */
+	  do_cleanups (cleanup);
 	  return;
 	}
       if (sals.nelts > 1)
 	{
 	  ambiguous_line_spec (&sals);
 	  xfree (sals.sals);
+	  do_cleanups (cleanup);
 	  return;
 	}
 
@@ -830,6 +840,7 @@ edit_command (char *arg, int from_tty)
 
       if (sal.symtab == 0)
         error (_("No line number known for %s."), arg);
+      do_cleanups (cleanup);
     }
 
   if ((editor = (char *) getenv ("EDITOR")) == NULL)
@@ -858,6 +869,9 @@ list_command (char *arg, int from_tty)
   int dummy_beg = 0;
   int linenum_beg = 0;
   char *p;
+  struct cleanup *cleanup;
+
+  cleanup = make_cleanup (null_cleanup, NULL);
 
   /* Pull in the current default source line if necessary.  */
   if (arg == 0 || arg[0] == '+' || arg[0] == '-')
@@ -900,15 +914,28 @@ list_command (char *arg, int from_tty)
     dummy_beg = 1;
   else
     {
-      sals = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, 0, 0);
+      struct event_location *location, copy_location;
+
+      location = string_to_event_location (&arg1, current_language);
+      make_cleanup (delete_event_location, location);
+      copy_location = *location;
+      sals = decode_line_1 (&copy_location, DECODE_LINE_LIST_MODE, 0, 0);
+
+      if (EVENT_LOCATION_TYPE (&copy_location) == EVENT_LOCATION_LINESPEC)
+	arg1 = EVENT_LOCATION_LINESPEC (&copy_location);
 
       filter_sals (&sals);
       if (!sals.nelts)
-	return;			/*  C++  */
+	{
+	  /*  C++  */
+	  do_cleanups (cleanup);
+	  return;
+	}
       if (sals.nelts > 1)
 	{
 	  ambiguous_line_spec (&sals);
 	  xfree (sals.sals);
+	  do_cleanups (cleanup);
 	  return;
 	}
 
@@ -933,18 +960,32 @@ list_command (char *arg, int from_tty)
 	dummy_end = 1;
       else
 	{
+	  struct event_location *location, copy_location;
+
+	  location = string_to_event_location (&arg1, current_language);
+	  make_cleanup (delete_event_location, location);
+	  copy_location = *location;
 	  if (dummy_beg)
-	    sals_end = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE, 0, 0);
+	    sals_end = decode_line_1 (&copy_location,
+				      DECODE_LINE_LIST_MODE, 0, 0);
 	  else
-	    sals_end = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE,
+	    sals_end = decode_line_1 (&copy_location, DECODE_LINE_LIST_MODE,
 				      sal.symtab, sal.line);
+
+	  if (EVENT_LOCATION_TYPE (&copy_location) == EVENT_LOCATION_LINESPEC)
+	    arg1 = EVENT_LOCATION_LINESPEC (&copy_location);
+
 	  filter_sals (&sals_end);
 	  if (sals_end.nelts == 0)
-	    return;
+	    {
+	      do_cleanups (cleanup);
+	      return;
+	    }
 	  if (sals_end.nelts > 1)
 	    {
 	      ambiguous_line_spec (&sals_end);
 	      xfree (sals_end.sals);
+	      do_cleanups (cleanup);
 	      return;
 	    }
 	  sal_end = sals_end.sals[0];
@@ -1026,6 +1067,7 @@ list_command (char *arg, int from_tty)
 			 ? sal.line + get_lines_to_list ()
 			 : sal_end.line + 1),
 			0);
+  do_cleanups (cleanup);
 }
 
 /* Subroutine of disassemble_command to simplify it.
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 14952b8..d7c7077 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -1057,7 +1057,8 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
 						    &current_target);
 
   gdb_assert (current_program_space == b->pspace || b->pspace == NULL);
-  elf_gnu_ifunc_record_cache (b->addr_string, resolved_pc);
+  elf_gnu_ifunc_record_cache (event_location_to_string (b->location),
+			      resolved_pc);
 
   sal = find_pc_line (resolved_pc, 0);
   sals.nelts = 1;
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 9647d08..ad98f26 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -1281,7 +1281,8 @@ filter_results (struct linespec_state *self,
 
       if (lsal.sals.nelts > 0)
 	{
-	  lsal.canonical = xstrdup (name);
+	  lsal.canonical = new_event_location (EVENT_LOCATION_LINESPEC);
+	  EVENT_LOCATION_LINESPEC (lsal.canonical) = xstrdup (name);
 	  VEC_safe_push (linespec_sals, self->canonical->sals, &lsal);
 	}
     }
@@ -1761,13 +1762,23 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
 
   /* Shortcut expressions, which can only appear by themselves.  */
   if (ls->expression != NULL)
-    state->canonical->addr_string = xstrdup (ls->expression);
+    {
+      state->canonical->location
+	= new_event_location (EVENT_LOCATION_ADDRESS);
+      EVENT_LOCATION_ADDRESS (state->canonical->location) = ls->expr_pc;
+      EVENT_LOCATION_SAVE_SPEC (state->canonical->location)
+	= xstrdup (ls->expression);
+    }
   else
     {
       struct ui_file *buf;
       int need_colon = 0;
 
       buf = mem_fileopen ();
+
+      state->canonical->location
+	= new_event_location (EVENT_LOCATION_LINESPEC);
+
       if (ls->source_filename)
 	{
 	  fputs_unfiltered (ls->source_filename, buf);
@@ -1816,7 +1827,10 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
 			    ls->line_offset.offset);
 	}
 
-      state->canonical->addr_string = ui_file_xstrdup (buf, NULL);
+      EVENT_LOCATION_SAVE_SPEC (state->canonical->location)
+	= ui_file_xstrdup (buf, NULL);
+      EVENT_LOCATION_LINESPEC (state->canonical->location)
+	= xstrdup (EVENT_LOCATION_SAVE_SPEC (state->canonical->location));
       ui_file_delete (buf);
     }
 }
@@ -1972,6 +1986,30 @@ 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);
+
+  if (self->canonical != NULL)
+    {
+      self->canonical->location = new_event_location (EVENT_LOCATION_ADDRESS);
+      EVENT_LOCATION_ADDRESS (self->canonical->location) = address;
+    }
+
+  return sals;
+}
+
 /* Create and return SALs from the linespec LS.  */
 
 static struct symtabs_and_lines
@@ -1981,14 +2019,8 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 
   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);
+      sals = convert_address_location_to_sals (state, ls->expr_pc);
     }
   else if (ls->labels.label_symbols != NULL)
     {
@@ -2184,6 +2216,9 @@ parse_linespec (linespec_parser *parser, char **argptr)
       char *expr;
       const char *copy;
 
+      /* NOTE: This case should normally be covered by
+	 string_to_event_location.  */
+
       /* User specified an expression, *EXPR.  */
       copy = expr = copy_token_string (token);
       cleanup = make_cleanup (xfree, expr);
@@ -2353,6 +2388,7 @@ linespec_parser_new (linespec_parser *parser,
 		     int default_line,
 		     struct linespec_result *canonical)
 {
+  memset (parser, 0, sizeof (linespec_parser));
   parser->lexer.current.type = LSTOKEN_CONSUMED;
   memset (PARSER_RESULT (parser), 0, sizeof (struct linespec));
   PARSER_RESULT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
@@ -2398,14 +2434,70 @@ linespec_parser_delete (void *arg)
   linespec_state_destructor (PARSER_STATE (parser));
 }
 
+/* A helper function for decode_line_full and decode_line_1 to
+   turn LOCATION into symtabs_and_lines.  */
+
+static struct symtabs_and_lines
+event_location_to_sals (linespec_parser *parser,
+			struct event_location *location)
+{
+  struct symtabs_and_lines result = {NULL, 0};
+
+  switch (EVENT_LOCATION_TYPE (location))
+    {
+    case EVENT_LOCATION_LINESPEC:
+      {
+	char *copy;
+	volatile struct gdb_exception except;
+
+	TRY_CATCH (except, RETURN_MASK_ERROR)
+	  {
+	    copy = EVENT_LOCATION_LINESPEC (location);
+	    result = parse_linespec (parser, &copy);
+	  }
+	EVENT_LOCATION_LINESPEC (location) = copy;
+
+	if (except.reason < 0)
+	  throw_exception (except);
+      }
+      break;
+
+    case EVENT_LOCATION_ADDRESS:
+      result
+	= convert_address_location_to_sals (PARSER_STATE (parser),
+					    EVENT_LOCATION_ADDRESS (location));
+      break;
+
+    default:
+      gdb_assert_not_reached ("unhandled event location type");
+    }
+
+
+  /* If the original location has a save spec, copy it into the
+     canonical location.  This will preserve how the breakpoint
+     was originally created.  */
+  if (EVENT_LOCATION_SAVE_SPEC (location) != NULL
+      && PARSER_STATE (parser)->canonical != NULL)
+    {
+      struct event_location *loc
+	= PARSER_STATE (parser)->canonical->location;
+
+      xfree (EVENT_LOCATION_SAVE_SPEC (loc));
+      EVENT_LOCATION_SAVE_SPEC (loc)
+	= xstrdup (EVENT_LOCATION_SAVE_SPEC (location));
+    }
+
+  return result;
+}
+
 /* See linespec.h.  */
 
 void
-decode_line_full (char **argptr, int flags,
+decode_line_full (struct event_location *location, int flags,
 		  struct symtab *default_symtab,
 		  int default_line, struct linespec_result *canonical,
 		  const char *select_mode,
-		  const char *filter)
+		  const struct event_location *filter)
 {
   struct symtabs_and_lines result;
   struct cleanup *cleanups;
@@ -2427,11 +2519,11 @@ decode_line_full (char **argptr, int flags,
   cleanups = make_cleanup (linespec_parser_delete, &parser);
   save_current_program_space ();
 
-  result = parse_linespec (&parser, argptr);
+  result = event_location_to_sals (&parser, location);
   state = PARSER_STATE (&parser);
 
   gdb_assert (result.nelts == 1 || canonical->pre_expanded);
-  gdb_assert (canonical->addr_string != NULL);
+  gdb_assert (canonical->location != NULL);
   canonical->pre_expanded = 1;
 
   /* Arrange for allocated canonical names to be freed.  */
@@ -2459,9 +2551,14 @@ decode_line_full (char **argptr, int flags,
     {
       if (filter != NULL)
 	{
-	  make_cleanup (VEC_cleanup (const_char_ptr), &filters);
-	  VEC_safe_push (const_char_ptr, filters, filter);
-	  filter_results (state, &result, filters);
+	  if (EVENT_LOCATION_TYPE (filter) == EVENT_LOCATION_LINESPEC)
+	    {
+	      const char *as_string = event_location_to_string (filter);
+
+	      make_cleanup (VEC_cleanup (const_char_ptr), &filters);
+	      VEC_safe_push (const_char_ptr, filters, as_string);
+	      filter_results (state, &result, filters);
+	    }
 	}
       else
 	convert_results_to_lsals (state, &result);
@@ -2475,7 +2572,7 @@ decode_line_full (char **argptr, int flags,
 /* See linespec.h.  */
 
 struct symtabs_and_lines
-decode_line_1 (char **argptr, int flags,
+decode_line_1 (struct event_location *location, int flags,
 	       struct symtab *default_symtab,
 	       int default_line)
 {
@@ -2488,7 +2585,7 @@ decode_line_1 (char **argptr, int flags,
   cleanups = make_cleanup (linespec_parser_delete, &parser);
   save_current_program_space ();
 
-  result = parse_linespec (&parser, argptr);
+  result = event_location_to_sals (&parser, location);
 
   do_cleanups (cleanups);
   return result;
@@ -2501,6 +2598,8 @@ decode_line_with_current_source (char *string, int flags)
 {
   struct symtabs_and_lines sals;
   struct symtab_and_line cursal;
+  struct event_location *location, copy_location;
+  struct cleanup *cleanup;
 
   if (string == 0)
     error (_("Empty line specification."));
@@ -2509,11 +2608,19 @@ decode_line_with_current_source (char *string, int flags)
      and get a default source symtab+line or it will recursively call us!  */
   cursal = get_current_source_symtab_and_line ();
 
-  sals = decode_line_1 (&string, flags,
+  location = string_to_event_location (&string, current_language);
+  cleanup = make_cleanup (delete_event_location, location);
+
+  copy_location = *location;
+  sals = decode_line_1 (&copy_location, flags,
 			cursal.symtab, cursal.line);
+  if (EVENT_LOCATION_TYPE (&copy_location) == EVENT_LOCATION_LINESPEC)
+    string = EVENT_LOCATION_LINESPEC (&copy_location);
 
   if (*string)
     error (_("Junk at end of line specification: %s"), string);
+
+  do_cleanups (cleanup);
   return sals;
 }
 
@@ -2523,19 +2630,30 @@ struct symtabs_and_lines
 decode_line_with_last_displayed (char *string, int flags)
 {
   struct symtabs_and_lines sals;
+  struct event_location *location, copy_location;
+  struct cleanup *cleanup;
 
   if (string == 0)
     error (_("Empty line specification."));
 
+  location = string_to_event_location (&string, current_language);
+  cleanup = make_cleanup (delete_event_location, location);
+
+  copy_location = *location;
   if (last_displayed_sal_is_valid ())
-    sals = decode_line_1 (&string, flags,
+    sals = decode_line_1 (&copy_location, flags,
 			  get_last_displayed_symtab (),
 			  get_last_displayed_line ());
   else
-    sals = decode_line_1 (&string, flags, (struct symtab *) NULL, 0);
+    sals = decode_line_1 (&copy_location, flags, (struct symtab *) NULL, 0);
+
+  if (EVENT_LOCATION_TYPE (&copy_location) == EVENT_LOCATION_LINESPEC)
+    string = EVENT_LOCATION_LINESPEC (&copy_location);
 
   if (*string)
     error (_("Junk at end of line specification: %s"), string);
+
+  do_cleanups (cleanup);
   return sals;
 }
 
@@ -2632,11 +2750,15 @@ decode_objc (struct linespec_state *self, linespec_p ls, char **argptr)
       if (self->canonical)
 	{
 	  self->canonical->pre_expanded = 1;
+	  self->canonical->location
+	    = new_event_location (EVENT_LOCATION_LINESPEC);
+
 	  if (ls->source_filename)
-	    self->canonical->addr_string
+	    EVENT_LOCATION_LINESPEC (self->canonical->location)
 	      = xstrprintf ("%s:%s", ls->source_filename, saved_arg);
 	  else
-	    self->canonical->addr_string = xstrdup (saved_arg);
+	    EVENT_LOCATION_LINESPEC (self->canonical->location)
+	      = xstrdup (saved_arg);
 	}
     }
 
@@ -3668,10 +3790,10 @@ destroy_linespec_result (struct linespec_result *ls)
   int i;
   struct linespec_sals *lsal;
 
-  xfree (ls->addr_string);
+  delete_event_location (ls->location);
   for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i)
     {
-      xfree (lsal->canonical);
+      delete_event_location (lsal->canonical);
       xfree (lsal->sals.sals);
     }
   VEC_free (linespec_sals, ls->sals);
@@ -3692,3 +3814,37 @@ make_cleanup_destroy_linespec_result (struct linespec_result *ls)
 {
   return make_cleanup (cleanup_linespec_result, ls);
 }
+
+/* Parse the user input in *STRINGP and turn it into a struct
+   event_location, advancing STRINGP past any parsed input.
+   Return value is malloc'd.  */
+
+struct event_location *
+string_to_event_location (char **stringp,
+			 const struct language_defn *language)
+{
+  struct event_location *location;
+
+  /* First, check if the string is an address location.  */
+  if (*stringp != NULL && **stringp == '*')
+    {
+      const char *p = *stringp;
+
+      location = new_event_location (EVENT_LOCATION_ADDRESS);
+      EVENT_LOCATION_SAVE_SPEC (location) = xstrdup (p);
+      EVENT_LOCATION_ADDRESS (location) = linespec_expression_to_pc (&p);
+      *stringp = (char *) p;
+    }
+  else
+    {
+      location = new_event_location (EVENT_LOCATION_LINESPEC);
+
+      if (*stringp != NULL)
+	{
+	  EVENT_LOCATION_LINESPEC (location) = xstrdup (*stringp);
+	  *stringp += strlen (*stringp);
+	}
+    }
+
+  return location;
+}
diff --git a/gdb/linespec.h b/gdb/linespec.h
index 8852975..c7926e0 100644
--- a/gdb/linespec.h
+++ b/gdb/linespec.h
@@ -39,11 +39,11 @@ enum decode_line_flags
 
 struct linespec_sals
 {
-  /* This is the linespec corresponding to the sals contained in this
+  /* This is the location corresponding to the sals contained in this
      object.  It can be passed as the FILTER argument to future calls
      to decode_line_full.  This is freed by
      destroy_linespec_result.  */
-  char *canonical;
+  struct event_location *canonical;
 
   /* Sals.  The 'sals' field is destroyed by
      destroy_linespec_result.  */
@@ -71,9 +71,9 @@ struct linespec_result
      object.  */
   int pre_expanded;
 
-  /* If PRE_EXPANDED is non-zero, this is set to the linespec entered
+  /* If PRE_EXPANDED is non-zero, this is set to the location entered
      by the user.  This will be freed by destroy_linespec_result.  */
-  char *addr_string;
+  struct event_location *location;
 
   /* The sals.  The vector will be freed by
      destroy_linespec_result.  */
@@ -96,10 +96,10 @@ extern struct cleanup *
 /* Decode a linespec using the provided default symtab and line.  */
 
 extern struct symtabs_and_lines
-	decode_line_1 (char **argptr, int flags,
+	decode_line_1 (struct event_location *location, int flags,
 		       struct symtab *default_symtab, int default_line);
 
-/* Parse *ARGPTR as a linespec and return results.  This is the "full"
+/* Parse LOCATION and return results.  This is the "full"
    interface to this module, which handles multiple results
    properly.
 
@@ -116,8 +116,8 @@ extern struct symtabs_and_lines
    NULL.  It determines how multiple results will be handled.  If
    NULL, the appropriate CLI value will be used.
 
-   FILTER can either be NULL or a string holding a canonical name.
-   This is only valid when SELECT_MODE is multiple_symbols_all.
+   FILTER can either be NULL or a location.  This is only valid when
+   SELECT_MODE is multiple_symbols_all.
 
    Multiple results are handled differently depending on the
    arguments:
@@ -135,11 +135,11 @@ extern struct symtabs_and_lines
    strcmp sense) to FILTER will be returned; all others will be
    filtered out.  */
 
-extern void decode_line_full (char **argptr, int flags,
+extern void decode_line_full (struct event_location *location, int flags,
 			      struct symtab *default_symtab, int default_line,
 			      struct linespec_result *canonical,
 			      const char *select_mode,
-			      const char *filter);
+			      const struct event_location *filter);
 
 /* Given a string, return the line specified by it, using the current
    source symtab and line as defaults.
@@ -152,4 +152,16 @@ extern struct symtabs_and_lines decode_line_with_current_source (char *, int);
 
 extern struct symtabs_and_lines decode_line_with_last_displayed (char *, int);
 
+/* Attempt to convert the input string in *ARGP into an event location.
+   ARGP is advanced past any processed input.  Returns a event_location
+   (malloc'd) if an event location was successfully found in *ARGP,
+   NULL otherwise.
+
+   This function may call error() if *ARGP looks like properly formed,
+   but invalid, input, e.g., if it is called with missing argument parameters
+   or invalid options.  */
+
+extern struct event_location *
+	string_to_event_location (char **argp,
+				 const struct language_defn *langauge);
 #endif /* defined (LINESPEC_H) */
diff --git a/gdb/mi/mi-cmd-break.c b/gdb/mi/mi-cmd-break.c
index ebc1e6a..d673878 100644
--- a/gdb/mi/mi-cmd-break.c
+++ b/gdb/mi/mi-cmd-break.c
@@ -30,6 +30,8 @@
 #include "observer.h"
 #include "mi-main.h"
 #include "mi-cmd-break.h"
+#include "linespec.h"
+#include "language.h"
 
 enum
   {
@@ -101,6 +103,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
   int tracepoint = 0;
   struct cleanup *back_to;
   enum bptype type_wanted;
+  struct event_location *location;
   struct breakpoint_ops *ops;
 
   enum opt
@@ -183,7 +186,9 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
 		 : (hardware ? bp_hardware_breakpoint : bp_breakpoint));
   ops = tracepoint ? &tracepoint_breakpoint_ops : &bkpt_breakpoint_ops;
 
-  create_breakpoint (get_current_arch (), address, condition, thread,
+  location = string_to_event_location (&address, current_language);
+  make_cleanup (delete_event_location, location);
+  create_breakpoint (get_current_arch (), location, condition, thread,
 		     NULL,
 		     0 /* condition and thread are valid.  */,
 		     temp_p, type_wanted,
diff --git a/gdb/probe.c b/gdb/probe.c
index dfb6e7e..ec1dce3 100644
--- a/gdb/probe.c
+++ b/gdb/probe.c
@@ -32,13 +32,15 @@
 #include "frame.h"
 #include "arch-utils.h"
 #include <ctype.h>
+#include "breakpoint.h"
 
 
 
 /* See definition in probe.h.  */
 
 struct symtabs_and_lines
-parse_probes (char **argptr, struct linespec_result *canonical)
+parse_probes (struct event_location *location,
+	      struct linespec_result *canonical)
 {
   char *arg_start, *arg_end, *arg;
   char *objfile_name = NULL, *provider = NULL, *name, *p;
@@ -52,9 +54,9 @@ parse_probes (char **argptr, struct linespec_result *canonical)
   result.sals = NULL;
   result.nelts = 0;
 
-  arg_start = *argptr;
+  arg_start = EVENT_LOCATION_LINESPEC (location);
 
-  cs = *argptr;
+  cs = arg_start;
   probe_ops = probe_linespec_to_ops (&cs);
   gdb_assert (probe_ops != NULL);
 
@@ -164,10 +166,12 @@ parse_probes (char **argptr, struct linespec_result *canonical)
     {
       canonical->special_display = 1;
       canonical->pre_expanded = 1;
-      canonical->addr_string = savestring (*argptr, arg_end - *argptr);
+      canonical->location = new_event_location (EVENT_LOCATION_LINESPEC);
+      EVENT_LOCATION_LINESPEC (canonical->location)
+	= savestring (arg_start, arg_end - arg_start);
     }
 
-  *argptr = arg_end;
+  EVENT_LOCATION_LINESPEC (location) = arg_end;
   do_cleanups (cleanup);
 
   return result;
diff --git a/gdb/probe.h b/gdb/probe.h
index be1faa4..8eb1aeb 100644
--- a/gdb/probe.h
+++ b/gdb/probe.h
@@ -20,6 +20,8 @@
 #if !defined (PROBE_H)
 #define PROBE_H 1
 
+struct event_location;
+
 #include "gdb_vecs.h"
 
 /* Definition of a vector of probes.  */
@@ -175,10 +177,9 @@ struct probe
   };
 
 /* A helper for linespec that decodes a probe specification.  It returns a
-   symtabs_and_lines object and updates *ARGPTR or throws an error.  The
-   argument PTYPE specifies the type of the probe(s) to be parsed.  */
+   symtabs_and_lines object and updates LOC or throws an error.  */
 
-extern struct symtabs_and_lines parse_probes (char **argptr,
+extern struct symtabs_and_lines parse_probes (struct event_location *loc,
 					      struct linespec_result *canon);
 
 /* Helper function to register the proper probe_ops to a newly created probe.
diff --git a/gdb/python/py-breakpoint.c b/gdb/python/py-breakpoint.c
index 5e5f9b3..b4950b1 100644
--- a/gdb/python/py-breakpoint.c
+++ b/gdb/python/py-breakpoint.c
@@ -369,7 +369,7 @@ bppy_set_hit_count (PyObject *self, PyObject *newvalue, void *closure)
 static PyObject *
 bppy_get_location (PyObject *self, void *closure)
 {
-  char *str;
+  const char *str;
   breakpoint_object *obj = (breakpoint_object *) self;
 
   BPPY_REQUIRE_VALID (obj);
@@ -377,8 +377,7 @@ bppy_get_location (PyObject *self, void *closure)
   if (obj->bp->type != bp_breakpoint)
     Py_RETURN_NONE;
 
-  str = obj->bp->addr_string;
-
+  str = event_location_to_string (obj->bp->location);
   if (! str)
     str = "";
   return PyString_Decode (str, strlen (str), host_charset (), NULL);
@@ -621,8 +620,12 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
 	{
 	case bp_breakpoint:
 	  {
+	    struct event_location location;
+
+	    initialize_event_location (&location, EVENT_LOCATION_LINESPEC);
+	    EVENT_LOCATION_LINESPEC (&location) = copy;
 	    create_breakpoint (python_gdbarch,
-			       copy, NULL, -1, NULL,
+			       &location, NULL, -1, NULL,
 			       0,
 			       0, bp_breakpoint,
 			       0,
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index 6e095b5..d5ac261 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -165,7 +165,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;
+  CORE_ADDR pc;
   volatile struct gdb_exception except;
   char *addr_str, small_buf[100];
   struct symbol *function;
@@ -286,13 +286,13 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
 
   TRY_CATCH (except, RETURN_MASK_ALL)
     {
-      /* 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));
-      addr_str = small_buf;
+      struct event_location location;
 
+      /* Set a breakpoint on the return address.  */
+      initialize_event_location (&location, EVENT_LOCATION_ADDRESS);
+      EVENT_LOCATION_ADDRESS (&location) = get_frame_pc (prev_frame);
       create_breakpoint (python_gdbarch,
-                         addr_str, NULL, thread, NULL,
+                         &location, NULL, thread, NULL,
                          0,
                          1 /*temp_flag*/,
                          bp_breakpoint,
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 4a7cb28..cc2864a 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -621,9 +621,14 @@ gdbpy_decode_line (PyObject *self, PyObject *args)
     {
       if (arg)
 	{
+	  struct event_location location;
+
 	  copy = xstrdup (arg);
 	  copy_to_free = copy;
-	  sals = decode_line_1 (&copy, 0, 0, 0);
+	  initialize_event_location (&location, EVENT_LOCATION_LINESPEC);
+	  EVENT_LOCATION_LINESPEC (&location) = copy;
+	  sals = decode_line_1 (&location, 0, 0, 0);
+	  copy = EVENT_LOCATION_LINESPEC (&location);
 	}
       else
 	{
diff --git a/gdb/remote.c b/gdb/remote.c
index d0a2ee9..b81c3a9 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -10510,13 +10510,12 @@ remote_download_tracepoint (struct bp_location *loc)
   if (remote_protocol_packets[PACKET_TracepointSource].support
       == PACKET_ENABLE)
     {
-      if (b->addr_string)
+      if (b->location != NULL)
 	{
 	  strcpy (buf, "QTDPsrc:");
-	  encode_source_string (b->number, loc->address,
-				"at", b->addr_string, buf + strlen (buf),
-				2048 - strlen (buf));
-
+	  encode_source_string (b->number, loc->address, "at",
+				event_location_to_string (b->location),
+				buf + strlen (buf), 2048 - strlen (buf));
 	  putpkt (buf);
 	  remote_get_noisy_reply (&target_buf, &target_buf_size);
 	  if (strcmp (target_buf, "OK"))
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index 0cf94e9..7e049fa 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -1897,7 +1897,7 @@ spu_catch_start (struct objfile *objfile)
   struct minimal_symbol *minsym;
   struct symtab *symtab;
   CORE_ADDR pc;
-  char buf[32];
+  struct event_location location;
 
   /* Do this only if requested by "set spu stop-on-load on".  */
   if (!spu_stop_on_load_p)
@@ -1939,8 +1939,9 @@ 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));
-  create_breakpoint (get_objfile_arch (objfile), buf /* arg */,
+  initialize_event_location (&location, EVENT_LOCATION_ADDRESS);
+  EVENT_LOCATION_ADDRESS (&location) = pc;
+  create_breakpoint (get_objfile_arch (objfile), &location,
 		     NULL /* cond_string */, -1 /* thread */,
 		     NULL /* extra_string */,
 		     0 /* parse_condition_and_thread */, 1 /* tempflag */,
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 9a2425b..c8e59ea 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -2661,14 +2661,23 @@ scope_info (char *args, int from_tty)
   int j, count = 0;
   struct gdbarch *gdbarch;
   int regno;
+  struct event_location *location, copy_location;
+  struct cleanup *back_to;
 
   if (args == 0 || *args == 0)
     error (_("requires an argument (function, "
 	     "line or *addr) to define a scope"));
 
-  sals = decode_line_1 (&args, DECODE_LINE_FUNFIRSTLINE, NULL, 0);
+  location = string_to_event_location (&args, current_language);
+  back_to = make_cleanup (delete_event_location, location);
+  copy_location = *location;
+  sals = decode_line_1 (&copy_location, DECODE_LINE_FUNFIRSTLINE, NULL, 0);
   if (sals.nelts == 0)
-    return;		/* Presumably decode_line_1 has already warned.  */
+    {
+      /* Presumably decode_line_1 has already warned.  */
+      do_cleanups (back_to);
+      return;
+    }
 
   /* Resolve line numbers to PC.  */
   resolve_sal_pc (&sals.sals[0]);
@@ -2805,6 +2814,7 @@ scope_info (char *args, int from_tty)
   if (count <= 0)
     printf_filtered ("Scope for %s contains no locals or arguments.\n",
 		     save_args);
+  do_cleanups (back_to);
 }
 
 /* Helper for trace_dump_command.  Dump the action list starting at
@@ -2987,7 +2997,7 @@ trace_dump_command (char *args, int from_tty)
 
 extern int
 encode_source_string (int tpnum, ULONGEST addr,
-		      char *srctype, char *src, char *buf, int buf_size)
+		      char *srctype, const char *src, char *buf, int buf_size)
 {
   if (80 + strlen (srctype) > buf_size)
     error (_("Buffer too small for source encoding"));
diff --git a/gdb/tracepoint.h b/gdb/tracepoint.h
index c7eef7b..6bc5706 100644
--- a/gdb/tracepoint.h
+++ b/gdb/tracepoint.h
@@ -354,7 +354,7 @@ extern struct trace_state_variable *find_trace_state_variable (const char *name)
 extern struct trace_state_variable *create_trace_state_variable (const char *name);
 
 extern int encode_source_string (int num, ULONGEST addr,
-				 char *srctype, char *src,
+				 char *srctype, const char *src,
 				 char *buf, int buf_size);
 
 extern void parse_trace_status (char *line, struct trace_status *ts);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]