diff options
author | Keith Seitz <keiths@redhat.com> | 2015-08-11 17:09:35 -0700 |
---|---|---|
committer | Keith Seitz <keiths@redhat.com> | 2015-08-11 17:09:35 -0700 |
commit | 00e52e5376c7ec604a739e6242e6be36221162d7 (patch) | |
tree | 77a9fa434f22eaecc5ba49b594743dae36962115 /gdb/linespec.c | |
parent | 5b56227bdc000d129d393772f1e4544b5ea0fd46 (diff) | |
download | gdb-00e52e5376c7ec604a739e6242e6be36221162d7.zip gdb-00e52e5376c7ec604a739e6242e6be36221162d7.tar.gz gdb-00e52e5376c7ec604a739e6242e6be36221162d7.tar.bz2 |
Explicit locations: introduce explicit locations
This patch add support for explicit locations and switches many linespec
locations to this new location type. This patch also converts all
linespec locations entered by the user to an explicit representation
internally (thus bypassing the linespec parser when resetting the
breakpoint).
This patch does not introduce any user-visible changes.
gdb/ChangeLog:
* 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.
Diffstat (limited to 'gdb/linespec.c')
-rw-r--r-- | gdb/linespec.c | 304 |
1 files changed, 167 insertions, 137 deletions
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; |