@@ -3305,8 +3305,9 @@ create_overlay_event_breakpoint (void)
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_overlay_event,
&internal_breakpoint_ops);
- b->location = new_event_location (EVENT_LOCATION_LINESPEC);
- EVENT_LOCATION_LINESPEC (b->location) = xstrdup (func_name);
+ b->location = new_event_location (EVENT_LOCATION_EXPLICIT);
+ EVENT_LOCATION_EXPLICIT (b->location)->function_name
+ = xstrdup (func_name);
if (overlay_debugging == ovly_auto)
{
@@ -3426,8 +3427,9 @@ create_longjmp_master_breakpoint (void)
addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->longjmp_msym[i]);
b = create_internal_breakpoint (gdbarch, addr, bp_longjmp_master,
&internal_breakpoint_ops);
- b->location = new_event_location (EVENT_LOCATION_LINESPEC);
- EVENT_LOCATION_LINESPEC (b->location) = xstrdup (func_name);
+ b->location = new_event_location (EVENT_LOCATION_EXPLICIT);
+ EVENT_LOCATION_EXPLICIT (b->location)->function_name
+ = xstrdup (func_name);
b->enable_state = bp_disabled;
}
}
@@ -3483,8 +3485,9 @@ create_std_terminate_master_breakpoint (void)
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_std_terminate_master,
&internal_breakpoint_ops);
- b->location = new_event_location (EVENT_LOCATION_LINESPEC);
- EVENT_LOCATION_LINESPEC (b->location) = xstrdup (func_name);
+ b->location = new_event_location (EVENT_LOCATION_EXPLICIT);
+ EVENT_LOCATION_EXPLICIT (b->location)->function_name
+ = xstrdup (func_name);
b->enable_state = bp_disabled;
}
}
@@ -3589,8 +3592,9 @@ create_exception_master_breakpoint (void)
¤t_target);
b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
&internal_breakpoint_ops);
- b->location = new_event_location (EVENT_LOCATION_LINESPEC);
- EVENT_LOCATION_LINESPEC (b->location) = xstrdup (func_name);
+ b->location = new_event_location (EVENT_LOCATION_EXPLICIT);
+ EVENT_LOCATION_EXPLICIT (b->location)->function_name
+ = xstrdup (func_name);
b->enable_state = bp_disabled;
}
@@ -10015,7 +10019,17 @@ create_breakpoint (struct gdbarch *gdbarch,
/* If the location has a string representation,
save it to the breakpoint's location save spec, since this
may be used to save the breakpoint to a file. */
- if (EVENT_LOCATION_SAVE_SPEC (b->location) == NULL
+ if (EVENT_LOCATION_TYPE (b->location) == EVENT_LOCATION_EXPLICIT)
+ {
+ char *old = EVENT_LOCATION_SAVE_SPEC (b->location);
+
+ EVENT_LOCATION_SAVE_SPEC (b->location)
+ = xstrprintf ("%s%s%s", old,
+ (extra_string == NULL ? "" : " "),
+ (extra_string == NULL ? "" : extra_string));
+ xfree (old);
+ }
+ else if (EVENT_LOCATION_SAVE_SPEC (b->location) == NULL
&& event_location_to_string (b->location) != NULL)
{
EVENT_LOCATION_SAVE_SPEC (b->location)
@@ -14272,11 +14286,11 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
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);
+ b->location = new_event_location (EVENT_LOCATION_EXPLICIT);
+ EVENT_LOCATION_EXPLICIT (b->location)->source_filename
+ = xstrdup (symtab_to_filename_for_display (sal2.symtab));
+ EVENT_LOCATION_EXPLICIT (b->location)->line_offset.offset
+ = b->loc->line_number;
/* Might be nice to check if function changed, and warn if
so. */
@@ -14528,7 +14542,14 @@ location_to_sals (struct breakpoint *b, struct event_location *location,
char *p, *str;
char *old = EVENT_LOCATION_SAVE_SPEC (location);
- len = orig - prev;
+ if (EVENT_LOCATION_TYPE (location) == EVENT_LOCATION_EXPLICIT)
+ {
+ len = strlen (prev);
+ if (s != NULL)
+ len -= strlen (s);
+ }
+ else
+ len = orig - prev;
str = savestring (prev, len);
p = remove_trailing_whitespace (str, str + len);
@@ -66,31 +66,6 @@ typedef struct bound_minimal_symbol bound_minimal_symbol_d;
DEF_VEC_O (bound_minimal_symbol_d);
-/* An enumeration of possible signs for a line offset. */
-enum offset_relative_sign
-{
- /* No sign */
- LINE_OFFSET_NONE,
-
- /* A plus sign ("+") */
- LINE_OFFSET_PLUS,
-
- /* A minus sign ("-") */
- LINE_OFFSET_MINUS,
-
- /* A special "sign" for unspecified offset. */
- LINE_OFFSET_UNKNOWN
-};
-
-/* A line offset in a linespec. */
-
-struct line_offset
-{
- /* Line offset and any specified sign. */
- int offset;
- enum offset_relative_sign sign;
-};
-
/* A linespec. Elements of this structure are filled in by a parser
(either parse_linespec or some other function). The structure is
then converted into SALs by convert_linespec_to_sals. */
@@ -1550,6 +1525,29 @@ unexpected_linespec_error (linespec_parser *parser)
token_type_strings[token.type]);
}
+/* Throw an undefined label error. */
+
+static void ATTRIBUTE_NORETURN
+undefined_label_error (const char *function, const char *label)
+{
+ if (function != NULL)
+ throw_error (NOT_FOUND_ERROR,
+ _("No label \"%s\" defined in function \"%s\"."),
+ label, function);
+ else
+ throw_error (NOT_FOUND_ERROR,
+ _("No label \"%s\" defined in current function."),
+ label);
+}
+
+/* Throw a source file not found error. */
+
+static void ATTRIBUTE_NORETURN
+source_file_not_found_error (const char *name)
+{
+ throw_error (NOT_FOUND_ERROR, _("No source file named %s."), name);
+}
+
/* Parse and return a line offset in STRING. */
static struct line_offset
@@ -1724,9 +1722,8 @@ linespec_parse_basic (linespec_parser *parser)
else
{
/* We don't know what it was, but it isn't a label. */
- throw_error (NOT_FOUND_ERROR,
- _("No label \"%s\" defined in function \"%s\"."),
- name, PARSER_RESULT (parser)->function_name);
+ undefined_label_error (PARSER_RESULT (parser)->function_name,
+ name);
}
/* Check for a line offset. */
@@ -1782,17 +1779,22 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
else
{
struct ui_file *buf;
+ struct explicit_location *explicit;
int need_colon = 0;
buf = mem_fileopen ();
+ /* Convert any LINESPEC into EXPLICIT form so that the
+ parsing that was just done does not need to be repeated. */
state->canonical->location
- = new_event_location (EVENT_LOCATION_LINESPEC);
+ = new_event_location (EVENT_LOCATION_EXPLICIT);
+ explicit = EVENT_LOCATION_EXPLICIT (state->canonical->location);
if (ls->source_filename)
{
fputs_unfiltered (ls->source_filename, buf);
need_colon = 1;
+ explicit->source_filename = xstrdup (ls->source_filename);
}
if (ls->function_name)
@@ -1801,6 +1803,7 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
fputc_unfiltered (':', buf);
fputs_unfiltered (ls->function_name, buf);
need_colon = 1;
+ explicit->function_name = xstrdup (ls->function_name);
}
if (ls->label_name)
@@ -1819,11 +1822,13 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
s = VEC_index (symbolp, ls->labels.function_symbols, 0);
fputs_unfiltered (SYMBOL_NATURAL_NAME (s), buf);
fputc_unfiltered (':', buf);
+ explicit->function_name = xstrdup (SYMBOL_NATURAL_NAME (s));
}
fputs_unfiltered (ls->label_name, buf);
need_colon = 1;
state->canonical->special_display = 1;
+ explicit->label_name = xstrdup (ls->label_name);
}
if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
@@ -1835,12 +1840,11 @@ canonicalize_linespec (struct linespec_state *state, linespec_p ls)
: (ls->line_offset.sign
== LINE_OFFSET_PLUS ? "+" : "-")),
ls->line_offset.offset);
+ explicit->line_offset = ls->line_offset;
}
- EVENT_LOCATION_LINESPEC (state->canonical->location)
- = ui_file_xstrdup (buf, NULL);
EVENT_LOCATION_SAVE_SPEC (state->canonical->location)
- = xstrdup (EVENT_LOCATION_LINESPEC (state->canonical->location));
+ = ui_file_xstrdup (buf, NULL);
ui_file_delete (buf);
}
}
@@ -2126,6 +2130,72 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
return sals;
}
+/* Convert the explicit location EXPLICIT into SaLs. */
+
+static struct symtabs_and_lines
+convert_explicit_location_to_sals (struct linespec_state *self,
+ linespec_p result,
+ struct explicit_location *explicit)
+{
+ VEC (symbolp) *symbols, *labels;
+ VEC (bound_minimal_symbol_d) *minimal_symbols;
+
+ if (explicit->source_filename != NULL)
+ {
+ volatile struct gdb_exception except;
+
+ TRY_CATCH (except, RETURN_MASK_ERROR)
+ {
+ result->file_symtabs
+ = symtabs_from_filename (explicit->source_filename);
+ }
+
+ if (except.reason < 0 || result->file_symtabs == NULL)
+ source_file_not_found_error (explicit->source_filename);
+
+ result->source_filename = xstrdup (explicit->source_filename);
+ }
+ else
+ {
+ /* A NULL entry means to use the default symtab. */
+ VEC_safe_push (symtab_ptr, result->file_symtabs, NULL);
+ }
+
+ if (explicit->function_name != NULL)
+ {
+ find_linespec_symbols (self, result->file_symtabs,
+ explicit->function_name, &symbols,
+ &minimal_symbols);
+
+ if (symbols == NULL && minimal_symbols == NULL)
+ symbol_not_found_error (explicit->function_name,
+ result->source_filename);
+
+ result->function_name = xstrdup (explicit->function_name);
+ result->function_symbols = symbols;
+ result->minimal_symbols = minimal_symbols;
+ }
+
+ if (explicit->label_name != NULL)
+ {
+ symbols = NULL;
+ labels = find_label_symbols (self, result->function_symbols,
+ &symbols, explicit->label_name);
+
+ if (labels == NULL)
+ undefined_label_error (result->function_name, explicit->label_name);
+
+ result->label_name = xstrdup (explicit->label_name);
+ result->labels.label_symbols = labels;
+ result->labels.function_symbols = symbols;
+ }
+
+ if (explicit->line_offset.sign != LINE_OFFSET_UNKNOWN)
+ result->line_offset = explicit->line_offset;
+
+ return convert_linespec_to_sals (self, result);
+}
+
/* Parse a string that specifies a linespec.
Pass the address of a char * variable; that variable will be
advanced over the characters actually parsed.
@@ -2457,6 +2527,13 @@ event_location_to_sals (linespec_parser *parser,
EVENT_LOCATION_ADDRESS (location));
break;
+ case EVENT_LOCATION_EXPLICIT:
+ result
+ = convert_explicit_location_to_sals (PARSER_STATE (parser),
+ PARSER_RESULT (parser),
+ EVENT_LOCATION_EXPLICIT (location));
+ break;
+
case EVENT_LOCATION_PROBE:
/* Probes are handled by their own decoders. */
gdb_assert_not_reached ("attempt to decode probe location");
@@ -3122,7 +3199,7 @@ symtabs_from_filename (const char *filename)
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. "
"Use the \"file\" command."));
- throw_error (NOT_FOUND_ERROR, _("No source file named %s."), filename);
+ source_file_not_found_error (filename);
}
return result;
@@ -28,6 +28,15 @@
#include <ctype.h>
#include <string.h>
+/* Initialize the given explicit location. */
+
+void
+initialize_explicit_location (struct explicit_location *explicit)
+{
+ memset (explicit, 0, sizeof (struct explicit_location));
+ explicit->line_offset.sign = LINE_OFFSET_UNKNOWN;
+}
+
/* Initialize the given LOCATION. */
void
@@ -36,6 +45,8 @@ initialize_event_location (struct event_location *location,
{
memset (location, 0, sizeof (struct event_location));
EVENT_LOCATION_TYPE (location) = type;
+ if (type == EVENT_LOCATION_EXPLICIT)
+ initialize_explicit_location (EVENT_LOCATION_EXPLICIT (location));
}
/* Create a new location with the given TYPE. */
@@ -72,6 +83,24 @@ copy_event_location (const struct event_location *src)
EVENT_LOCATION_ADDRESS (dst) = EVENT_LOCATION_ADDRESS (src);
break;
+ case EVENT_LOCATION_EXPLICIT:
+ if (EVENT_LOCATION_EXPLICIT (src)->source_filename != NULL)
+ EVENT_LOCATION_EXPLICIT (dst)->source_filename
+ = xstrdup (EVENT_LOCATION_EXPLICIT (src)->source_filename);
+
+ if (EVENT_LOCATION_EXPLICIT (src)->function_name != NULL)
+ EVENT_LOCATION_EXPLICIT (dst)->function_name
+ = xstrdup (EVENT_LOCATION_EXPLICIT (src)->function_name);
+
+ if (EVENT_LOCATION_EXPLICIT (src)->label_name != NULL)
+ EVENT_LOCATION_EXPLICIT (dst)->label_name
+ = xstrdup (EVENT_LOCATION_EXPLICIT (src)->label_name);
+
+ EVENT_LOCATION_EXPLICIT (dst)->line_offset
+ = EVENT_LOCATION_EXPLICIT (src)->line_offset;
+ break;
+
+
case EVENT_LOCATION_PROBE:
EVENT_LOCATION_PROBE (dst) = xstrdup (EVENT_LOCATION_PROBE (src));
break;
@@ -105,6 +134,12 @@ delete_event_location (void *data)
/* Nothing to do. */
break;
+ case EVENT_LOCATION_EXPLICIT:
+ xfree (EVENT_LOCATION_EXPLICIT (location)->source_filename);
+ xfree (EVENT_LOCATION_EXPLICIT (location)->function_name);
+ xfree (EVENT_LOCATION_EXPLICIT (location)->label_name);
+ break;
+
case EVENT_LOCATION_PROBE:
xfree (EVENT_LOCATION_PROBE (location));
break;
@@ -133,6 +168,7 @@ event_location_to_string (const struct event_location *location)
break;
case EVENT_LOCATION_ADDRESS:
+ case EVENT_LOCATION_EXPLICIT:
result = EVENT_LOCATION_SAVE_SPEC (location);
break;
@@ -211,6 +247,14 @@ event_location_empty_p (const struct event_location *location)
case EVENT_LOCATION_ADDRESS:
return 0;
+ case EVENT_LOCATION_EXPLICIT:
+ return (EVENT_LOCATION_EXPLICIT (location) == NULL
+ || (EVENT_LOCATION_EXPLICIT (location)->source_filename == NULL
+ && EVENT_LOCATION_EXPLICIT (location)->function_name == NULL
+ && EVENT_LOCATION_EXPLICIT (location)->label_name == NULL
+ && (EVENT_LOCATION_EXPLICIT (location)->line_offset.sign
+ == LINE_OFFSET_UNKNOWN)));
+
case EVENT_LOCATION_PROBE:
return EVENT_LOCATION_PROBE (location) == NULL;
@@ -21,6 +21,32 @@
struct language_defn;
+/* An enumeration of possible signs for a line offset. */
+
+enum offset_relative_sign
+{
+ /* No sign */
+ LINE_OFFSET_NONE,
+
+ /* A plus sign ("+") */
+ LINE_OFFSET_PLUS,
+
+ /* A minus sign ("-") */
+ LINE_OFFSET_MINUS,
+
+ /* A special "sign" for unspecified offset. */
+ LINE_OFFSET_UNKNOWN
+};
+
+/* A line offset in a location. */
+
+struct line_offset
+{
+ /* Line offset and any specified sign. */
+ int offset;
+ enum offset_relative_sign sign;
+};
+
/* An enumeration of the various ways to specify a stop event
location (used with create_breakpoint). */
@@ -32,10 +58,35 @@ enum event_location_type
/* An address in the inferior. */
EVENT_LOCATION_ADDRESS,
+ /* An explicit location. */
+ EVENT_LOCATION_EXPLICIT,
+
/* A probe location. */
EVENT_LOCATION_PROBE
};
+/* An explicit location. This structure is used to bypass the
+ parsing done on linespecs. It still has the same requirements
+ as linespecs, though. For example, source_filename requires
+ at least one other field. */
+
+struct explicit_location
+{
+ /* The source filename. Malloc'd. */
+ char *source_filename;
+
+ /* The function name. Malloc'd. */
+ char *function_name;
+
+ /* The name of a label. Malloc'd. */
+ char *label_name;
+
+ /* A line offset relative to the start of the symbol
+ identified by the above fields or the current symtab
+ if the other fields are NULL. */
+ struct line_offset line_offset;
+};
+
/* 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. */
@@ -58,6 +109,10 @@ struct event_location
/* An address in the inferior. */
CORE_ADDR address;
#define EVENT_LOCATION_ADDRESS(S) ((S)->u.address)
+
+ /* An explicit location. */
+ struct explicit_location explicit;
+#define EVENT_LOCATION_EXPLICIT(S) (&((S)->u.explicit))
} u;
/* A string representation of how this location may be
@@ -92,6 +147,10 @@ extern struct event_location *
extern void initialize_event_location (struct event_location *location,
enum event_location_type type);
+/* Initialize the given explicit location. */
+
+extern void initialize_explicit_location (struct explicit_location *explicit);
+
/* 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,