gdb/
* linespec.c (struct linespec_canonical_name): New. (struct linespec_state): Change canonical_names type to it. (add_sal_to_sals): Change variable canonical_name to canonical. Change xrealloc element size. Initialize the different CANONICAL fields. (canonical_to_fullform): New. (filter_results): Use it. Add variables canonical, fullform and cleanup. (struct decode_line_2_item, decode_line_2_compare_items): New. (decode_line_2): Remove variables iter and item_names, add variables items and items_count. Modify the code for these new variables. gdb/testsuite/ * gdb.linespec/base/one/thefile.cc (twodup): New. (m): Call it. * gdb.linespec/base/two/thefile.cc (dupname): New. (n): Call it. * gdb.linespec/break-ask.exp: New file. * gdb.linespec/lspec.cc (body_elsewhere): New comment marker.
This commit is contained in:
parent
feb1472522
commit
33f448b11e
@ -1,3 +1,16 @@
|
||||
2013-03-04 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* linespec.c (struct linespec_canonical_name): New.
|
||||
(struct linespec_state): Change canonical_names type to it.
|
||||
(add_sal_to_sals): Change variable canonical_name to canonical. Change
|
||||
xrealloc element size. Initialize the different CANONICAL fields.
|
||||
(canonical_to_fullform): New.
|
||||
(filter_results): Use it. Add variables canonical, fullform and
|
||||
cleanup.
|
||||
(struct decode_line_2_item, decode_line_2_compare_items): New.
|
||||
(decode_line_2): Remove variables iter and item_names, add variables
|
||||
items and items_count. Modify the code for these new variables.
|
||||
|
||||
2013-03-04 Corinna Vinschen <vinschen@redhat.com>
|
||||
|
||||
* coff-pe-read.c (read_pe_exported_syms): Don't return without
|
||||
|
196
gdb/linespec.c
196
gdb/linespec.c
@ -157,6 +157,21 @@ struct linespec
|
||||
};
|
||||
typedef struct linespec *linespec_p;
|
||||
|
||||
/* A canonical linespec represented as a symtab-related string.
|
||||
|
||||
Each entry represents the "SYMTAB:SUFFIX" linespec string.
|
||||
SYMTAB can be converted for example by symtab_to_fullname or
|
||||
symtab_to_filename_for_display as needed. */
|
||||
|
||||
struct linespec_canonical_name
|
||||
{
|
||||
/* Remaining text part of the linespec string. */
|
||||
char *suffix;
|
||||
|
||||
/* If NULL then SUFFIX is the whole linespec string. */
|
||||
struct symtab *symtab;
|
||||
};
|
||||
|
||||
/* An instance of this is used to keep all state while linespec
|
||||
operates. This instance is passed around as a 'this' pointer to
|
||||
the various implementation methods. */
|
||||
@ -186,7 +201,7 @@ struct linespec_state
|
||||
struct linespec_result *canonical;
|
||||
|
||||
/* Canonical strings that mirror the symtabs_and_lines result. */
|
||||
char **canonical_names;
|
||||
struct linespec_canonical_name *canonical_names;
|
||||
|
||||
/* This is a set of address_entry objects which is used to prevent
|
||||
duplicate symbols from being entered into the result. */
|
||||
@ -848,10 +863,12 @@ add_sal_to_sals (struct linespec_state *self,
|
||||
|
||||
if (self->canonical)
|
||||
{
|
||||
char *canonical_name = NULL;
|
||||
struct linespec_canonical_name *canonical;
|
||||
|
||||
self->canonical_names = xrealloc (self->canonical_names,
|
||||
sals->nelts * sizeof (char *));
|
||||
(sals->nelts
|
||||
* sizeof (*self->canonical_names)));
|
||||
canonical = &self->canonical_names[sals->nelts - 1];
|
||||
if (!literal_canonical && sal->symtab)
|
||||
{
|
||||
const char *fullname = symtab_to_fullname (sal->symtab);
|
||||
@ -861,17 +878,21 @@ add_sal_to_sals (struct linespec_state *self,
|
||||
the time being. */
|
||||
if (symname != NULL && sal->line != 0
|
||||
&& self->language->la_language == language_ada)
|
||||
canonical_name = xstrprintf ("%s:%s:%d", fullname, symname,
|
||||
sal->line);
|
||||
canonical->suffix = xstrprintf ("%s:%d", symname, sal->line);
|
||||
else if (symname != NULL)
|
||||
canonical_name = xstrprintf ("%s:%s", fullname, symname);
|
||||
canonical->suffix = xstrdup (symname);
|
||||
else
|
||||
canonical_name = xstrprintf ("%s:%d", fullname, sal->line);
|
||||
canonical->suffix = xstrprintf ("%d", sal->line);
|
||||
canonical->symtab = sal->symtab;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (symname != NULL)
|
||||
canonical->suffix = xstrdup (symname);
|
||||
else
|
||||
canonical->suffix = NULL;
|
||||
canonical->symtab = NULL;
|
||||
}
|
||||
else if (symname != NULL)
|
||||
canonical_name = xstrdup (symname);
|
||||
|
||||
self->canonical_names[sals->nelts - 1] = canonical_name;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1200,6 +1221,19 @@ find_toplevel_string (const char *haystack, const char *needle)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Convert CANONICAL to its string representation using
|
||||
symtab_to_fullname for SYMTAB. The caller must xfree the result. */
|
||||
|
||||
static char *
|
||||
canonical_to_fullform (const struct linespec_canonical_name *canonical)
|
||||
{
|
||||
if (canonical->symtab == NULL)
|
||||
return xstrdup (canonical->suffix);
|
||||
else
|
||||
return xstrprintf ("%s:%s", symtab_to_fullname (canonical->symtab),
|
||||
canonical->suffix);
|
||||
}
|
||||
|
||||
/* Given FILTERS, a list of canonical names, filter the sals in RESULT
|
||||
and store the result in SELF->CANONICAL. */
|
||||
|
||||
@ -1220,8 +1254,18 @@ filter_results (struct linespec_state *self,
|
||||
|
||||
for (j = 0; j < result->nelts; ++j)
|
||||
{
|
||||
if (strcmp (name, self->canonical_names[j]) == 0)
|
||||
const struct linespec_canonical_name *canonical;
|
||||
char *fullform;
|
||||
struct cleanup *cleanup;
|
||||
|
||||
canonical = &self->canonical_names[j];
|
||||
fullform = canonical_to_fullform (canonical);
|
||||
cleanup = make_cleanup (xfree, fullform);
|
||||
|
||||
if (strcmp (name, fullform) == 0)
|
||||
add_sal_to_sals_basic (&lsal.sals, &result->sals[j]);
|
||||
|
||||
do_cleanups (cleanup);
|
||||
}
|
||||
|
||||
if (lsal.sals.nelts > 0)
|
||||
@ -1247,6 +1291,44 @@ convert_results_to_lsals (struct linespec_state *self,
|
||||
VEC_safe_push (linespec_sals, self->canonical->sals, &lsal);
|
||||
}
|
||||
|
||||
/* A structure that contains two string representations of a struct
|
||||
linespec_canonical_name:
|
||||
- one where the the symtab's fullname is used;
|
||||
- one where the filename followed the "set filename-display"
|
||||
setting. */
|
||||
|
||||
struct decode_line_2_item
|
||||
{
|
||||
/* The form using symtab_to_fullname.
|
||||
It must be xfree'ed after use. */
|
||||
char *fullform;
|
||||
|
||||
/* The form using symtab_to_filename_for_display.
|
||||
It must be xfree'ed after use. */
|
||||
char *displayform;
|
||||
|
||||
/* Field is initialized to zero and it is set to one if the user
|
||||
requested breakpoint for this entry. */
|
||||
unsigned int selected : 1;
|
||||
};
|
||||
|
||||
/* Helper for qsort to sort decode_line_2_item entries by DISPLAYFORM and
|
||||
secondarily by FULLFORM. */
|
||||
|
||||
static int
|
||||
decode_line_2_compare_items (const void *ap, const void *bp)
|
||||
{
|
||||
const struct decode_line_2_item *a = ap;
|
||||
const struct decode_line_2_item *b = bp;
|
||||
int retval;
|
||||
|
||||
retval = strcmp (a->displayform, b->displayform);
|
||||
if (retval != 0)
|
||||
return retval;
|
||||
|
||||
return strcmp (a->fullform, b->fullform);
|
||||
}
|
||||
|
||||
/* Handle multiple results in RESULT depending on SELECT_MODE. This
|
||||
will either return normally, throw an exception on multiple
|
||||
results, or present a menu to the user. On return, the SALS vector
|
||||
@ -1257,58 +1339,80 @@ decode_line_2 (struct linespec_state *self,
|
||||
struct symtabs_and_lines *result,
|
||||
const char *select_mode)
|
||||
{
|
||||
const char *iter;
|
||||
char *args, *prompt;
|
||||
int i;
|
||||
struct cleanup *old_chain;
|
||||
VEC (const_char_ptr) *item_names = NULL, *filters = NULL;
|
||||
VEC (const_char_ptr) *filters = NULL;
|
||||
struct get_number_or_range_state state;
|
||||
struct decode_line_2_item *items;
|
||||
int items_count;
|
||||
|
||||
gdb_assert (select_mode != multiple_symbols_all);
|
||||
gdb_assert (self->canonical != NULL);
|
||||
gdb_assert (result->nelts >= 1);
|
||||
|
||||
old_chain = make_cleanup (VEC_cleanup (const_char_ptr), &item_names);
|
||||
make_cleanup (VEC_cleanup (const_char_ptr), &filters);
|
||||
for (i = 0; i < result->nelts; ++i)
|
||||
old_chain = make_cleanup (VEC_cleanup (const_char_ptr), &filters);
|
||||
|
||||
/* Prepare ITEMS array. */
|
||||
items_count = result->nelts;
|
||||
items = xmalloc (sizeof (*items) * items_count);
|
||||
make_cleanup (xfree, items);
|
||||
for (i = 0; i < items_count; ++i)
|
||||
{
|
||||
int j, found = 0;
|
||||
const char *iter;
|
||||
const struct linespec_canonical_name *canonical;
|
||||
struct decode_line_2_item *item;
|
||||
|
||||
gdb_assert (self->canonical_names[i] != NULL);
|
||||
for (j = 0; VEC_iterate (const_char_ptr, item_names, j, iter); ++j)
|
||||
canonical = &self->canonical_names[i];
|
||||
gdb_assert (canonical->suffix != NULL);
|
||||
item = &items[i];
|
||||
|
||||
item->fullform = canonical_to_fullform (canonical);
|
||||
make_cleanup (xfree, item->fullform);
|
||||
|
||||
if (canonical->symtab == NULL)
|
||||
item->displayform = canonical->suffix;
|
||||
else
|
||||
{
|
||||
if (strcmp (iter, self->canonical_names[i]) == 0)
|
||||
{
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
const char *fn_for_display;
|
||||
|
||||
fn_for_display = symtab_to_filename_for_display (canonical->symtab);
|
||||
item->displayform = xstrprintf ("%s:%s", fn_for_display,
|
||||
canonical->suffix);
|
||||
make_cleanup (xfree, item->displayform);
|
||||
}
|
||||
|
||||
if (!found)
|
||||
VEC_safe_push (const_char_ptr, item_names, self->canonical_names[i]);
|
||||
item->selected = 0;
|
||||
}
|
||||
|
||||
if (select_mode == multiple_symbols_cancel
|
||||
&& VEC_length (const_char_ptr, item_names) > 1)
|
||||
/* Sort the list of method names. */
|
||||
qsort (items, items_count, sizeof (*items), decode_line_2_compare_items);
|
||||
|
||||
/* Remove entries with the same FULLFORM. */
|
||||
if (items_count >= 2)
|
||||
{
|
||||
struct decode_line_2_item *dst, *src;
|
||||
|
||||
dst = items;
|
||||
for (src = &items[1]; src < &items[items_count]; src++)
|
||||
if (strcmp (src->fullform, dst->fullform) != 0)
|
||||
*++dst = *src;
|
||||
items_count = dst + 1 - items;
|
||||
}
|
||||
|
||||
if (select_mode == multiple_symbols_cancel && items_count > 1)
|
||||
error (_("canceled because the command is ambiguous\n"
|
||||
"See set/show multiple-symbol."));
|
||||
|
||||
if (select_mode == multiple_symbols_all
|
||||
|| VEC_length (const_char_ptr, item_names) == 1)
|
||||
if (select_mode == multiple_symbols_all || items_count == 1)
|
||||
{
|
||||
do_cleanups (old_chain);
|
||||
convert_results_to_lsals (self, result);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Sort the list of method names alphabetically. */
|
||||
qsort (VEC_address (const_char_ptr, item_names),
|
||||
VEC_length (const_char_ptr, item_names),
|
||||
sizeof (const_char_ptr), compare_strings);
|
||||
|
||||
printf_unfiltered (_("[0] cancel\n[1] all\n"));
|
||||
for (i = 0; VEC_iterate (const_char_ptr, item_names, i, iter); ++i)
|
||||
printf_unfiltered ("[%d] %s\n", i + 2, iter);
|
||||
for (i = 0; i < items_count; i++)
|
||||
printf_unfiltered ("[%d] %s\n", i + 2, items[i].displayform);
|
||||
|
||||
prompt = getenv ("PS2");
|
||||
if (prompt == NULL)
|
||||
@ -1343,16 +1447,16 @@ decode_line_2 (struct linespec_state *self,
|
||||
}
|
||||
|
||||
num -= 2;
|
||||
if (num >= VEC_length (const_char_ptr, item_names))
|
||||
if (num >= items_count)
|
||||
printf_unfiltered (_("No choice number %d.\n"), num);
|
||||
else
|
||||
{
|
||||
const char *elt = VEC_index (const_char_ptr, item_names, num);
|
||||
struct decode_line_2_item *item = &items[num];
|
||||
|
||||
if (elt != NULL)
|
||||
if (!item->selected)
|
||||
{
|
||||
VEC_safe_push (const_char_ptr, filters, elt);
|
||||
VEC_replace (const_char_ptr, item_names, num, NULL);
|
||||
VEC_safe_push (const_char_ptr, filters, item->fullform);
|
||||
item->selected = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2326,8 +2430,8 @@ decode_line_full (char **argptr, int flags,
|
||||
make_cleanup (xfree, state->canonical_names);
|
||||
for (i = 0; i < result.nelts; ++i)
|
||||
{
|
||||
gdb_assert (state->canonical_names[i] != NULL);
|
||||
make_cleanup (xfree, state->canonical_names[i]);
|
||||
gdb_assert (state->canonical_names[i].suffix != NULL);
|
||||
make_cleanup (xfree, state->canonical_names[i].suffix);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
2013-03-04 Jan Kratochvil <jan.kratochvil@redhat.com>
|
||||
|
||||
* gdb.linespec/base/one/thefile.cc (twodup): New.
|
||||
(m): Call it.
|
||||
* gdb.linespec/base/two/thefile.cc (dupname): New.
|
||||
(n): Call it.
|
||||
* gdb.linespec/break-ask.exp: New file.
|
||||
* gdb.linespec/lspec.cc (body_elsewhere): New comment marker.
|
||||
|
||||
2013-02-28 Yao Qi <yao@codesourcery.com>
|
||||
|
||||
* gdb.trace/report.exp: Move some code to ...
|
||||
|
@ -9,9 +9,14 @@
|
||||
|
||||
|
||||
|
||||
static int twodup ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int m(int x)
|
||||
{
|
||||
return x + 23; /* thefile breakpoint */
|
||||
return x + 23 + twodup (); /* thefile breakpoint */
|
||||
}
|
||||
|
||||
int NameSpace::overload(int x)
|
||||
|
@ -9,10 +9,15 @@ static int dupname(int y)
|
||||
label: return y;
|
||||
}
|
||||
|
||||
static int twodup ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n(int y)
|
||||
{
|
||||
int v = dupname(y) - 23; /* thefile breakpoint */
|
||||
return v; /* after dupname */
|
||||
return v + twodup (); /* after dupname */
|
||||
}
|
||||
|
||||
int NameSpace::overload(double x)
|
||||
|
100
gdb/testsuite/gdb.linespec/break-ask.exp
Normal file
100
gdb/testsuite/gdb.linespec/break-ask.exp
Normal file
@ -0,0 +1,100 @@
|
||||
# Copyright 2013 Free Software Foundation, Inc.
|
||||
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
standard_testfile lspec.cc
|
||||
|
||||
if {[skip_cplus_tests]} {
|
||||
unsupported ${testfile}.exp
|
||||
return
|
||||
}
|
||||
|
||||
set opts {debug c++}
|
||||
set objfile1 [standard_output_file ${testfile}one.o]
|
||||
set objfile2 [standard_output_file ${testfile}two.o]
|
||||
|
||||
if { [file pathtype $objdir] == "relative" } {
|
||||
untested "objdir $objdir should be absolute"
|
||||
return
|
||||
}
|
||||
set saved_pwd [pwd]
|
||||
cd $srcdir/${subdir}/base/one
|
||||
set err1 [gdb_compile "thefile.cc" $objfile1 object $opts]
|
||||
cd $saved_pwd
|
||||
cd $srcdir/${subdir}/base/two
|
||||
set err2 [gdb_compile "thefile.cc" $objfile2 object $opts]
|
||||
cd $saved_pwd
|
||||
if { $err1 != "" || $err2 != "" } {
|
||||
untested "compilation failed"
|
||||
return -1
|
||||
}
|
||||
|
||||
if { [gdb_compile "$srcdir/${subdir}/$srcfile $objfile1 $objfile2" \
|
||||
$binfile executable $opts] != "" } {
|
||||
return -1
|
||||
}
|
||||
|
||||
clean_restart ${testfile}
|
||||
|
||||
gdb_test_no_output "set multiple-symbols ask"
|
||||
|
||||
gdb_test_no_output "set filename-display absolute"
|
||||
set cmd "break twodup"
|
||||
set test "break twodup absolute"
|
||||
gdb_test_multiple $cmd $test {
|
||||
-re "^$cmd\r\n\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] \[^\r\n\]+/base/one/thefile\\.cc:twodup\\\(\\\)\r\n\\\[3\\\] \[^\r\n\]+/base/two/thefile\\.cc:twodup\\\(\\\)\r\n> $" {
|
||||
pass $test
|
||||
}
|
||||
}
|
||||
gdb_test "0" "canceled"
|
||||
|
||||
gdb_test_no_output "set filename-display relative"
|
||||
|
||||
set cmd "break twodup"
|
||||
set test "break twodup relative"
|
||||
gdb_test_multiple $cmd $test {
|
||||
-re "^$cmd\r\n\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] thefile\\.cc:twodup\\\(\\\)\r\n\\\[3\\\] thefile\\.cc:twodup\\\(\\\)\r\n> $" {
|
||||
pass $test
|
||||
}
|
||||
}
|
||||
gdb_test "2" "^2\r\nBreakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file thefile\\.cc, line \[0-9a-f\]+\\."
|
||||
|
||||
gdb_breakpoint "body_elsewhere"
|
||||
|
||||
gdb_run_cmd
|
||||
gdb_test "" "Breakpoint \[0-9\]+, twodup \\(\\) at thefile.cc:\[0-9\]+\r\n.*" "expect breakpoint"
|
||||
|
||||
gdb_test "info source" "\r\nLocated in \[^\r\n\]+/base/one/thefile\\.cc\r\n.*"
|
||||
|
||||
gdb_continue_to_breakpoint "body_elsewhere" ".* body_elsewhere marker .*"
|
||||
|
||||
delete_breakpoints
|
||||
|
||||
set cmd "break twodup"
|
||||
set test "break twodup relative other"
|
||||
gdb_test_multiple $cmd $test {
|
||||
-re "^$cmd\r\n\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] thefile\\.cc:twodup\\\(\\\)\r\n\\\[3\\\] thefile\\.cc:twodup\\\(\\\)\r\n> $" {
|
||||
pass $test
|
||||
}
|
||||
}
|
||||
gdb_test "3" "^3\r\nBreakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file thefile\\.cc, line \[0-9a-f\]+\\."
|
||||
|
||||
gdb_breakpoint "body_elsewhere"
|
||||
|
||||
gdb_run_cmd
|
||||
gdb_test "" "Breakpoint \[0-9\]+, twodup \\(\\) at thefile.cc:\[0-9\]+\r\n.*" "expect breakpoint other"
|
||||
|
||||
gdb_test "info source" "\r\nLocated in \[^\r\n\]+/base/two/thefile\\.cc\r\n.*" "info source other"
|
||||
|
||||
gdb_continue_to_breakpoint "body_elsewhere other" ".* body_elsewhere marker .*"
|
@ -9,7 +9,7 @@ int NameSpace::overload()
|
||||
|
||||
int body_elsewhere()
|
||||
{
|
||||
int x = 5;
|
||||
int x = 5; /* body_elsewhere marker */
|
||||
#include "body.h"
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user