From patchwork Fri Jun 2 12:22:14 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pedro Alves X-Patchwork-Id: 20725 Received: (qmail 23145 invoked by alias); 2 Jun 2017 12:29:17 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 23099 invoked by uid 89); 2 Jun 2017 12:29:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.8 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_STOCKGEN, RP_MATCHES_RCVD, SPF_HELO_PASS, T_FILL_THIS_FORM_SHORT autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 02 Jun 2017 12:29:10 +0000 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 6B0107D4EA for ; Fri, 2 Jun 2017 12:22:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 6B0107D4EA Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx04.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=palves@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 6B0107D4EA Received: from cascais.lan (ovpn04.gateway.prod.ext.ams2.redhat.com [10.39.146.4]) by smtp.corp.redhat.com (Postfix) with ESMTP id CB5074DA7A for ; Fri, 2 Jun 2017 12:22:55 +0000 (UTC) From: Pedro Alves To: gdb-patches@sourceware.org Subject: [PATCH 16/40] Explicit locations -label completer Date: Fri, 2 Jun 2017 13:22:14 +0100 Message-Id: <1496406158-12663-17-git-send-email-palves@redhat.com> In-Reply-To: <1496406158-12663-1-git-send-email-palves@redhat.com> References: <1496406158-12663-1-git-send-email-palves@redhat.com> We're missing a completer for (gdb) break -function func -label [TAB] This patch adds one. Tests will be added later in the series. gdb/ChangeLog: yyyy-mm-dd Pedro Alves * completer.c (collect_explicit_location_matches): Handle MATCH_LABEL. (convert_explicit_location_to_linespec): New, factored out from ... (convert_explicit_location_to_sals): ... this. (complete_label): New. (linespec_complete_label, find_label_symbols_in_block): New. (find_label_symbols): Add completion_mode parameter and adjust to call find_label_symbols_in_block. * linespec.h (linespec_complete_label): Declare. --- gdb/completer.c | 8 ++- gdb/linespec.c | 199 ++++++++++++++++++++++++++++++++++++++++++++------------ gdb/linespec.h | 11 ++++ 3 files changed, 177 insertions(+), 41 deletions(-) diff --git a/gdb/completer.c b/gdb/completer.c index 0473d8c..c7986e6 100644 --- a/gdb/completer.c +++ b/gdb/completer.c @@ -633,7 +633,13 @@ collect_explicit_location_matches (completion_tracker &tracker, break; case MATCH_LABEL: - /* Not supported. */ + { + const char *label = string_or_empty (explicit_loc->label_name); + linespec_complete_label (tracker, language, + explicit_loc->source_filename, + explicit_loc->function_name, + label); + } break; default: diff --git a/gdb/linespec.c b/gdb/linespec.c index 20ac71d..0216bf1 100644 --- a/gdb/linespec.c +++ b/gdb/linespec.c @@ -299,7 +299,8 @@ static VEC (symtab_ptr) *symtabs_from_filename (const char *, static VEC (symbolp) *find_label_symbols (struct linespec_state *self, VEC (symbolp) *function_symbols, VEC (symbolp) **label_funcs_ret, - const char *name); + const char *name, + bool completion_mode = false); static void find_linespec_symbols (struct linespec_state *self, VEC (symtab_ptr) *file_symtabs, @@ -2053,31 +2054,33 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls) return sals; } -/* Convert the explicit location EXPLICIT_LOC into SaLs. */ +/* Build RESULT from the explicit location components SOURCE_FILENAME, + FUNCTION_NAME, LABEL_NAME and LINE_OFFSET. */ -static struct symtabs_and_lines -convert_explicit_location_to_sals (struct linespec_state *self, - linespec_p result, - const struct explicit_location *explicit_loc) +static void +convert_explicit_location_to_linespec (struct linespec_state *self, + linespec_p result, + const char *source_filename, + const char *function_name, + const char *label_name, + struct line_offset line_offset) { VEC (symbolp) *symbols, *labels; VEC (bound_minimal_symbol_d) *minimal_symbols; - if (explicit_loc->source_filename != NULL) + if (source_filename != NULL) { TRY { result->file_symtabs - = symtabs_from_filename (explicit_loc->source_filename, - self->search_pspace); + = symtabs_from_filename (source_filename, self->search_pspace); } CATCH (except, RETURN_MASK_ERROR) { - source_file_not_found_error (explicit_loc->source_filename); + source_file_not_found_error (source_filename); } END_CATCH - result->explicit_loc.source_filename - = xstrdup (explicit_loc->source_filename); + result->explicit_loc.source_filename = xstrdup (source_filename); } else { @@ -2085,41 +2088,53 @@ convert_explicit_location_to_sals (struct linespec_state *self, VEC_safe_push (symtab_ptr, result->file_symtabs, NULL); } - if (explicit_loc->function_name != NULL) + if (function_name != NULL) { find_linespec_symbols (self, result->file_symtabs, - explicit_loc->function_name, &symbols, + function_name, &symbols, &minimal_symbols); if (symbols == NULL && minimal_symbols == NULL) - symbol_not_found_error (explicit_loc->function_name, + symbol_not_found_error (function_name, result->explicit_loc.source_filename); - result->explicit_loc.function_name - = xstrdup (explicit_loc->function_name); + result->explicit_loc.function_name = xstrdup (function_name); result->function_symbols = symbols; result->minimal_symbols = minimal_symbols; } - if (explicit_loc->label_name != NULL) + if (label_name != NULL) { symbols = NULL; labels = find_label_symbols (self, result->function_symbols, - &symbols, explicit_loc->label_name); + &symbols, label_name); if (labels == NULL) undefined_label_error (result->explicit_loc.function_name, - explicit_loc->label_name); + label_name); - result->explicit_loc.label_name = xstrdup (explicit_loc->label_name); + result->explicit_loc.label_name = xstrdup (label_name); result->labels.label_symbols = labels; result->labels.function_symbols = symbols; } - if (explicit_loc->line_offset.sign != LINE_OFFSET_UNKNOWN) - result->explicit_loc.line_offset = explicit_loc->line_offset; + if (line_offset.sign != LINE_OFFSET_UNKNOWN) + result->explicit_loc.line_offset = line_offset; +} - return convert_linespec_to_sals (self, result); +/* Convert the explicit location EXPLICIT_LOC into SaLs. */ + +static struct symtabs_and_lines +convert_explicit_location_to_sals (struct linespec_state *self, + linespec_p result, + const struct explicit_location *explicit_loc) +{ + convert_explicit_location_to_linespec (self, result, + explicit_loc->source_filename, + explicit_loc->function_name, + explicit_loc->label_name, + explicit_loc->line_offset); + return convert_linespec_to_sals (self, result); } /* Parse a string that specifies a linespec. @@ -2470,6 +2485,69 @@ linespec_complete_function (completion_tracker &tracker, collect_symbol_completion_matches (tracker, mode, function, function); } +/* Helper for linespec_complete_label. Find labels that match + LABEL_NAME in the function symbols listed in the PARSER, and add + them to the tracker. */ + +static void +complete_label (completion_tracker &tracker, + linespec_parser *parser, + const char *label_name) +{ + VEC (symbolp) *label_function_symbols = NULL; + VEC (symbolp) *labels + = find_label_symbols (PARSER_STATE (parser), + PARSER_RESULT (parser)->function_symbols, + &label_function_symbols, + label_name, true); + + symbol *label; + for (int ix = 0; + VEC_iterate (symbolp, labels, ix, label); ++ix) + { + char *match = xstrdup (SYMBOL_SEARCH_NAME (label)); + tracker.add_completion (gdb::unique_xmalloc_ptr (match)); + } + VEC_free (symbolp, labels); +} + +/* See linespec.h. */ + +void +linespec_complete_label (completion_tracker &tracker, + const struct language_defn *language, + const char *source_filename, + const char *function_name, + const char *label_name) +{ + linespec_parser parser; + struct cleanup *cleanup; + + linespec_parser_new (&parser, 0, language, NULL, NULL, 0, NULL); + cleanup = make_cleanup (linespec_parser_delete, &parser); + + line_offset unknown_offset = { 0, LINE_OFFSET_UNKNOWN }; + + TRY + { + convert_explicit_location_to_linespec (PARSER_STATE (&parser), + PARSER_RESULT (&parser), + source_filename, + function_name, + NULL, unknown_offset); + } + CATCH (ex, RETURN_MASK_ERROR) + { + do_cleanups (cleanup); + return; + } + END_CATCH + + complete_label (tracker, &parser, label_name); + + do_cleanups (cleanup); +} + /* A helper function for decode_line_full and decode_line_1 to turn LOCATION into symtabs_and_lines. */ @@ -3385,13 +3463,63 @@ find_linespec_symbols (struct linespec_state *state, } } -/* Return all labels named NAME in FUNCTION_SYMBOLS. Return the - actual function symbol in which the label was found in LABEL_FUNC_RET. */ +/* Helper for find_label_symbols. Find all labels that match name + NAME in BLOCK. Return all labels that match in FUNCTION_SYMBOLS. + Return the actual function symbol in which the label was found in + LABEL_FUNC_RET. If COMPLETION_MODE is true, then NAME is + interpreted as a label name prefix. Otherwise, only a label named + exactly NAME match. */ + +static void +find_label_symbols_in_block (const struct block *block, + const char *name, struct symbol *fn_sym, + bool completion_mode, + VEC (symbolp) **result, + VEC (symbolp) **label_funcs_ret) +{ + if (completion_mode) + { + struct block_iterator iter; + struct symbol *sym; + size_t name_len = strlen (name); + + int (*cmp) (const char *, const char *, size_t); + cmp = case_sensitivity == case_sensitive_on ? strncmp : strncasecmp; + + ALL_BLOCK_SYMBOLS (block, iter, sym) + { + if (symbol_matches_domain (SYMBOL_LANGUAGE (sym), + SYMBOL_DOMAIN (sym), LABEL_DOMAIN) + && cmp (SYMBOL_SEARCH_NAME (sym), name, name_len) == 0) + { + VEC_safe_push (symbolp, *result, sym); + VEC_safe_push (symbolp, *label_funcs_ret, fn_sym); + } + } + } + else + { + struct symbol *sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol; + + if (sym != NULL) + { + VEC_safe_push (symbolp, *result, sym); + VEC_safe_push (symbolp, *label_funcs_ret, fn_sym); + } + } +} + +/* Return all labels that match name NAME in FUNCTION_SYMBOLS. Return + the actual function symbol in which the label was found in + LABEL_FUNC_RET. If COMPLETION_MODE is true, then NAME is + interpreted as a label name prefix. Otherwise, only labels named + exactly NAME match. */ static VEC (symbolp) * find_label_symbols (struct linespec_state *self, VEC (symbolp) *function_symbols, - VEC (symbolp) **label_funcs_ret, const char *name) + VEC (symbolp) **label_funcs_ret, const char *name, + bool completion_mode) { int ix; const struct block *block; @@ -3412,13 +3540,8 @@ find_label_symbols (struct linespec_state *self, return NULL; fn_sym = BLOCK_FUNCTION (block); - sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol; - - if (sym != NULL) - { - VEC_safe_push (symbolp, result, sym); - VEC_safe_push (symbolp, *label_funcs_ret, fn_sym); - } + find_label_symbols_in_block (block, name, fn_sym, completion_mode, + &result, label_funcs_ret); } else { @@ -3427,13 +3550,9 @@ find_label_symbols (struct linespec_state *self, { set_current_program_space (SYMTAB_PSPACE (symbol_symtab (fn_sym))); block = SYMBOL_BLOCK_VALUE (fn_sym); - sym = lookup_symbol (name, block, LABEL_DOMAIN, 0).symbol; - if (sym != NULL) - { - VEC_safe_push (symbolp, result, sym); - VEC_safe_push (symbolp, *label_funcs_ret, fn_sym); - } + find_label_symbols_in_block (block, name, fn_sym, completion_mode, + &result, label_funcs_ret); } } diff --git a/gdb/linespec.h b/gdb/linespec.h index d55ba12..f16bb81 100644 --- a/gdb/linespec.h +++ b/gdb/linespec.h @@ -194,6 +194,17 @@ extern void linespec_complete_function (completion_tracker &tracker, const char *function, const char *source_filename); +/* Complete a label symbol, in linespec mode. Only labels of + functions named FUNCTION_NAME are considered. If SOURCE_FILENAME + is non-NULL, limits completion to labels of functions defined in + source files that match SOURCE_FILENAME. */ + +extern void linespec_complete_label (completion_tracker &tracker, + const struct language_defn *language, + const char *source_filename, + const char *function_name, + const char *label_name); + /* Evaluate the expression pointed to by EXP_PTR into a CORE_ADDR, advancing EXP_PTR past any parsed text. */