* 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:
Jan Kratochvil 2013-03-04 19:30:28 +00:00
parent feb1472522
commit 33f448b11e
7 changed files with 285 additions and 49 deletions

View File

@ -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

View File

@ -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);
}
}

View File

@ -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 ...

View File

@ -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)

View File

@ -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)

View 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 .*"

View File

@ -9,7 +9,7 @@ int NameSpace::overload()
int body_elsewhere()
{
int x = 5;
int x = 5; /* body_elsewhere marker */
#include "body.h"
}