Re: [RFC] canonical linespec and multiple breakpoints ...

Matt Rice
2011-05-06T18:08:24Z

[-- Attachment #1: Type: text/plain, Size: 1564 bytes --]

On Thu, May 5, 2011 at 9:42 PM, Joel Brobecker <brobecker@adacore.com> wrote:
>> You have commonly system libraries debug info installed and you debug
>> some unpackaged application without debug info.  You see there
>> application function `next_line', you `break next_line' on it.
>>
>> Oops, the breakpoint is missed, it broke on libc static function
>> `next_line' and not on the application function.
>
> OK. This means that we need to have a canonical form for symbols
> without debug info as well. We actually have something for Ada
> that could be extended to all languages, I think: We use angle
> brackets to denote the fact that an entity name is a linkage
> name.  For instance:
>
>        break <my_function_linkage_name>

here's a hastily thrown together hack of the approach I was
considering when i was looking at objective-c's ambiguity problems...

basically adding a decoder_info thing (which doesn't really contain
anything useful atm)

the idea is that we return this in linespec_result, and pass it back
in on the next call to decode_line_1

in the case of objc it being non-null should be enough to
disambiguate, if its non-null we're looking for an 'exact match' of
the name, otherwise we can return ambiguous results.

it may also be nice if we want to jump directly to the specific
decoder, instead of running them all sequentially every time on
re_set...

its an update of an older patch hasn't been tested very well/looked at
in a long time but seems to pass the testsuite with only racy
differences

[-- Attachment #2: foo.diff --]
[-- Type: application/octet-stream, Size: 14123 bytes --]

diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index b5fc448..d5eb537 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -64,6 +64,7 @@
#include "xml-syscall.h"
#include "parser-defs.h"
#include "cli/cli-utils.h"
+#include "linespec.h"

/* readline include files */
#include "readline/readline.h"
@@ -7337,7 +7338,8 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
enum bptype type, enum bpdisp disposition,
int thread, int task, int ignore_count,
struct breakpoint_ops *ops, int from_tty,
- int enabled, int internal, int display_canonical)
+ int enabled, int internal, int display_canonical,
+ struct linespec_breakpoint_info *decoder_info)
{
struct breakpoint *b = NULL;
int i;
@@ -7446,6 +7448,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
}
}

+ b->decoder_info = decoder_info;
b->display_canonical = display_canonical;
if (addr_string)
b->addr_string = addr_string;
@@ -7631,7 +7634,10 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
cond_string, type, disposition,
thread, task, ignore_count, ops,
from_tty, enabled, internal,
- canonical->special_display);
+ canonical->special_display,
+ canonical->decoder_info
+ ? canonical->decoder_info[i]
+ : NULL);
}
}

@@ -7698,10 +7704,10 @@ parse_breakpoint_sals (char **address,
|| ((strchr ("+-", (*address)[0]) != NULL)
&& ((*address)[1] != '['))))
*sals = decode_line_1 (address, 1, default_breakpoint_symtab,
- default_breakpoint_line, canonical);
+ default_breakpoint_line, canonical, NULL);
else
*sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0,
- canonical);
+ canonical, NULL);
}
/* For any SAL that didn't have a canonical string, fill one in. */
if (sals->nelts > 0 && canonical->canonical == NULL)
@@ -7925,8 +7931,12 @@ create_breakpoint (struct gdbarch *gdbarch,

copy_arg = savestring (addr_start, arg - addr_start);
canonical.canonical = xcalloc (sals.nelts, sizeof (char *));
+ canonical.decoder_info = xcalloc (sals.nelts, sizeof (struct linespec_breakpoint_info **));
for (i = 0; i < sals.nelts; i++)
- canonical.canonical[i] = xstrdup (copy_arg);
+ {
+ canonical.canonical[i] = xstrdup (copy_arg);
+ canonical.decoder_info[i] = NULL;
+ }
goto done;
}

@@ -8072,7 +8082,8 @@ create_breakpoint (struct gdbarch *gdbarch,
tempflag ? disp_del : disp_donttouch,
thread, task, ignore_count, ops,
from_tty, enabled, internal,
- canonical.special_display);
+ canonical.special_display,
+ canonical.decoder_info[i]);

do_cleanups (old_chain);

@@ -8117,6 +8128,7 @@ create_breakpoint (struct gdbarch *gdbarch,
b->enable_state = enabled ? bp_enabled : bp_disabled;
b->pspace = current_program_space;
b->py_bp_object = NULL;
+ b->decoder_info = NULL;

if (enabled && b->pspace->executing_startup
&& (b->type == bp_breakpoint
@@ -8576,7 +8588,7 @@ break_range_command (char *arg, int from_tty)
range. This makes it possible to have ranges like "foo.c:27, +14",
where +14 means 14 lines from the start location. */
sals_end = decode_line_1 (&arg, 1, sal_start.symtab, sal_start.line,
- &canonical_end);
+ &canonical_end, NULL);

/* canonical_end can be NULL if it was of the form "*0xdeadbeef". */
if (canonical_end.canonical == NULL)
@@ -9259,9 +9271,9 @@ until_break_command (char *arg, int from_tty, int anywhere)

if (default_breakpoint_valid)
sals = decode_line_1 (&arg, 1, default_breakpoint_symtab,
- default_breakpoint_line, NULL);
+ default_breakpoint_line, NULL, NULL);
else
- sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL);
+ sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL, NULL);

if (sals.nelts != 1)
error (_("Couldn't get information on specified line."));
@@ -10946,7 +10958,7 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
error (_("marker %s not found"), b->static_trace_marker_id);
}
else
- sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, NULL);
+ sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, NULL, b->decoder_info);
}
if (e.reason < 0)
{
@@ -11613,10 +11625,10 @@ decode_line_spec_1 (char *string, int funfirstline)
sals = decode_line_1 (&string, funfirstline,
default_breakpoint_symtab,
default_breakpoint_line,
- NULL);
+ NULL, NULL);
else
sals = decode_line_1 (&string, funfirstline,
- (struct symtab *) NULL, 0, NULL);
+ (struct symtab *) NULL, 0, NULL, NULL);
if (*string)
error (_("Junk at end of line specification: %s"), string);
return sals;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index 7a9c2d4..f3ccfcd 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -651,6 +651,9 @@ struct breakpoint

/* Whether this watchpoint is exact (see target_exact_watchpoints). */
int exact;
+
+ /* We hold onto this for, and pass it back in to decode_line_1. */
+ struct linespec_breakpoint_info *decoder_info;
};

typedef struct breakpoint *breakpoint_p;
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index 7fd2f50..0fc5efc 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -787,7 +787,7 @@ edit_command (char *arg, int from_tty)
/* Now should only be one argument -- decode it in SAL. */

arg1 = arg;
- sals = decode_line_1 (&arg1, 0, 0, 0, 0);
+ sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0);

if (! sals.nelts)
{
@@ -917,7 +917,7 @@ list_command (char *arg, int from_tty)
dummy_beg = 1;
else
{
- sals = decode_line_1 (&arg1, 0, 0, 0, 0);
+ sals = decode_line_1 (&arg1, 0, 0, 0, 0, 0);

if (!sals.nelts)
return; /* C++ */
@@ -950,9 +950,9 @@ list_command (char *arg, int from_tty)
else
{
if (dummy_beg)
- sals_end = decode_line_1 (&arg1, 0, 0, 0, 0);
+ sals_end = decode_line_1 (&arg1, 0, 0, 0, 0, 0);
else
- sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0);
+ sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0, 0);
if (sals_end.nelts == 0)
return;
if (sals_end.nelts > 1)
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 94bb86f..4bd459c 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -146,6 +146,8 @@ static struct
symtabs_and_lines minsym_found (int funfirstline,
struct minimal_symbol *msymbol);

+struct linespec_breakpoint_info *make_decoder_info(enum linespec_decoder_func_id);
+
/* Helper functions. */

/* Issue a helpful hint on using the command completion feature on
@@ -788,7 +790,8 @@ keep_name_info (char *ptr)

struct symtabs_and_lines
decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
- int default_line, struct linespec_result *canonical)
+ int default_line, struct linespec_result *canonical,
+ struct linespec_breakpoint_info *decoder_info)
{
char *p;
char *q;
@@ -822,7 +825,17 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
/* See if arg is *PC. */

if (**argptr == '*')
- return decode_indirect (argptr);
+ {
+ if (canonical)
+ {
+ struct linespec_breakpoint_info **decoder_info;
+
+ decoder_info = xmalloc (sizeof (struct linespec **) * 1);
+ decoder_info[0] = make_decoder_info (decoder_indirect);
+ canonical->decoder_info = decoder_info;
+ }
+ return decode_indirect (argptr);
+ }

is_quoted = (strchr (get_gdb_completer_quote_characters (),
**argptr) != NULL);
@@ -853,6 +866,21 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,

values = decode_objc (argptr, funfirstline, NULL,
canonical, saved_arg);
+ if (canonical && values.sals)
+ {
+ struct linespec_breakpoint_info **decoder_info;
+ int i;
+
+ decoder_info = xmalloc (sizeof (struct linespec **) * values.nelts);
+
+ for (i = 0; i < values.nelts; i++)
+ {
+ decoder_info[i] = make_decoder_info (decoder_objc);
+ }
+
+ canonical->decoder_info = decoder_info;
+ }
+
if (values.sals != NULL)
return values;
}
@@ -878,6 +906,22 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
saved_arg, p);
if (is_quoted && **argptr == '\'')
*argptr = *argptr + 1;
+
+ if (canonical)
+ {
+ struct linespec_breakpoint_info **decoder_info;
+ int i;
+
+ decoder_info = xmalloc (sizeof (struct linespec **)
+ * values.nelts);
+
+ for (i = 0; i < values.nelts; i++)
+ {
+ decoder_info[i] = make_decoder_info (decoder_compound);
+ }
+
+ canonical->decoder_info = decoder_info;
+ }
return values;
}

@@ -1941,6 +1985,16 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
if (need_canonical)
build_canonical_line_spec (values.sals, NULL, canonical);
values.sals[0].explicit_line = 1;
+
+ if (canonical)
+ {
+ struct linespec_breakpoint_info **decoder_info;
+
+ decoder_info = xmalloc (sizeof (struct linespec **) * 1);
+ decoder_info[0] = make_decoder_info (decoder_all_digits);
+ canonical->decoder_info = decoder_info;
+ }
+
return values;
}

@@ -1961,6 +2015,15 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
struct symbol *sym;
struct minimal_symbol *msymbol;

+ if (canonical)
+ {
+ struct linespec_breakpoint_info **decoder_info;
+
+ decoder_info = xmalloc (sizeof (struct linespec **) * 1);
+ decoder_info[0] = make_decoder_info (decoder_dollar);
+ canonical->decoder_info = decoder_info;
+ }
+
p = (copy[1] == '$') ? copy + 2 : copy + 1;
while (*p >= '0' && *p <= '9')
p++;
@@ -2039,6 +2102,15 @@ decode_label (struct symbol *function_symbol, char *copy,
struct symbol *sym;
struct block *block;

+ if (canonical)
+ {
+ struct linespec_breakpoint_info **decoder_info;
+
+ decoder_info = xmalloc (sizeof (struct linespec **) * 1);
+ decoder_info[0] = make_decoder_info (decoder_label);
+ canonical->decoder_info = decoder_info;
+ }
+
if (function_symbol)
block = SYMBOL_BLOCK_VALUE (function_symbol);
else
@@ -2072,6 +2144,15 @@ decode_variable (char *copy, int funfirstline,
struct symbol *sym;
struct minimal_symbol *msymbol;

+ if (canonical)
+ {
+ struct linespec_breakpoint_info **decoder_info;
+
+ decoder_info = xmalloc (sizeof (struct linespec **) * 1);
+ decoder_info[0] = make_decoder_info (decoder_variable);
+ canonical->decoder_info = decoder_info;
+ }
+
sym = lookup_symbol (copy,
(file_symtab
? BLOCKVECTOR_BLOCK (BLOCKVECTOR (file_symtab),
@@ -2223,3 +2304,13 @@ init_linespec_result (struct linespec_result *lr)
{
memset (lr, 0, sizeof (*lr));
}
+
+struct linespec_breakpoint_info *
+make_decoder_info(enum linespec_decoder_func_id decoder)
+{
+ struct linespec_breakpoint_info *decoder_info = xmalloc(sizeof(struct linespec_breakpoint_info));
+
+ decoder_info->decoder = decoder;
+
+ return decoder_info;
+}
diff --git a/gdb/linespec.h b/gdb/linespec.h
index 3c86af3..9324f85 100644
--- a/gdb/linespec.h
+++ b/gdb/linespec.h
@@ -20,6 +20,24 @@

struct symtab;

+enum linespec_decoder_func_id {
+ decoder_unknown = 0,
+ decoder_compound,
+ decoder_objc,
+ decoder_label,
+ decoder_indirect,
+ decoder_all_digits,
+ decoder_dollar,
+ decoder_variable
+};
+
+/* If linespec returns one of these in linespec_result it wants you
+ to pass it back to it should you call decode_line_1 again. */
+struct linespec_breakpoint_info
+{
+ enum linespec_decoder_func_id decoder;
+};
+
/* An instance of this may be filled in by decode_line_1. The caller
must call init_linespec_result to initialize it. */

@@ -37,6 +55,10 @@ struct linespec_result
element in it are allocated with xmalloc and must be freed by the
caller. */
char **canonical;
+
+ /* Stuff linespec wants breakpoint to hold onto and pass back on
+ breakpoint re setting. Same rules as canonical. */
+ struct linespec_breakpoint_info **decoder_info;
};

/* Initialize a linespec_result. */
@@ -46,6 +68,7 @@ extern void init_linespec_result (struct linespec_result *);
extern struct symtabs_and_lines
decode_line_1 (char **argptr, int funfirstline,
struct symtab *default_symtab, int default_line,
- struct linespec_result *canonical);
+ struct linespec_result *canonical,
+ struct linespec_breakpoint_info *decoder_info);

#endif /* defined (LINESPEC_H) */
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 8a7bc66..90d5dc8 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -454,7 +454,7 @@ gdbpy_decode_line (PyObject *self, PyObject *args)
arg = xstrdup (arg);
make_cleanup (xfree, arg);
copy = arg;
- sals = decode_line_1 (&copy, 0, 0, 0, 0);
+ sals = decode_line_1 (&copy, 0, 0, 0, 0, 0);
make_cleanup (xfree, sals.sals);
}
else
diff --git a/gdb/symtab.c b/gdb/symtab.c
index d98ac57..3645093 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -4395,7 +4395,7 @@ decode_line_spec (char *string, int funfirstline)

sals = decode_line_1 (&string, funfirstline,
cursal.symtab, cursal.line,
- NULL);
+ NULL, NULL);

if (*string)
error (_("Junk at end of line specification: %s"), string);
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 119ab22..0226613 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -2333,7 +2333,7 @@ scope_info (char *args, int from_tty)
error (_("requires an argument (function, "
"line or *addr) to define a scope"));

- sals = decode_line_1 (&args, 1, NULL, 0, NULL);
+ sals = decode_line_1 (&args, 1, NULL, 0, NULL, NULL);
if (sals.nelts == 0)
return; /* Presumably decode_line_1 has already warned. */