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