aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog62
-rw-r--r--gdb/break-catch-throw.c7
-rw-r--r--gdb/breakpoint.c43
-rw-r--r--gdb/linespec.c304
-rw-r--r--gdb/location.c179
-rw-r--r--gdb/location.h87
6 files changed, 523 insertions, 159 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index efb0587..13d31a6 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,6 +1,68 @@
2015-08-11 Keith Seitz <keiths@redhat.com>
* break-catch-throw.c (re_set_exception_catchpoint): Convert
+ linespec into explicit location.
+ * breakpoint.c (create_overlay_breakpoint)
+ (create_longjmp_master_breakpoint)
+ (create_std_terminate_master_breakpoint)
+ (create_exception_master_breakpoint): Convert linespec into explicit
+ location.
+ (update_static_tracepoint): Convert linespec into explicit location.
+ * linespec.c (enum offset_relative_sign, struct line_offset): Move
+ location.h.
+ (struct linespec) <expression, expr_pc, source_filename>
+ <function_name, label_name, line_offset>: Replace with ...
+ <explicit>: ... this.
+ <is_linespec>: New member.
+ (PARSER_EXPLICIT): New accessor macro.
+ (undefined_label_error): New function.
+ (source_file_not_found_error): New function.
+ (linespec_parse_basic): The parser result is now an explicit location.
+ Use PARSER_EXPLICIT to access it.
+ Use undefined_label_error.
+ (canonicalize_linespec): Convert canonical linespec into explicit
+ location.
+ Move string representation of location to explicit_location_to_linespec
+ and use it and explicit_location_to_string to save string
+ representations of the canonical location.
+ (create_sals_line_offset, convert_linespec_to_sals): `ls' contains an
+ explicit location. Update all references.
+ (convert_explicit_location_to_sals): New function.
+ (parse_linespec): Use PARSER_EXPLICIT to access the parser
+ result's explicit location.
+ (linespec_state_constructor): Initialize is_linespec.
+ Use PARSER_EXPLICIT.
+ (linespec_parser_delete): Use PARSER_EXPLICIT to access the parser's
+ result.
+ (event_location_to_sals): For linespec locations, set is_linespec.
+ Handle explicit locations.
+ (decode_objc): 'ls' contains an explicit location now. Update all
+ references.
+ (symtabs_from_filename): Use source_file_not_found_error.
+ * location.c (struct event_location.u) <explicit>: New member.
+ (initialize_explicit_location): New function.
+ (initialize_event_location): Initialize explicit locations.
+ (new_explicit_location, get_explicit_location)
+ (get_explicit_location_const): New functions.
+ (explicit_to_string_internal): New function; most of contents moved
+ from canonicalize_linespec.
+ (explicit_location_to_string): New function.
+ (explicit_location_to_linespec): New function.
+ (copy_event_location, delete_event_location)
+ (event_location_to_string_const, event_location_empty_p): Handle
+ explicit locations.
+ * location.h (enum offset_relative_sign, struct line_offset): Move
+ here from linespec.h.
+ (enum event_location_type): Add EXPLICIT_LOCATION.
+ (struct explicit_location): New structure.
+ (explicit_location_to_string): Declare.
+ (explicit_location_to_linespec): Declare.
+ (new_explicit_location, get_explicit_locationp
+ (get_explicit_location_const, initialize_explicit_location): Declare.
+
+2015-08-11 Keith Seitz <keiths@redhat.com>
+
+ * break-catch-throw.c (re_set_exception_catchpoint): Convert
linespec for stap probe to probe location.
* breakpoint.c (create_longjmp_master_breakpoint)
(create_exception_master_breakpoint): Likewise.
diff --git a/gdb/break-catch-throw.c b/gdb/break-catch-throw.c
index 07a8f05..209c3e3 100644
--- a/gdb/break-catch-throw.c
+++ b/gdb/break-catch-throw.c
@@ -229,9 +229,12 @@ re_set_exception_catchpoint (struct breakpoint *self)
catchpoint mode. */
TRY
{
- char *spec = ASTRDUP (exception_functions[kind].function);
+ struct explicit_location explicit;
- location = new_linespec_location (&spec);
+ initialize_explicit_location (&explicit);
+ explicit.function_name
+ = ASTRDUP (exception_functions[kind].function);
+ location = new_explicit_location (&explicit);
cleanup = make_cleanup_delete_event_location (location);
self->ops->decode_location (self, location, &sals);
do_cleanups (cleanup);
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 0597688..e6bee3d 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -3424,7 +3424,7 @@ create_overlay_event_breakpoint (void)
struct breakpoint *b;
struct breakpoint_objfile_data *bp_objfile_data;
CORE_ADDR addr;
- char *p;
+ struct explicit_location explicit;
bp_objfile_data = get_breakpoint_objfile_data (objfile);
@@ -3449,8 +3449,9 @@ create_overlay_event_breakpoint (void)
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_overlay_event,
&internal_breakpoint_ops);
- p = ASTRDUP (func_name);
- b->location = new_linespec_location (&p);
+ initialize_explicit_location (&explicit);
+ explicit.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit);
if (overlay_debugging == ovly_auto)
{
@@ -3547,7 +3548,7 @@ create_longjmp_master_breakpoint (void)
struct breakpoint *b;
const char *func_name;
CORE_ADDR addr;
- char *p;
+ struct explicit_location explicit;
if (msym_not_found_p (bp_objfile_data->longjmp_msym[i].minsym))
continue;
@@ -3570,8 +3571,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);
- p = ASTRDUP (func_name);
- b->location = new_linespec_location (&p);
+ initialize_explicit_location (&explicit);
+ explicit.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit);
b->enable_state = bp_disabled;
}
}
@@ -3602,7 +3604,7 @@ create_std_terminate_master_breakpoint (void)
{
struct breakpoint *b;
struct breakpoint_objfile_data *bp_objfile_data;
- char *p;
+ struct explicit_location explicit;
bp_objfile_data = get_breakpoint_objfile_data (objfile);
@@ -3628,8 +3630,9 @@ create_std_terminate_master_breakpoint (void)
b = create_internal_breakpoint (get_objfile_arch (objfile), addr,
bp_std_terminate_master,
&internal_breakpoint_ops);
- p = ASTRDUP (func_name);
- b->location = new_linespec_location (&p);
+ initialize_explicit_location (&explicit);
+ explicit.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit);
b->enable_state = bp_disabled;
}
}
@@ -3653,7 +3656,7 @@ create_exception_master_breakpoint (void)
struct gdbarch *gdbarch;
struct breakpoint_objfile_data *bp_objfile_data;
CORE_ADDR addr;
- char *p;
+ struct explicit_location explicit;
bp_objfile_data = get_breakpoint_objfile_data (objfile);
@@ -3734,8 +3737,9 @@ create_exception_master_breakpoint (void)
&current_target);
b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
&internal_breakpoint_ops);
- p = ASTRDUP (func_name);
- b->location = new_linespec_location (&p);
+ initialize_explicit_location (&explicit);
+ explicit.function_name = ASTRDUP (func_name);
+ b->location = new_explicit_location (&explicit);
b->enable_state = bp_disabled;
}
@@ -13932,12 +13936,11 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
if (!VEC_empty(static_tracepoint_marker_p, markers))
{
- char *p, *tmp;
struct symtab_and_line sal2;
struct symbol *sym;
struct static_tracepoint_marker *tpmarker;
struct ui_out *uiout = current_uiout;
- struct cleanup *cleanup;
+ struct explicit_location explicit;
tpmarker = VEC_index (static_tracepoint_marker_p, markers, 0);
@@ -13979,12 +13982,12 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
b->loc->symtab = sym != NULL ? sal2.symtab : NULL;
delete_event_location (b->location);
- p = tmp = xstrprintf ("%s:%d",
- symtab_to_filename_for_display (sal2.symtab),
- b->loc->line_number);
- cleanup = make_cleanup (xfree, tmp);
- b->location = new_linespec_location (&tmp);
- do_cleanups (cleanup);
+ initialize_explicit_location (&explicit);
+ explicit.source_filename
+ = ASTRDUP (symtab_to_filename_for_display (sal2.symtab));
+ explicit.line_offset.offset = b->loc->line_number;
+ explicit.line_offset.sign = LINE_OFFSET_NONE;
+ b->location = new_explicit_location (&explicit);
/* Might be nice to check if function changed, and warn if
so. */
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 8a7640b..84e518f 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -65,73 +65,26 @@ 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. */
struct linespec
{
- /* An expression and the resulting PC. Specifying an expression
- currently precludes the use of other members. */
-
- /* The expression entered by the user. */
- const char *expression;
-
- /* The resulting PC expression derived from evaluating EXPRESSION. */
- CORE_ADDR expr_pc;
-
- /* Any specified file symtabs. */
-
- /* The user-supplied source filename or NULL if none was specified. */
- const char *source_filename;
+ /* An explicit location describing the SaLs. */
+ struct explicit_location explicit;
/* The list of symtabs to search to which to limit the search. May not
- be NULL. If SOURCE_FILENAME is NULL (no user-specified filename),
- FILE_SYMTABS should contain one single NULL member. This will
- cause the code to use the default symtab. */
+ be NULL. If explicit.SOURCE_FILENAME is NULL (no user-specified
+ filename), FILE_SYMTABS should contain one single NULL member. This
+ will cause the code to use the default symtab. */
VEC (symtab_ptr) *file_symtabs;
- /* The name of a function or method and any matching symbols. */
-
- /* The user-specified function name. If no function name was
- supplied, this may be NULL. */
- const char *function_name;
-
/* A list of matching function symbols and minimal symbols. Both lists
may be NULL if no matching symbols were found. */
VEC (symbolp) *function_symbols;
VEC (bound_minimal_symbol_d) *minimal_symbols;
- /* The name of a label and matching symbols. */
-
- /* The user-specified label name. */
- const char *label_name;
-
/* A structure of matching label symbols and the corresponding
function symbol in which the label was found. Both may be NULL
or both must be non-NULL. */
@@ -140,10 +93,6 @@ struct linespec
VEC (symbolp) *label_symbols;
VEC (symbolp) *function_symbols;
} labels;
-
- /* Line offset. It may be LINE_OFFSET_UNKNOWN, meaning that no
- offset was specified. */
- struct line_offset line_offset;
};
typedef struct linespec *linespec_p;
@@ -196,6 +145,9 @@ struct linespec_state
/* This is a set of address_entry objects which is used to prevent
duplicate symbols from being entered into the result. */
htab_t addr_set;
+
+ /* Are we building a linespec? */
+ int is_linespec;
};
/* This is a helper object that is used when collecting symbols into a
@@ -302,6 +254,10 @@ struct ls_parser
};
typedef struct ls_parser linespec_parser;
+/* A convenience macro for accessing the explicit location result of
+ the parser. */
+#define PARSER_EXPLICIT(PPTR) (&PARSER_RESULT ((PPTR))->explicit)
+
/* Prototypes for local functions. */
static void iterate_over_file_blocks (struct symtab *symtab,
@@ -1572,6 +1528,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
@@ -1618,7 +1597,7 @@ linespec_parse_basic (linespec_parser *parser)
/* Record the line offset and get the next token. */
name = copy_token_string (token);
cleanup = make_cleanup (xfree, name);
- PARSER_RESULT (parser)->line_offset = linespec_parse_line_offset (name);
+ PARSER_EXPLICIT (parser)->line_offset = linespec_parse_line_offset (name);
do_cleanups (cleanup);
/* Get the next token. */
@@ -1655,7 +1634,7 @@ linespec_parse_basic (linespec_parser *parser)
{
PARSER_RESULT (parser)->function_symbols = symbols;
PARSER_RESULT (parser)->minimal_symbols = minimal_symbols;
- PARSER_RESULT (parser)->function_name = name;
+ PARSER_EXPLICIT (parser)->function_name = name;
symbols = NULL;
discard_cleanups (cleanup);
}
@@ -1669,7 +1648,7 @@ linespec_parse_basic (linespec_parser *parser)
{
PARSER_RESULT (parser)->labels.label_symbols = labels;
PARSER_RESULT (parser)->labels.function_symbols = symbols;
- PARSER_RESULT (parser)->label_name = name;
+ PARSER_EXPLICIT (parser)->label_name = name;
symbols = NULL;
discard_cleanups (cleanup);
}
@@ -1677,14 +1656,14 @@ linespec_parse_basic (linespec_parser *parser)
&& *LS_TOKEN_STOKEN (token).ptr == '$')
{
/* User specified a convenience variable or history value. */
- PARSER_RESULT (parser)->line_offset
+ PARSER_EXPLICIT (parser)->line_offset
= linespec_parse_variable (PARSER_STATE (parser), name);
- if (PARSER_RESULT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN)
+ if (PARSER_EXPLICIT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN)
{
/* The user-specified variable was not valid. Do not
throw an error here. parse_linespec will do it for us. */
- PARSER_RESULT (parser)->function_name = name;
+ PARSER_EXPLICIT (parser)->function_name = name;
discard_cleanups (cleanup);
return;
}
@@ -1699,7 +1678,7 @@ linespec_parse_basic (linespec_parser *parser)
an error here. parse_linespec will do it for us. */
/* Save a copy of the name we were trying to lookup. */
- PARSER_RESULT (parser)->function_name = name;
+ PARSER_EXPLICIT (parser)->function_name = name;
discard_cleanups (cleanup);
return;
}
@@ -1719,7 +1698,7 @@ linespec_parse_basic (linespec_parser *parser)
get the next token. */
name = copy_token_string (token);
cleanup = make_cleanup (xfree, name);
- PARSER_RESULT (parser)->line_offset
+ PARSER_EXPLICIT (parser)->line_offset
= linespec_parse_line_offset (name);
do_cleanups (cleanup);
@@ -1739,16 +1718,15 @@ linespec_parse_basic (linespec_parser *parser)
{
PARSER_RESULT (parser)->labels.label_symbols = labels;
PARSER_RESULT (parser)->labels.function_symbols = symbols;
- PARSER_RESULT (parser)->label_name = name;
+ PARSER_EXPLICIT (parser)->label_name = name;
symbols = NULL;
discard_cleanups (cleanup);
}
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_EXPLICIT (parser)->function_name,
+ name);
}
/* Check for a line offset. */
@@ -1766,7 +1744,7 @@ linespec_parse_basic (linespec_parser *parser)
name = copy_token_string (token);
cleanup = make_cleanup (xfree, name);
- PARSER_RESULT (parser)->line_offset
+ PARSER_EXPLICIT (parser)->line_offset
= linespec_parse_line_offset (name);
do_cleanups (cleanup);
@@ -1783,43 +1761,28 @@ linespec_parse_basic (linespec_parser *parser)
}
/* Canonicalize the linespec contained in LS. The result is saved into
- STATE->canonical. */
+ STATE->canonical. This function handles both linespec and explicit
+ locations. */
static void
canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
{
- char *tmp;
- struct ui_file *buf;
- int need_colon = 0;
- struct cleanup *cleanup;
+ struct event_location *canon;
+ struct explicit_location *explicit;
/* If canonicalization was not requested, no need to do anything. */
if (!state->canonical)
return;
- buf = mem_fileopen ();
- cleanup = make_cleanup_ui_file_delete (buf);
-
- if (ls->source_filename)
- {
- fputs_unfiltered (ls->source_filename, buf);
- need_colon = 1;
- }
-
- if (ls->function_name)
- {
- if (need_colon)
- fputc_unfiltered (':', buf);
- fputs_unfiltered (ls->function_name, buf);
- need_colon = 1;
- }
+ /* Save everything as an explicit location. */
+ canon = state->canonical->location = new_explicit_location (&ls->explicit);
+ explicit = get_explicit_location (canon);
- if (ls->label_name)
+ if (explicit->label_name != NULL)
{
- if (need_colon)
- fputc_unfiltered (':', buf);
+ state->canonical->special_display = 1;
- if (ls->function_name == NULL)
+ if (explicit->function_name == NULL)
{
struct symbol *s;
@@ -1828,30 +1791,19 @@ canonicalize_linespec (struct linespec_state *state, const linespec_p ls)
&& (VEC_length (symbolp, ls->labels.function_symbols)
== 1));
s = VEC_index (symbolp, ls->labels.function_symbols, 0);
- fputs_unfiltered (SYMBOL_NATURAL_NAME (s), buf);
- fputc_unfiltered (':', buf);
+ explicit->function_name = xstrdup (SYMBOL_NATURAL_NAME (s));
}
-
- fputs_unfiltered (ls->label_name, buf);
- need_colon = 1;
- state->canonical->special_display = 1;
}
- if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
+ /* If this location originally came from a linespec, save a string
+ representation of it for display and saving to file. */
+ if (state->is_linespec)
{
- if (need_colon)
- fputc_unfiltered (':', buf);
- fprintf_filtered (buf, "%s%d",
- (ls->line_offset.sign == LINE_OFFSET_NONE ? ""
- : (ls->line_offset.sign
- == LINE_OFFSET_PLUS ? "+" : "-")),
- ls->line_offset.offset);
- }
+ char *linespec = explicit_location_to_linespec (explicit);
- tmp = ui_file_xstrdup (buf, NULL);
- make_cleanup (xfree, tmp);
- state->canonical->location = new_linespec_location (&tmp);
- do_cleanups (cleanup);
+ set_event_location_string (canon, linespec);
+ xfree (linespec);
+ }
}
/* Given a line offset in LS, construct the relevant SALs. */
@@ -1891,18 +1843,18 @@ create_sals_line_offset (struct linespec_state *self,
use_default = 1;
}
- val.line = ls->line_offset.offset;
- switch (ls->line_offset.sign)
+ val.line = ls->explicit.line_offset.offset;
+ switch (ls->explicit.line_offset.sign)
{
case LINE_OFFSET_PLUS:
- if (ls->line_offset.offset == 0)
+ if (ls->explicit.line_offset.offset == 0)
val.line = 5;
if (use_default)
val.line = self->default_line + val.line;
break;
case LINE_OFFSET_MINUS:
- if (ls->line_offset.offset == 0)
+ if (ls->explicit.line_offset.offset == 0)
val.line = 15;
if (use_default)
val.line = self->default_line - val.line;
@@ -1994,9 +1946,9 @@ create_sals_line_offset (struct linespec_state *self,
if (values.nelts == 0)
{
- if (ls->source_filename)
+ if (ls->explicit.source_filename)
throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."),
- val.line, ls->source_filename);
+ val.line, ls->explicit.source_filename);
else
throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."),
val.line);
@@ -2093,13 +2045,13 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
}
}
}
- else if (ls->line_offset.sign != LINE_OFFSET_UNKNOWN)
+ else if (ls->explicit.line_offset.sign != LINE_OFFSET_UNKNOWN)
{
/* Only an offset was specified. */
sals = create_sals_line_offset (state, ls);
/* Make sure we have a filename for canonicalization. */
- if (ls->source_filename == NULL)
+ if (ls->explicit.source_filename == NULL)
{
const char *fullname = symtab_to_fullname (state->default_symtab);
@@ -2107,7 +2059,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
form so that displaying SOURCE_FILENAME can follow the current
FILENAME_DISPLAY_STRING setting. But as it is used only rarely
it has been kept for code simplicity only in absolute form. */
- ls->source_filename = xstrdup (fullname);
+ ls->explicit.source_filename = xstrdup (fullname);
}
}
else
@@ -2124,6 +2076,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,
+ const struct explicit_location *explicit)
+{
+ VEC (symbolp) *symbols, *labels;
+ VEC (bound_minimal_symbol_d) *minimal_symbols;
+
+ if (explicit->source_filename != NULL)
+ {
+ TRY
+ {
+ result->file_symtabs
+ = symtabs_from_filename (explicit->source_filename);
+ }
+ CATCH (except, RETURN_MASK_ERROR)
+ {
+ source_file_not_found_error (explicit->source_filename);
+ }
+ END_CATCH
+ result->explicit.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->explicit.source_filename);
+
+ result->explicit.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->explicit.function_name,
+ explicit->label_name);
+
+ result->explicit.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->explicit.line_offset = explicit->line_offset;
+
+ return convert_linespec_to_sals (self, result);
+}
+
/* Parse a string that specifies a linespec.
The basic grammar of linespecs:
@@ -2229,13 +2247,13 @@ parse_linespec (linespec_parser *parser, const char *arg)
/* User specified a convenience variable or history value. */
var = copy_token_string (token);
cleanup = make_cleanup (xfree, var);
- PARSER_RESULT (parser)->line_offset
+ PARSER_EXPLICIT (parser)->line_offset
= linespec_parse_variable (PARSER_STATE (parser), var);
do_cleanups (cleanup);
/* If a line_offset wasn't found (VAR is the name of a user
variable/function), then skip to normal symbol processing. */
- if (PARSER_RESULT (parser)->line_offset.sign != LINE_OFFSET_UNKNOWN)
+ if (PARSER_EXPLICIT (parser)->line_offset.sign != LINE_OFFSET_UNKNOWN)
{
/* Consume this token. */
linespec_lexer_consume_token (parser);
@@ -2273,7 +2291,7 @@ parse_linespec (linespec_parser *parser, const char *arg)
if (file_exception.reason >= 0)
{
/* Symtabs were found for the file. Record the filename. */
- PARSER_RESULT (parser)->source_filename = user_filename;
+ PARSER_EXPLICIT (parser)->source_filename = user_filename;
/* Get the next token. */
token = linespec_lexer_consume_token (parser);
@@ -2310,7 +2328,7 @@ parse_linespec (linespec_parser *parser, const char *arg)
if (PARSER_RESULT (parser)->function_symbols == NULL
&& PARSER_RESULT (parser)->labels.label_symbols == NULL
- && PARSER_RESULT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN
+ && PARSER_EXPLICIT (parser)->line_offset.sign == LINE_OFFSET_UNKNOWN
&& PARSER_RESULT (parser)->minimal_symbols == NULL)
{
/* The linespec didn't parse. Re-throw the file exception if
@@ -2319,8 +2337,8 @@ parse_linespec (linespec_parser *parser, const char *arg)
throw_exception (file_exception);
/* Otherwise, the symbol is not found. */
- symbol_not_found_error (PARSER_RESULT (parser)->function_name,
- PARSER_RESULT (parser)->source_filename);
+ symbol_not_found_error (PARSER_EXPLICIT (parser)->function_name,
+ PARSER_EXPLICIT (parser)->source_filename);
}
convert_to_sals:
@@ -2358,6 +2376,7 @@ linespec_state_constructor (struct linespec_state *self,
self->program_space = current_program_space;
self->addr_set = htab_create_alloc (10, hash_address_entry, eq_address_entry,
xfree, xcalloc, xfree);
+ self->is_linespec = 0;
}
/* Initialize a new linespec parser. */
@@ -2372,7 +2391,7 @@ linespec_parser_new (linespec_parser *parser,
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;
+ PARSER_EXPLICIT (parser)->line_offset.sign = LINE_OFFSET_UNKNOWN;
linespec_state_constructor (PARSER_STATE (parser), flags, language,
default_symtab, default_line, canonical);
}
@@ -2392,10 +2411,9 @@ linespec_parser_delete (void *arg)
{
linespec_parser *parser = (linespec_parser *) arg;
- xfree ((char *) PARSER_RESULT (parser)->expression);
- xfree ((char *) PARSER_RESULT (parser)->source_filename);
- xfree ((char *) PARSER_RESULT (parser)->label_name);
- xfree ((char *) PARSER_RESULT (parser)->function_name);
+ xfree (PARSER_EXPLICIT (parser)->source_filename);
+ xfree (PARSER_EXPLICIT (parser)->label_name);
+ xfree (PARSER_EXPLICIT (parser)->function_name);
if (PARSER_RESULT (parser)->file_symtabs != NULL)
VEC_free (symtab_ptr, PARSER_RESULT (parser)->file_symtabs);
@@ -2461,6 +2479,7 @@ event_location_to_sals (linespec_parser *parser,
{
case LINESPEC_LOCATION:
{
+ PARSER_STATE (parser)->is_linespec = 1;
TRY
{
result = parse_linespec (parser, get_linespec_location (location));
@@ -2479,6 +2498,17 @@ event_location_to_sals (linespec_parser *parser,
get_address_location (location));
break;
+ case EXPLICIT_LOCATION:
+ {
+ const struct explicit_location *explicit;
+
+ explicit = get_explicit_location_const (location);
+ result = convert_explicit_location_to_sals (PARSER_STATE (parser),
+ PARSER_RESULT (parser),
+ explicit);
+ }
+ break;
+
case PROBE_LOCATION:
/* Probes are handled by their own decoders. */
gdb_assert_not_reached ("attempt to decode probe location");
@@ -2728,7 +2758,7 @@ decode_objc (struct linespec_state *self, linespec_p ls, const char *arg)
memcpy (saved_arg, arg, new_argptr - arg);
saved_arg[new_argptr - arg] = '\0';
- ls->function_name = xstrdup (saved_arg);
+ ls->explicit.function_name = xstrdup (saved_arg);
ls->function_symbols = info.result.symbols;
ls->minimal_symbols = info.result.minimal_symbols;
values = convert_linespec_to_sals (self, ls);
@@ -2739,10 +2769,10 @@ decode_objc (struct linespec_state *self, linespec_p ls, const char *arg)
self->canonical->pre_expanded = 1;
- if (ls->source_filename)
+ if (ls->explicit.source_filename)
{
str = xstrprintf ("%s:%s",
- ls->source_filename, saved_arg);
+ ls->explicit.source_filename, saved_arg);
}
else
str = xstrdup (saved_arg);
@@ -3122,7 +3152,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;
diff --git a/gdb/location.c b/gdb/location.c
index fd35c48..3985e5a 100644
--- a/gdb/location.c
+++ b/gdb/location.c
@@ -50,6 +50,10 @@ struct event_location
/* An address in the inferior. */
CORE_ADDR address;
#define EL_ADDRESS(PTR) (PTR)->u.address
+
+ /* An explicit location. */
+ struct explicit_location explicit;
+#define EL_EXPLICIT(PTR) (&((PTR)->u.explicit))
} u;
/* Cached string representation of this location. This is used, e.g., to
@@ -68,6 +72,15 @@ event_location_type (const struct event_location *location)
/* See description in location.h. */
+void
+initialize_explicit_location (struct explicit_location *explicit)
+{
+ memset (explicit, 0, sizeof (struct explicit_location));
+ explicit->line_offset.sign = LINE_OFFSET_UNKNOWN;
+}
+
+/* See description in location.h. */
+
struct event_location *
new_linespec_location (char **linespec)
{
@@ -145,6 +158,137 @@ get_probe_location (const struct event_location *location)
/* See description in location.h. */
struct event_location *
+new_explicit_location (const struct explicit_location *explicit)
+{
+ struct event_location tmp;
+
+ memset (&tmp, 0, sizeof (struct event_location));
+ EL_TYPE (&tmp) = EXPLICIT_LOCATION;
+ initialize_explicit_location (EL_EXPLICIT (&tmp));
+ if (explicit != NULL)
+ {
+ if (explicit->source_filename != NULL)
+ {
+ EL_EXPLICIT (&tmp)->source_filename
+ = explicit->source_filename;
+ }
+
+ if (explicit->function_name != NULL)
+ EL_EXPLICIT (&tmp)->function_name
+ = explicit->function_name;
+
+ if (explicit->label_name != NULL)
+ EL_EXPLICIT (&tmp)->label_name = explicit->label_name;
+
+ if (explicit->line_offset.sign != LINE_OFFSET_UNKNOWN)
+ EL_EXPLICIT (&tmp)->line_offset = explicit->line_offset;
+ }
+
+ return copy_event_location (&tmp);
+}
+
+/* See description in location.h. */
+
+struct explicit_location *
+get_explicit_location (struct event_location *location)
+{
+ gdb_assert (EL_TYPE (location) == EXPLICIT_LOCATION);
+ return EL_EXPLICIT (location);
+}
+
+/* See description in location.h. */
+
+const struct explicit_location *
+get_explicit_location_const (const struct event_location *location)
+{
+ gdb_assert (EL_TYPE (location) == EXPLICIT_LOCATION);
+ return EL_EXPLICIT (location);
+}
+
+/* This convenience function returns a malloc'd string which
+ represents the location in EXPLICIT.
+
+ AS_LINESPEC is non-zero if this string should be a linespec.
+ Otherwise it will be output in explicit form. */
+
+static char *
+explicit_to_string_internal (int as_linespec,
+ const struct explicit_location *explicit)
+{
+ struct ui_file *buf;
+ char space, *result;
+ int need_space = 0;
+ struct cleanup *cleanup;
+
+ space = as_linespec ? ':' : ' ';
+ buf = mem_fileopen ();
+ cleanup = make_cleanup_ui_file_delete (buf);
+
+ if (explicit->source_filename != NULL)
+ {
+ if (!as_linespec)
+ fputs_unfiltered ("-source ", buf);
+ fputs_unfiltered (explicit->source_filename, buf);
+ need_space = 1;
+ }
+
+ if (explicit->function_name != NULL)
+ {
+ if (need_space)
+ fputc_unfiltered (space, buf);
+ if (!as_linespec)
+ fputs_unfiltered ("-function ", buf);
+ fputs_unfiltered (explicit->function_name, buf);
+ need_space = 1;
+ }
+
+ if (explicit->label_name != NULL)
+ {
+ if (need_space)
+ fputc_unfiltered (space, buf);
+ if (!as_linespec)
+ fputs_unfiltered ("-label ", buf);
+ fputs_unfiltered (explicit->label_name, buf);
+ need_space = 1;
+ }
+
+ if (explicit->line_offset.sign != LINE_OFFSET_UNKNOWN)
+ {
+ if (need_space)
+ fputc_unfiltered (space, buf);
+ if (!as_linespec)
+ fputs_unfiltered ("-line ", buf);
+ fprintf_filtered (buf, "%s%d",
+ (explicit->line_offset.sign == LINE_OFFSET_NONE ? ""
+ : (explicit->line_offset.sign
+ == LINE_OFFSET_PLUS ? "+" : "-")),
+ explicit->line_offset.offset);
+ }
+
+ result = ui_file_xstrdup (buf, NULL);
+ do_cleanups (cleanup);
+ return result;
+}
+
+/* See description in location.h. */
+
+char *
+explicit_location_to_string (const struct explicit_location *explicit)
+{
+ return explicit_to_string_internal (0, explicit);
+}
+
+/* See description in location.h. */
+
+char *
+explicit_location_to_linespec (const struct explicit_location *explicit)
+{
+ return explicit_to_string_internal (1, explicit);
+}
+
+/* See description in location.h. */
+
+struct event_location *
copy_event_location (const struct event_location *src)
{
struct event_location *dst;
@@ -165,6 +309,22 @@ copy_event_location (const struct event_location *src)
EL_ADDRESS (dst) = EL_ADDRESS (src);
break;
+ case EXPLICIT_LOCATION:
+ if (EL_EXPLICIT (src)->source_filename != NULL)
+ EL_EXPLICIT (dst)->source_filename
+ = xstrdup (EL_EXPLICIT (src)->source_filename);
+
+ if (EL_EXPLICIT (src)->function_name != NULL)
+ EL_EXPLICIT (dst)->function_name
+ = xstrdup (EL_EXPLICIT (src)->function_name);
+
+ if (EL_EXPLICIT (src)->label_name != NULL)
+ EL_EXPLICIT (dst)->label_name = xstrdup (EL_EXPLICIT (src)->label_name);
+
+ EL_EXPLICIT (dst)->line_offset = EL_EXPLICIT (src)->line_offset;
+ break;
+
+
case PROBE_LOCATION:
if (EL_PROBE (src) != NULL)
EL_PROBE (dst) = xstrdup (EL_PROBE (src));
@@ -214,6 +374,12 @@ delete_event_location (struct event_location *location)
/* Nothing to do. */
break;
+ case EXPLICIT_LOCATION:
+ xfree (EL_EXPLICIT (location)->source_filename);
+ xfree (EL_EXPLICIT (location)->function_name);
+ xfree (EL_EXPLICIT (location)->label_name);
+ break;
+
case PROBE_LOCATION:
xfree (EL_PROBE (location));
break;
@@ -246,6 +412,11 @@ event_location_to_string (struct event_location *location)
core_addr_to_string (EL_ADDRESS (location)));
break;
+ case EXPLICIT_LOCATION:
+ EL_STRING (location)
+ = explicit_location_to_string (EL_EXPLICIT (location));
+ break;
+
case PROBE_LOCATION:
EL_STRING (location) = xstrdup (EL_PROBE (location));
break;
@@ -312,6 +483,14 @@ event_location_empty_p (const struct event_location *location)
case ADDRESS_LOCATION:
return 0;
+ case EXPLICIT_LOCATION:
+ return (EL_EXPLICIT (location) == NULL
+ || (EL_EXPLICIT (location)->source_filename == NULL
+ && EL_EXPLICIT (location)->function_name == NULL
+ && EL_EXPLICIT (location)->label_name == NULL
+ && (EL_EXPLICIT (location)->line_offset.sign
+ == LINE_OFFSET_UNKNOWN)));
+
case PROBE_LOCATION:
return EL_PROBE (location) == NULL;
diff --git a/gdb/location.h b/gdb/location.h
index 63318ba..3082d9e 100644
--- a/gdb/location.h
+++ b/gdb/location.h
@@ -22,6 +22,32 @@
struct language_defn;
struct event_location;
+/* 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). */
@@ -33,15 +59,52 @@ enum event_location_type
/* An address in the inferior. */
ADDRESS_LOCATION,
+ /* An explicit location. */
+ EXPLICIT_LOCATION,
+
/* A probe location. */
PROBE_LOCATION
};
+/* 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;
+};
+
/* Return the type of the given event location. */
extern enum event_location_type
event_location_type (const struct event_location *);
+/* Return a malloc'd explicit string representation of the given
+ explicit location. The location must already be canonicalized/valid. */
+
+extern char *
+ explicit_location_to_string (const struct explicit_location *explicit);
+
+/* Return a malloc'd linespec string representation of the given
+ explicit location. The location must already be canonicalized/valid. */
+
+extern char *
+ explicit_location_to_linespec (const struct explicit_location *explicit);
+
/* Return a string representation of the LOCATION.
This function may return NULL for unspecified linespecs,
e.g, LOCATION_LINESPEC and addr_string is NULL.
@@ -87,6 +150,30 @@ extern struct event_location *
extern const char *
get_probe_location (const struct event_location *location);
+/* Initialize the given explicit location. */
+
+extern void initialize_explicit_location (struct explicit_location *explicit);
+
+/* Create a new explicit location. If not NULL, EXPLICIT is checked for
+ validity. If invalid, an exception is thrown.
+
+ The return result is malloc'd and should be freed with
+ delete_event_location. */
+
+extern struct event_location *
+ new_explicit_location (const struct explicit_location *explicit);
+
+/* Return the explicit location of the given event_location
+ (which must be of type EXPLICIT_LOCATION). */
+
+extern struct explicit_location *
+ get_explicit_location (struct event_location *location);
+
+/* A const version of the above. */
+
+extern const struct explicit_location *
+ get_explicit_location_const (const struct event_location *location);
+
/* Free an event location and any associated data. */
extern void delete_event_location (struct event_location *location);