* GDB 7.4 branching status? (2011-11-23)
@ 2011-11-23 16:39 Joel Brobecker
2011-11-23 16:56 ` Tristan Gingold
` (3 more replies)
0 siblings, 4 replies; 42+ messages in thread
From: Joel Brobecker @ 2011-11-23 16:39 UTC (permalink / raw)
To: gdb-patches
Hello everyone,
Today was the day we were hoping to create the branch from.
I don't think we're quite ready:
- I think we might still have some patches that are unreviewed.
The cutoff was: Friday night Nov 11. Please ping us to make
sure they do not fall through the cracks!
- We're still waiting for Tom's awesome work on ambiguous linespec.
I think he's more or less ready to go, once he's re-based and
re-posted his patches (with a couple of improvements made for
the Ada support)
- I just discovered a build failure in gdb-dlfcn on Windows.
I need to investigate a little further what's going on, but
I am hoping to be able to send a patch soon.
On the optional TODO list, we have:
- Support for Darwin/Lion - Tristan told me that he started working
on this, but I don't think it's full time. I don't think we should
delay the branch without some sort of idea of how much time we
expect this work to take.
- Yao's tracepoint feature: Download tracepoint locations when tracing
is running.
I think all the patches are in, now, right?
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-23 16:39 GDB 7.4 branching status? (2011-11-23) Joel Brobecker
@ 2011-11-23 16:56 ` Tristan Gingold
2011-11-23 18:47 ` Tom Tromey
` (2 subsequent siblings)
3 siblings, 0 replies; 42+ messages in thread
From: Tristan Gingold @ 2011-11-23 16:56 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Nov 23, 2011, at 5:39 PM, Joel Brobecker wrote:
> Hello everyone,
>
> Today was the day we were hoping to create the branch from.
> I don't think we're quite ready:
>
> - I think we might still have some patches that are unreviewed.
> The cutoff was: Friday night Nov 11. Please ping us to make
> sure they do not fall through the cracks!
>
> - We're still waiting for Tom's awesome work on ambiguous linespec.
> I think he's more or less ready to go, once he's re-based and
> re-posted his patches (with a couple of improvements made for
> the Ada support)
>
> - I just discovered a build failure in gdb-dlfcn on Windows.
> I need to investigate a little further what's going on, but
> I am hoping to be able to send a patch soon.
>
> On the optional TODO list, we have:
>
> - Support for Darwin/Lion - Tristan told me that he started working
> on this, but I don't think it's full time. I don't think we should
> delay the branch without some sort of idea of how much time we
> expect this work to take.
I have just finished the major part of this work. I plan to commit it tomorrow.
Tristan.
>
> - Yao's tracepoint feature: Download tracepoint locations when tracing
> is running.
>
> I think all the patches are in, now, right?
>
> --
> Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-23 16:39 GDB 7.4 branching status? (2011-11-23) Joel Brobecker
2011-11-23 16:56 ` Tristan Gingold
@ 2011-11-23 18:47 ` Tom Tromey
2011-11-23 23:24 ` Joel Brobecker
2011-11-24 0:58 ` GDB 7.4 branching status? (2011-11-23) Yao Qi
2011-11-24 17:17 ` Maciej W. Rozycki
3 siblings, 1 reply; 42+ messages in thread
From: Tom Tromey @ 2011-11-23 18:47 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> - We're still waiting for Tom's awesome work on ambiguous linespec.
Joel> I think he's more or less ready to go, once he's re-based and
Joel> re-posted his patches (with a couple of improvements made for
Joel> the Ada support)
I was composing a note this morning about the issues we were
discussing. I think I will just write it here instead of gdb@.
Joel and Jerome found a couple of bugs in the existing patches.
First, there was an Ada-specific bug that I can't readily describe. I
solved this by adding a new language method, implemented only by Ada,
that basically exposes a form of ada_lookup_symbol_list to linespec. I
will send this separately, today, for review.
Second, it turns out that FILE:LINE linespecs are trickier than they may
first appear. Specifically, the problems arise due to their "inexact
match" semantics" -- if LINE is not seen in a symtab, gdb will pick the
next executable line from the symtab.
This yields a few problems. A simple one is if you have multiple
instances of a symtab where some functions are instantiated in one use
and some in another use -- say, a C++ header with template functions in
it. Then if you "break header.h:LINE", with the current patches you can
wind up with breakpoints in functions that do not actually cover LINE.
This brings up the idea of trying to see "is LINE covered by the
resulting function?". But, this is tough with gdb's current line
tables. For example, the simplest approach of checking the starting
line of the function (let's call this "heuristic 1") fails for this sort
of case:
void function () {
#include "body.h"
}
I think maybe it would be possible to do this by replaying the line
number program, but I am not totally sure.
I implemented another heuristic ("heuristic 2") instead: if the function
is defined in a different symtab, assume it is ok; otherwise, if it is
defined in the same symtab, require that the function's first line be <=
than the requested line.
This heuristic works ok-ish, but there is a specific Ada case that still
fails.
Joel then suggested another heuristic ("heuristic 3"):
Me neither. Our ideas revolved around the idea of marking a SAL as
questionable if it is the first line in the symtab, and its line
number is strictly greater than the requested line number. If we
find other SALs that are not questionable, then discard the questionable
ones.
[...]
If SAL is questionable (using the definition above), and another
symtab contains a function whose line range inclues our target line,
then the SAL should be discarded. This should take care of our
original example involving the generic, and should take care of
the inlining case above as well (this assume that the compiler would
mark the first line of the function to be on line 10, not 11 as my
example suggests).
I am not sure how to implement "and another symtab contains a function
whose line range includes our target line". I am not certain but it
seems to beg the question: if we could determine whether a function
contains a given line, then we could just apply this directly to the
location we just found.
If you are interested in trying to come up with a heuristic, consider
this scenario as well: two files named "file.c". In one file, line 53
is a comment in the middle of a function. In another file, line 53 is
executable. In this case, "break file.c:53" should still set 2
breakpoints.
Another idea I had ("heuristic 4"):
One maybe simpler idea I came up with today is to consider an exact
match in a given symtab, as determined by dirname+filename, to override
all inexact matches.
This would let the file.c:53 case work. But, I think it would reject
the Ada test case we have been struggling with: pack.o has a line 10, so
it would prohibit us from finding the false match in m.o.
The use of the symtab's dirname+filename as the discriminant is there to
let us handle the multiple-files-same-name case.
Joel thinks that this would probably not work:
This is the initial idea that we had. But that might break down in
the case of inlining that I mentioned, no?
10 procedure Foo is
11 begin
12 Do_Something;
In the case of the inlined instance, I would suspect that there would
be no code for line 10 and 11 since no prologue would be necessary.
Someone inserting a breakpoint on line 10 would get the non-inlined
instance, but would miss the inlined one.
A couple of observations.
First, I think having too many locations is better than having too few.
With too many, at least the user can disable some. With too few,
whoops, gdb isn't doing as asked.
Second, at least initially the heuristic only has to perform as well as
what gdb already does. It is pretty easy to construct cases where
"break file:line" sets a breakpoint in the wrong function entirely.
From the latest version of the test case I have here, using cvs head
gdb:
$ nl -ba lspec.h
[...]
11 int f1(void)
12 {
13 return 1; /* f1 breakpoint */
14 }
[...]
20 int f2(void)
21 {
22 return 1; /* f2 breakpoint */
23 }
[...]
(gdb) b lspec.h:13
Breakpoint 1 at 0x400554: file ../../../archer/gdb/testsuite/gdb.linespec/base/two/../../lspec.h, line 13.
(gdb) info b
Num Type Disp Enb Address What
1 breakpoint keep y 0x0000000000400554 in f2()
at ../../../archer/gdb/testsuite/gdb.linespec/base/two/../../lspec.h:13
Oops, it broke in f2, even though f1 actually exists in the program:
(gdb) b f1
Breakpoint 2 at 0x400528: file ../../../archer/gdb/testsuite/gdb.linespec/base/one/../../lspec.h, line 13.
Note the line numbers.
To sum up, this is the last known problem facing this patch series. I
would like to resolve it, but I am not sure exactly how, so I am looking
for input.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-23 18:47 ` Tom Tromey
@ 2011-11-23 23:24 ` Joel Brobecker
2011-11-24 10:56 ` Jerome Guitton
0 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-23 23:24 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
Thanks, Tom, for sending out a summary (this started out as an informal
discussion on IRC while asking Tom questions about what we were seeing
when we tried the patch out).
On second thoughts, I don't think the heuristics I proposed are
going to work. It's easy to defeat by trying to insert a breakpoint
inside a generic function (procedure Second is our Generic/Template
function here):
7 procedure Second is
8 begin
9 Do_Nothing;
10 end Second;
11
12 procedure Third is
13 begin
14 Do_Nothing;
15 end Third;
With that, AdaCore's GDB yields:
(gdb) b pck.adb:9
[0] cancel
[1] all
[2] pck.third <<<<---------- This one is wrong
[3] foo.good_second
So, the idea of marking the lines below the first line of code
as suspect doesn't work. All we need is to produce the issue is
a "hole" in the linetable.
Heuristic 4 (where exact matches in a given symtab, as determine by
dirname + filename override inexact matches) isn't bad, and I think
it would prevent us from seeing the problem with generics above.
That's actually what we do today, except that we don't do the
dirname + filename check, because we're only concerned with returning
one single location.
However, I think it would miss some location as I explained using
my example with inlined functions. I think that it's a bit of
a corner case, but still legitimate.
On the other hand, the other heuristic that I like the most so far
is the simplest one, which takes the first line we find, inexact
and all. The downside is that we'll have too many matches.
> A couple of observations.
>
> First, I think having too many locations is better than having too few.
> With too many, at least the user can disable some. With too few,
> whoops, gdb isn't doing as asked.
>
> Second, at least initially the heuristic only has to perform as well as
> what gdb already does.
I agree.
Right now, we're stuck between a rock and a hard place. So it's
more of a matter of deciding which approach matches our goals
the most. If we go by the principles above, the simpler heuristic
seems the way to go. It introduces an apparent regression for Ada,
but I don't see a simple way around it that does not sacrifice
a little bit of the principles above. We're just going to have
to call it a limitation.
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-23 16:39 GDB 7.4 branching status? (2011-11-23) Joel Brobecker
2011-11-23 16:56 ` Tristan Gingold
2011-11-23 18:47 ` Tom Tromey
@ 2011-11-24 0:58 ` Yao Qi
2011-11-24 17:17 ` Maciej W. Rozycki
3 siblings, 0 replies; 42+ messages in thread
From: Yao Qi @ 2011-11-24 0:58 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On 11/24/2011 12:39 AM, Joel Brobecker wrote:
> - Yao's tracepoint feature: Download tracepoint locations when tracing
> is running.
>
> I think all the patches are in, now, right?
Yes, all 'pending tracepoint' patches are in.
--
Yao (é½å°§)
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-23 23:24 ` Joel Brobecker
@ 2011-11-24 10:56 ` Jerome Guitton
2011-11-24 16:33 ` Joel Brobecker
0 siblings, 1 reply; 42+ messages in thread
From: Jerome Guitton @ 2011-11-24 10:56 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Tom Tromey, gdb-patches
Joel Brobecker (brobecker@adacore.com):
> > First, I think having too many locations is better than having too few.
> > With too many, at least the user can disable some. With too few,
> > whoops, gdb isn't doing as asked.
> >
> > Second, at least initially the heuristic only has to perform as well as
> > what gdb already does.
>
> I agree.
>
> Right now, we're stuck between a rock and a hard place. So it's
> more of a matter of deciding which approach matches our goals
> the most. If we go by the principles above, the simpler heuristic
> seems the way to go. It introduces an apparent regression for Ada,
> but I don't see a simple way around it that does not sacrifice
> a little bit of the principles above. We're just going to have
> to call it a limitation.
Well, having a regression for Ada defeats the second principle, IMHO :)
And I think that it is not Ada-specific at all actually; to reproduce
the problem in C++, you just need to have a couple of
templates/inlined functions in a header and have them instanciated in
different source files.
What about having the same heuristics as expand_line_sal used to have for
this kind of issue? At least we would have the exact same behavior as
before...
You reported that this heuristic was the following:
The approach they use is to select exact matches first. And then, if there
are no exact matches, then select exact matches for the first line above the
selected line.
This heuristic is flawed as well, but the other that have been proposed
so far have some issues themselves. So maybe we should just start with
what we already have before trying to find a clever solution?
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-24 10:56 ` Jerome Guitton
@ 2011-11-24 16:33 ` Joel Brobecker
2011-11-28 16:17 ` Tom Tromey
2011-11-28 21:29 ` Tom Tromey
0 siblings, 2 replies; 42+ messages in thread
From: Joel Brobecker @ 2011-11-24 16:33 UTC (permalink / raw)
To: Jerome Guitton; +Cc: Tom Tromey, gdb-patches
> Well, having a regression for Ada defeats the second principle, IMHO :)
Yes, but right now, we cannot seem to satisfy all of our principles,
so it is a matter of deciding what's best for this iteration.
> What about having the same heuristics as expand_line_sal used to have
> for this kind of issue? At least we would have the exact same behavior
> as before...
We proposed that as well, and I am fine with that approach too. But
we have to bear in mind that we will be missing some location in
some (corner only?) cases.
So, for now, either approach is fine with me, maybe with a slight
preference for possibly accepting more locations in order to avoid
missing some. So prefer keeping the previous the previous heuristic,
which I think makes sense as well - no surprise in a way. What do
others think?
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-23 16:39 GDB 7.4 branching status? (2011-11-23) Joel Brobecker
` (2 preceding siblings ...)
2011-11-24 0:58 ` GDB 7.4 branching status? (2011-11-23) Yao Qi
@ 2011-11-24 17:17 ` Maciej W. Rozycki
2011-11-24 17:27 ` Joel Brobecker
3 siblings, 1 reply; 42+ messages in thread
From: Maciej W. Rozycki @ 2011-11-24 17:17 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Wed, 23 Nov 2011, Joel Brobecker wrote:
> - I think we might still have some patches that are unreviewed.
> The cutoff was: Friday night Nov 11. Please ping us to make
> sure they do not fall through the cracks!
For the avoidance of doubt -- none of the patches I've been sending
lately I consider important for the release branch. If anything these are
new features or fixes for long-standing bugs that nobody must have
complained against our trunk or they would have been long fixed so I am
perfectly happy to get them sorted on trunk only once the branch has been
made so that they can go through all the usual crash testing before the
following release. Unless you or anyone is interested in having a
particular change included in the upcoming release that is -- please speak
out if so. Thanks.
Maciej
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-24 17:17 ` Maciej W. Rozycki
@ 2011-11-24 17:27 ` Joel Brobecker
2011-12-03 1:19 ` Maciej W. Rozycki
0 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-24 17:27 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: gdb-patches
> For the avoidance of doubt -- none of the patches I've been sending
> lately I consider important for the release branch. If anything these are
> new features or fixes for long-standing bugs that nobody must have
> complained against our trunk or they would have been long fixed so I am
> perfectly happy to get them sorted on trunk only once the branch has been
> made so that they can go through all the usual crash testing before the
> following release. Unless you or anyone is interested in having a
> particular change included in the upcoming release that is -- please speak
> out if so. Thanks.
Thanks. Still, it would be nice if we could at least review them...
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-24 16:33 ` Joel Brobecker
@ 2011-11-28 16:17 ` Tom Tromey
2011-11-28 21:29 ` Tom Tromey
1 sibling, 0 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-28 16:17 UTC (permalink / raw)
To: Joel Brobecker; +Cc: Jerome Guitton, gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Jerome> What about having the same heuristics as expand_line_sal used to have
Jerome> for this kind of issue? At least we would have the exact same behavior
Jerome> as before...
Joel> We proposed that as well, and I am fine with that approach too. But
Joel> we have to bear in mind that we will be missing some location in
Joel> some (corner only?) cases.
Joel> So, for now, either approach is fine with me, maybe with a slight
Joel> preference for possibly accepting more locations in order to avoid
Joel> missing some. So prefer keeping the previous the previous heuristic,
Joel> which I think makes sense as well - no surprise in a way. What do
Joel> others think?
I think this makes sense. I will implement it today or tomorrow.
Also this made me remember that I intended to remove expand_line_sal,
but forgot. So, I will do that too.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-24 16:33 ` Joel Brobecker
2011-11-28 16:17 ` Tom Tromey
@ 2011-11-28 21:29 ` Tom Tromey
2011-11-29 2:28 ` Joel Brobecker
` (8 more replies)
1 sibling, 9 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-28 21:29 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 581 bytes --]
Here are the latest patches.
The ChangeLog entries are screwy, I will clean them up before checkin.
I am only including the big main patch, plus the Ada patch.
The other patches haven't changed in recent rebases.
Built and regtested on x86-64 F15.
Relative to the previous patch, I:
* Removed expand_line_sal
* Removed validate_inexact_match
* Changed decode_all_digits to replicate the logic that used to be in
expand_line_sal
* Removed decode_line_list and instead added a "flags" enum and
changed all callers
* Changed "info line" and "clear" to use "list mode"
Tom
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: main patch --]
[-- Type: text/x-patch, Size: 252219 bytes --]
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a35c692..1aebcc4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,36 @@
+2011-11-28 Tom Tromey <tromey@redhat.com>
+
+ * source.c (line_info): Use DECODE_LINE_LIST_MODE.
+ * breakpoint.c (clear_command): Use DECODE_LINE_LIST_MODE.
+ * linespec.c (decode_digits_line_mode): New function.
+ (decode_digits_ordinary): Likewise.
+ * symtab.c (append_expanded_sal): Remove.
+ (append_exact_match_to_sals): Remove.
+ (expand_line_sal): Remove.
+ * symtab.h (expand_line_sal): Remove.
+
+2011-11-22 Tom Tromey <tromey@redhat.com>
+
+ * linespec.c (iterate_over_all_matching_symtabs): Call
+ la_iterate_over_symbols.
+ (find_function_symbols, decode_variable): Remove Ada special
+ case.
+ * language.h (struct language_defn) <la_iterate_over_symbols>: New
+ field.
+ * language.c (unknown_language_defn, auto_language_defn)
+ (local_language_defn): Update.
+ * c-lang.c (c_language_defn, cplus_language_defn)
+ (asm_language_defn, minimal_language_defn): Update.
+ * d-lang.c (d_language_defn): Update.
+ * f-lang.c (f_language_defn): Update.
+ * jv-lang.c (java_language_defn): Update.
+ * m2-lang.c (m2_language_defn): Update.
+ * objc-lang.c (objc_language_defn): Update.
+ * opencl-lang.c (opencl_language_defn): Update.
+ * p-lang.c (pascal_language_defn): Update.
+ * ada-lang.c (ada_iterate_over_symbols): New function.
+ (ada_language_defn): Update.
+
2011-11-28 Phil Muldoon <pmuldoon@redhat.com>
PR python/13369
@@ -248,6 +281,158 @@
2011-11-18 Tom Tromey <tromey@redhat.com>
+ PR breakpoints/13105, PR objc/8341, PR objc/8343, PR objc/8366,
+ PR objc/8535, PR breakpoints/11657, PR breakpoints/11970,
+ PR breakpoints/12023, PR breakpoints/12334, PR breakpoints/12856,
+ PR shlibs/8929, PR shlibs/7393:
+ * python/py-type.c (compare_maybe_null_strings): Rename from
+ compare_strings.
+ (check_types_equal): Update.
+ * utils.c (compare_strings): New function.
+ * tui/tui-winsource.c (tui_update_breakpoint_info): Update for
+ location changes.
+ * tracepoint.c (scope_info): Update.
+ * symtab.h (iterate_over_minimal_symbols)
+ (iterate_over_some_symtabs, iterate_over_symtabs)
+ (find_pcs_for_symtab_line, iterate_over_symbols)
+ (demangle_for_lookup): Declare.
+ * symtab.c (iterate_over_some_symtabs, iterate_over_symtabs)
+ (lookup_symtab_callback): New functions.
+ (lookup_symtab): Rewrite.
+ (demangle_for_lookup): New function, extract from
+ lookup_symbol_in_language.
+ (lookup_symbol_in_language): Use it.
+ (iterate_over_symbols): New function.
+ (find_line_symtab): Update.
+ (find_pcs_for_symtab_line): New functions.
+ (find_line_common): Add 'start' argument.
+ (decode_line_spec): Update.
+ (validate_inexact_match): New function.
+ * symfile.h (struct quick_symbol_functions) <lookup_symtab>:
+ Remove.
+ <map_symtabs_matching_filename>: New field.
+ * stack.c (func_command): Only look in the current program space.
+ * source.c (line_info): Set pspace on sal. Check program space in
+ the loop.
+ * solib-target.c: Remove DEF_VEC_I(CORE_ADDR).
+ * python/python.c (gdbpy_decode_line): Update.
+ * psymtab.c (partial_map_expand_apply): New function.
+ (partial_map_symtabs_matching_filename): Rename from
+ lookup_partial_symbol. Update arguments.
+ (lookup_symtab_via_partial_symtab): Remove.
+ (psym_functions): Update.
+ * objc-lang.h (parse_selector, parse_method): Don't declare.
+ (find_imps): Update.
+ * objc-lang.c (parse_selector, parse_method): Now static.
+ (find_methods): Change arguments. Fill in a vector of symbol
+ names.
+ (uniquify_strings): New function.
+ (find_imps): Change arguments.
+ * minsyms.c (iterate_over_minimal_symbols): New function.
+ * linespec.h (struct linespec_sals): New type.
+ (struct linespec_result) <canonical>: Remove.
+ (enum decode_line_flags): New.
+ <pre_expanded, addr_string, sals>: New fields.
+ (destroy_linespec_result, make_cleanup_destroy_linespec_result)
+ (decode_line_full): Declare.
+ (decode_line_1): Update.
+ * linespec.c (struct address_entry, struct linespec_state, struct
+ collect_info): New types.
+ (add_sal_to_sals_basic, add_sal_to_sals, hash_address_entry)
+ (eq_address_entry, maybe_add_address): New functions.
+ (total_number_of_methods): Remove.
+ (iterate_name_matcher, iterate_over_all_matching_symtabs): New
+ functions.
+ (find_methods): Change arguments. Don't canonicalize input.
+ Simplify logic.
+ (add_matching_methods, add_constructors)
+ (build_canonical_line_spec): Remove.
+ (filter_results, convert_results_to_lsals): New functions.
+ (decode_line_2): Change arguments. Rewrite for new data
+ structures.
+ (decode_line_internal): Rename from decode_line_1. Change
+ arguments. Add cleanups. Update for new data structures.
+ (linespec_state_constructor, linespec_state_destructor)
+ (decode_line_full, decode_line_1): New functions.
+ (decode_indirect): Change arguments. Update.
+ (locate_first_half): Use skip_spaces.
+ (decode_objc): Change arguments. Update for new data structures.
+ Simplify logic.
+ (decode_compound): Change arguments. Add cleanups. Fall back on
+ decode_variable.
+ (struct decode_compound_collector): New type.
+ (collect_one_symbol): New function.
+ (lookup_prefix_sym): Change arguments. Update.
+ (compare_symbol_name, add_all_symbol_names_from_pspace)
+ (find_superclass_methods ): New functions.
+ (find_method): Rewrite.
+ (struct symtab_collector): New type.
+ (add_symtabs_to_list, collect_symtabs_from_filename): New
+ functions.
+ (symtabs_from_filename): Change API. Rename from
+ symtab_from_filename.
+ (collect_function_symbols): New function.
+ (find_function_symbols): Change API. Rename from
+ find_function_symbol. Rewrite.
+ (decode_all_digits): Change arguments. Rewrite.
+ (decode_dollar): Change arguments. Use decode_variable.
+ (decode_label): Change arguments. Rewrite.
+ (collect_symbols): New function.
+ (minsym_found): Change arguments. Rewrite.
+ (check_minsym, search_minsyms_for_name)
+ (add_matching_symbols_to_info): New function.
+ (decode_variable): Change arguments. Iterate over all symbols.
+ (symbol_found): Remove.
+ (symbol_to_sal): New function.
+ (init_linespec_result, destroy_linespec_result)
+ (cleanup_linespec_result, make_cleanup_destroy_linespec_result):
+ New functions.
+ * dwarf2read.c (dw2_map_expand_apply): New function.
+ (dw2_map_symtabs_matching_filename): Rename from
+ dw2_lookup_symtab. Change arguments.
+ (dwarf2_gdb_index_functions): Update.
+ * dwarf2loc.c: Remove DEF_VEC_I(CORE_ADDR).
+ * defs.h (compare_strings): Declare.
+ * cli/cli-cmds.c (compare_strings): Move to utils.c.
+ (edit_command, list_command): Use decode_line_list. Call
+ filter_sals.
+ (compare_symtabs, filter_sals): New functions.
+ * breakpoint.h (struct bp_location) <line_number, source_file>:
+ New fields.
+ (struct breakpoint) <line_number, source_file>: Remove.
+ <filter>: New field.
+ * breakpoint.c (print_breakpoint_location, init_raw_breakpoint)
+ (momentary_breakpoint_from_master, add_location_to_breakpoint):
+ Update for changes to locations.
+ (init_breakpoint_sal): Add 'filter' argument. Set 'filter' on
+ breakpoint.
+ (create_breakpoint_sal): Add 'filter' argument.
+ (remove_sal, expand_line_sal_maybe): Remove.
+ (create_breakpoints_sal): Remove 'sals' argument. Handle
+ pre-expanded sals and the filter.
+ (parse_breakpoint_sals): Use decode_line_full.
+ (check_fast_tracepoint_sals): Use get_sal_arch.
+ (create_breakpoint): Create a linespec_sals. Update.
+ (break_range_command): Use decode_line_full. Update.
+ (until_break_command): Update.
+ (clear_command): Update match conditions for linespec.c changes.
+ (say_where): Update for changes to locations.
+ (bp_location_dtor): Free 'source_file'.
+ (base_breakpoint_dtor): Free 'filter'. Don't free 'source_file'.
+ (update_static_tracepoint): Update for changes to locations.
+ (update_breakpoint_locations): Disable ranged breakpoint if too
+ many locations match. Update.
+ (addr_string_to_sals): Use decode_line_full. Resolve all sal
+ PCs.
+ (breakpoint_re_set_default): Don't call expand_line_sal_maybe.
+ (decode_line_spec_1): Update.
+ * block.h (block_containing_function): Declare.
+ * block.c (block_containing_function): New function.
+ * skip.c (skip_function_command): Update.
+ (skip_re_set): Update.
+
+2011-10-28 Tom Tromey <tromey@redhat.com>
+
* elfread.c (elf_gnu_ifunc_resolver_return_stop): Allow
breakpoint's pspace to be NULL.
* breakpoint.h (struct breakpoint) <pspace>: Update comment.
diff --git a/gdb/block.c b/gdb/block.c
index c165bc2..1fa3688 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -82,6 +82,20 @@ block_linkage_function (const struct block *bl)
return BLOCK_FUNCTION (bl);
}
+/* Return the symbol for the function which contains a specified
+ block, described by a struct block BL. The return value will be
+ the closest enclosing function, which might be an inline
+ function. */
+
+struct symbol *
+block_containing_function (const struct block *bl)
+{
+ while (BLOCK_FUNCTION (bl) == NULL && BLOCK_SUPERBLOCK (bl) != NULL)
+ bl = BLOCK_SUPERBLOCK (bl);
+
+ return BLOCK_FUNCTION (bl);
+}
+
/* Return one if BL represents an inlined function. */
int
diff --git a/gdb/block.h b/gdb/block.h
index 1742f24..63b18a6 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -131,6 +131,8 @@ struct blockvector
extern struct symbol *block_linkage_function (const struct block *);
+extern struct symbol *block_containing_function (const struct block *);
+
extern int block_inlined_p (const struct block *block);
extern int contained_in (const struct block *, const struct block *);
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 6eced70..8ed3f4c 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4563,7 +4563,7 @@ print_breakpoint_location (struct breakpoint *b,
if (b->display_canonical)
ui_out_field_string (uiout, "what", b->addr_string);
- else if (b->source_file && loc)
+ else if (loc && loc->source_file)
{
struct symbol *sym
= find_pc_sect_function (loc->address, loc->section);
@@ -4576,7 +4576,7 @@ print_breakpoint_location (struct breakpoint *b,
ui_out_wrap_hint (uiout, wrap_indent_at_field (uiout, "what"));
ui_out_text (uiout, "at ");
}
- ui_out_field_string (uiout, "file", b->source_file);
+ ui_out_field_string (uiout, "file", loc->source_file);
ui_out_text (uiout, ":");
if (ui_out_is_mi_like_p (uiout))
@@ -4588,7 +4588,7 @@ print_breakpoint_location (struct breakpoint *b,
ui_out_field_string (uiout, "fullname", fullname);
}
- ui_out_field_int (uiout, "line", b->line_number);
+ ui_out_field_int (uiout, "line", loc->line_number);
}
else if (loc)
{
@@ -5825,12 +5825,6 @@ init_raw_breakpoint (struct breakpoint *b, struct gdbarch *gdbarch,
if (bptype != bp_breakpoint && bptype != bp_hardware_breakpoint)
b->pspace = sal.pspace;
- if (sal.symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file = xstrdup (sal.symtab->filename);
- b->line_number = sal.line;
-
breakpoints_changed ();
}
@@ -7076,12 +7070,10 @@ momentary_breakpoint_from_master (struct breakpoint *orig,
copy->loc->section = orig->loc->section;
copy->loc->pspace = orig->loc->pspace;
- if (orig->source_file == NULL)
- copy->source_file = NULL;
- else
- copy->source_file = xstrdup (orig->source_file);
+ if (orig->loc->source_file != NULL)
+ copy->loc->source_file = xstrdup (orig->loc->source_file);
- copy->line_number = orig->line_number;
+ copy->loc->line_number = orig->loc->line_number;
copy->frame_id = orig->frame_id;
copy->thread = orig->thread;
copy->pspace = orig->pspace;
@@ -7165,6 +7157,11 @@ add_location_to_breakpoint (struct breakpoint *b,
gdb_assert (loc->pspace != NULL);
loc->section = sal->section;
loc->gdbarch = loc_gdbarch;
+
+ if (sal->symtab != NULL)
+ loc->source_file = xstrdup (sal->symtab->filename);
+ loc->line_number = sal->line;
+
set_breakpoint_location_function (loc,
sal->explicit_pc || sal->explicit_line);
return loc;
@@ -7221,7 +7218,7 @@ bp_loc_is_permanent (struct bp_location *loc)
static void
init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
struct symtabs_and_lines sals, char *addr_string,
- char *cond_string,
+ char *filter, char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int task, int ignore_count,
const struct breakpoint_ops *ops, int from_tty,
@@ -7335,12 +7332,13 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
me. */
b->addr_string
= xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+ b->filter = filter;
}
static void
create_breakpoint_sal (struct gdbarch *gdbarch,
struct symtabs_and_lines sals, char *addr_string,
- char *cond_string,
+ char *filter, char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int task, int ignore_count,
const struct breakpoint_ops *ops, int from_tty,
@@ -7363,7 +7361,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
init_breakpoint_sal (b, gdbarch,
sals, addr_string,
- cond_string,
+ filter, cond_string,
type, disposition,
thread, task, ignore_count,
ops, from_tty,
@@ -7373,138 +7371,6 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
install_breakpoint (internal, b, 0);
}
-/* Remove element at INDEX_TO_REMOVE from SAL, shifting other
- elements to fill the void space. */
-static void
-remove_sal (struct symtabs_and_lines *sal, int index_to_remove)
-{
- int i = index_to_remove+1;
- int last_index = sal->nelts-1;
-
- for (;i <= last_index; ++i)
- sal->sals[i-1] = sal->sals[i];
-
- --(sal->nelts);
-}
-
-/* If appropriate, obtains all sals that correspond to the same file
- and line as SAL, in all program spaces. Users debugging with IDEs,
- will want to set a breakpoint at foo.c:line, and not really care
- about program spaces. This is done only if SAL does not have
- explicit PC and has line and file information. If we got just a
- single expanded sal, return the original.
-
- Otherwise, if SAL.explicit_line is not set, filter out all sals for
- which the name of enclosing function is different from SAL. This
- makes sure that if we have breakpoint originally set in template
- instantiation, say foo<int>(), we won't expand SAL to locations at
- the same line in all existing instantiations of 'foo'. */
-
-static struct symtabs_and_lines
-expand_line_sal_maybe (struct symtab_and_line sal)
-{
- struct symtabs_and_lines expanded;
- CORE_ADDR original_pc = sal.pc;
- char *original_function = NULL;
- int found;
- int i;
- struct cleanup *old_chain;
-
- /* If we have explicit pc, don't expand.
- If we have no line number, we can't expand. */
- if (sal.explicit_pc || sal.line == 0 || sal.symtab == NULL)
- {
- expanded.nelts = 1;
- expanded.sals = xmalloc (sizeof (struct symtab_and_line));
- expanded.sals[0] = sal;
- return expanded;
- }
-
- sal.pc = 0;
-
- old_chain = save_current_space_and_thread ();
-
- switch_to_program_space_and_thread (sal.pspace);
-
- find_pc_partial_function (original_pc, &original_function, NULL, NULL);
-
- /* Note that expand_line_sal visits *all* program spaces. */
- expanded = expand_line_sal (sal);
-
- if (expanded.nelts == 1)
- {
- /* We had one sal, we got one sal. Return that sal, adjusting it
- past the function prologue if necessary. */
- xfree (expanded.sals);
- expanded.nelts = 1;
- expanded.sals = xmalloc (sizeof (struct symtab_and_line));
- sal.pc = original_pc;
- expanded.sals[0] = sal;
- skip_prologue_sal (&expanded.sals[0]);
- do_cleanups (old_chain);
- return expanded;
- }
-
- if (!sal.explicit_line)
- {
- CORE_ADDR func_addr, func_end;
- for (i = 0; i < expanded.nelts; ++i)
- {
- CORE_ADDR pc = expanded.sals[i].pc;
- char *this_function;
-
- /* We need to switch threads as well since we're about to
- read memory. */
- switch_to_program_space_and_thread (expanded.sals[i].pspace);
-
- if (find_pc_partial_function (pc, &this_function,
- &func_addr, &func_end))
- {
- if (this_function
- && strcmp (this_function, original_function) != 0)
- {
- remove_sal (&expanded, i);
- --i;
- }
- }
- }
- }
-
- /* Skip the function prologue if necessary. */
- for (i = 0; i < expanded.nelts; ++i)
- skip_prologue_sal (&expanded.sals[i]);
-
- do_cleanups (old_chain);
-
- if (expanded.nelts <= 1)
- {
- /* This is an ugly workaround. If we get zero expanded sals
- then something is really wrong. Fix that by returning the
- original sal. */
-
- xfree (expanded.sals);
- expanded.nelts = 1;
- expanded.sals = xmalloc (sizeof (struct symtab_and_line));
- sal.pc = original_pc;
- expanded.sals[0] = sal;
- return expanded;
- }
-
- if (original_pc)
- {
- found = 0;
- for (i = 0; i < expanded.nelts; ++i)
- if (expanded.sals[i].pc == original_pc)
- {
- found = 1;
- break;
- }
- gdb_assert (found);
- }
-
- return expanded;
-}
-
/* Add SALS.nelts breakpoints to the breakpoint table. For each
SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
value. COND_STRING, if not NULL, specified the condition to be
@@ -7522,7 +7388,6 @@ expand_line_sal_maybe (struct symtab_and_line sal)
static void
create_breakpoints_sal (struct gdbarch *gdbarch,
- struct symtabs_and_lines sals,
struct linespec_result *canonical,
char *cond_string,
enum bptype type, enum bpdisp disposition,
@@ -7531,17 +7396,30 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
int enabled, int internal)
{
int i;
+ struct linespec_sals *lsal;
- for (i = 0; i < sals.nelts; ++i)
+ if (canonical->pre_expanded)
+ gdb_assert (VEC_length (linespec_sals, canonical->sals) == 1);
+
+ for (i = 0; VEC_iterate (linespec_sals, canonical->sals, i, lsal); ++i)
{
- struct symtabs_and_lines expanded =
- expand_line_sal_maybe (sals.sals[i]);
+ /* Note that 'addr_string' can be NULL in the case of a plain
+ 'break', without arguments. */
+ char *addr_string = (canonical->addr_string
+ ? xstrdup (canonical->addr_string)
+ : NULL);
+ char *filter_string = lsal->canonical ? xstrdup (lsal->canonical) : NULL;
+ struct cleanup *inner = make_cleanup (xfree, addr_string);
- create_breakpoint_sal (gdbarch, expanded, canonical->canonical[i],
+ make_cleanup (xfree, filter_string);
+ create_breakpoint_sal (gdbarch, lsal->sals,
+ addr_string,
+ filter_string,
cond_string, type, disposition,
thread, task, ignore_count, ops,
from_tty, enabled, internal,
canonical->special_display);
+ discard_cleanups (inner);
}
}
@@ -7555,7 +7433,6 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
static void
parse_breakpoint_sals (char **address,
- struct symtabs_and_lines *sals,
struct linespec_result *canonical)
{
char *addr_start = *address;
@@ -7569,10 +7446,11 @@ parse_breakpoint_sals (char **address,
address. */
if (last_displayed_sal_is_valid ())
{
+ struct linespec_sals lsal;
struct symtab_and_line sal;
init_sal (&sal); /* Initialize to zeroes. */
- sals->sals = (struct symtab_and_line *)
+ lsal.sals.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
/* Set sal's pspace, pc, symtab, and line to the values
@@ -7587,8 +7465,11 @@ parse_breakpoint_sals (char **address,
instances with the same symtab and line. */
sal.explicit_pc = 1;
- sals->sals[0] = sal;
- sals->nelts = 1;
+ lsal.sals.sals[0] = sal;
+ lsal.sals.nelts = 1;
+ lsal.canonical = NULL;
+
+ VEC_safe_push (linespec_sals, canonical->sals, &lsal);
}
else
error (_("No default breakpoint address now."));
@@ -7598,40 +7479,16 @@ parse_breakpoint_sals (char **address,
/* Force almost all breakpoints to be in terms of the
current_source_symtab (which is decode_line_1's default).
This should produce the results we want almost all of the
- time while leaving the last displayed codepoint pointers
- alone.
-
- ObjC: However, don't match an Objective-C method name which
- may have a '+' or '-' succeeded by a '[' */
-
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
-
- if (last_displayed_sal_is_valid ()
- && (!cursal.symtab
- || ((strchr ("+-", (*address)[0]) != NULL)
- && ((*address)[1] != '['))))
- *sals = decode_line_1 (address, 1,
- get_last_displayed_symtab (),
- get_last_displayed_line (),
- canonical);
+ time while leaving default_breakpoint_* alone. */
+ if (last_displayed_sal_is_valid ())
+ decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
+ get_last_displayed_symtab (),
+ get_last_displayed_line (),
+ canonical, NULL, NULL);
else
- *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0,
- canonical);
- }
- /* For any SAL that didn't have a canonical string, fill one in. */
- if (sals->nelts > 0 && canonical->canonical == NULL)
- canonical->canonical = xcalloc (sals->nelts, sizeof (char *));
- if (addr_start != (*address))
- {
- int i;
-
- for (i = 0; i < sals->nelts; i++)
- {
- /* Add the string if not present. */
- if (canonical->canonical[i] == NULL)
- canonical->canonical[i] = savestring (addr_start,
- (*address) - addr_start);
- }
+ decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
+ (struct symtab *) NULL, 0,
+ canonical, NULL, NULL);
}
}
@@ -7666,15 +7523,22 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch,
for (i = 0; i < sals->nelts; i++)
{
+ struct gdbarch *sarch;
+
sal = &sals->sals[i];
- rslt = gdbarch_fast_tracepoint_valid_at (gdbarch, sal->pc,
+ sarch = get_sal_arch (*sal);
+ /* We fall back to GDBARCH if there is no architecture
+ associated with SAL. */
+ if (sarch == NULL)
+ sarch = gdbarch;
+ rslt = gdbarch_fast_tracepoint_valid_at (sarch, sal->pc,
NULL, &msg);
old_chain = make_cleanup (xfree, msg);
if (!rslt)
error (_("May not have a fast tracepoint at 0x%s%s"),
- paddress (gdbarch, sal->pc), (msg ? msg : ""));
+ paddress (sarch, sal->pc), (msg ? msg : ""));
do_cleanups (old_chain);
}
@@ -7816,9 +7680,7 @@ create_breakpoint (struct gdbarch *gdbarch,
int from_tty, int enabled, int internal)
{
volatile struct gdb_exception e;
- struct symtabs_and_lines sals;
- struct symtab_and_line pending_sal;
- char *copy_arg;
+ char *copy_arg = NULL;
char *addr_start = arg;
struct linespec_result canonical;
struct cleanup *old_chain;
@@ -7830,26 +7692,26 @@ create_breakpoint (struct gdbarch *gdbarch,
gdb_assert (ops != NULL);
- sals.sals = NULL;
- sals.nelts = 0;
init_linespec_result (&canonical);
if (type_wanted == bp_static_tracepoint && is_marker_spec (arg))
{
int i;
+ struct linespec_sals lsal;
- sals = decode_static_tracepoint_spec (&arg);
+ lsal.sals = decode_static_tracepoint_spec (&arg);
copy_arg = savestring (addr_start, arg - addr_start);
- canonical.canonical = xcalloc (sals.nelts, sizeof (char *));
- for (i = 0; i < sals.nelts; i++)
- canonical.canonical[i] = xstrdup (copy_arg);
+
+ lsal.canonical = xstrdup (copy_arg);
+ VEC_safe_push (linespec_sals, canonical.sals, &lsal);
+
goto done;
}
TRY_CATCH (e, RETURN_MASK_ALL)
{
- parse_breakpoint_sals (&arg, &sals, &canonical);
+ parse_breakpoint_sals (&arg, &canonical);
}
/* If caller is interested in rc value from parse, set value. */
@@ -7881,35 +7743,31 @@ create_breakpoint (struct gdbarch *gdbarch,
a pending breakpoint and selected yes, or pending
breakpoint behavior is on and thus a pending breakpoint
is defaulted on behalf of the user. */
- copy_arg = xstrdup (addr_start);
- canonical.canonical = ©_arg;
- sals.nelts = 1;
- sals.sals = &pending_sal;
- pending_sal.pc = 0;
- pending = 1;
+ {
+ struct linespec_sals lsal;
+
+ copy_arg = xstrdup (addr_start);
+ lsal.canonical = xstrdup (copy_arg);
+ lsal.sals.nelts = 1;
+ lsal.sals.sals = XNEW (struct symtab_and_line);
+ init_sal (&lsal.sals.sals[0]);
+ pending = 1;
+ VEC_safe_push (linespec_sals, canonical.sals, &lsal);
+ }
break;
default:
throw_exception (e);
}
break;
default:
- if (!sals.nelts)
+ if (VEC_empty (linespec_sals, canonical.sals))
return 0;
}
done:
/* Create a chain of things that always need to be cleaned up. */
- old_chain = make_cleanup (null_cleanup, 0);
-
- if (!pending)
- {
- /* Make sure that all storage allocated to SALS gets freed. */
- make_cleanup (xfree, sals.sals);
-
- /* Cleanup the canonical array but not its contents. */
- make_cleanup (xfree, canonical.canonical);
- }
+ old_chain = make_cleanup_destroy_linespec_result (&canonical);
/* ----------------------------- SNIP -----------------------------
Anything added to the cleanup chain beyond this point is assumed
@@ -7917,28 +7775,36 @@ create_breakpoint (struct gdbarch *gdbarch,
then the memory is not reclaimed. */
bkpt_chain = make_cleanup (null_cleanup, 0);
- /* Mark the contents of the canonical for cleanup. These go on
- the bkpt_chain and only occur if the breakpoint create fails. */
- for (i = 0; i < sals.nelts; i++)
- {
- if (canonical.canonical[i] != NULL)
- make_cleanup (xfree, canonical.canonical[i]);
- }
-
/* Resolve all line numbers to PC's and verify that the addresses
are ok for the target. */
if (!pending)
- breakpoint_sals_to_pc (&sals);
+ {
+ int ix;
+ struct linespec_sals *iter;
+
+ for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix)
+ breakpoint_sals_to_pc (&iter->sals);
+ }
/* Fast tracepoints may have additional restrictions on location. */
if (!pending && type_wanted == bp_fast_tracepoint)
- check_fast_tracepoint_sals (gdbarch, &sals);
+ {
+ int ix;
+ struct linespec_sals *iter;
+
+ for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix)
+ check_fast_tracepoint_sals (gdbarch, &iter->sals);
+ }
/* Verify that condition can be parsed, before setting any
breakpoints. Allocate a separate condition expression for each
breakpoint. */
if (!pending)
{
+ struct linespec_sals *lsal;
+
+ lsal = VEC_index (linespec_sals, canonical.sals, 0);
+
if (parse_condition_and_thread)
{
/* Here we only parse 'arg' to separate condition
@@ -7947,7 +7813,7 @@ create_breakpoint (struct gdbarch *gdbarch,
re-parse it in context of each sal. */
cond_string = NULL;
thread = -1;
- find_condition_and_thread (arg, sals.sals[0].pc, &cond_string,
+ find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
&thread, &task);
if (cond_string)
make_cleanup (xfree, cond_string);
@@ -7969,24 +7835,26 @@ create_breakpoint (struct gdbarch *gdbarch,
expand multiple locations for each sal, given than SALS
already should contain all sals for MARKER_ID. */
if (type_wanted == bp_static_tracepoint
- && is_marker_spec (canonical.canonical[0]))
+ && is_marker_spec (lsal->canonical))
{
int i;
- for (i = 0; i < sals.nelts; ++i)
+ for (i = 0; i < lsal->sals.nelts; ++i)
{
struct symtabs_and_lines expanded;
struct tracepoint *tp;
struct cleanup *old_chain;
+ char *addr_string;
expanded.nelts = 1;
- expanded.sals = xmalloc (sizeof (struct symtab_and_line));
- expanded.sals[0] = sals.sals[i];
- old_chain = make_cleanup (xfree, expanded.sals);
+ expanded.sals = &lsal->sals.sals[i];
+
+ addr_string = xstrdup (canonical.addr_string);
+ old_chain = make_cleanup (xfree, addr_string);
tp = XCNEW (struct tracepoint);
init_breakpoint_sal (&tp->base, gdbarch, expanded,
- canonical.canonical[i],
+ addr_string, NULL,
cond_string, type_wanted,
tempflag ? disp_del : disp_donttouch,
thread, task, ignore_count, ops,
@@ -8002,11 +7870,11 @@ create_breakpoint (struct gdbarch *gdbarch,
install_breakpoint (internal, &tp->base, 0);
- do_cleanups (old_chain);
+ discard_cleanups (old_chain);
}
}
else
- create_breakpoints_sal (gdbarch, sals, &canonical, cond_string,
+ create_breakpoints_sal (gdbarch, &canonical, cond_string,
type_wanted,
tempflag ? disp_del : disp_donttouch,
thread, task, ignore_count, ops, from_tty,
@@ -8030,7 +7898,7 @@ create_breakpoint (struct gdbarch *gdbarch,
init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
- b->addr_string = canonical.canonical[0];
+ b->addr_string = copy_arg;
b->cond_string = NULL;
b->ignore_count = ignore_count;
b->disposition = tempflag ? disp_del : disp_donttouch;
@@ -8042,7 +7910,7 @@ create_breakpoint (struct gdbarch *gdbarch,
install_breakpoint (internal, b, 0);
}
- if (sals.nelts > 1)
+ if (VEC_length (linespec_sals, canonical.sals) > 1)
{
warning (_("Multiple breakpoints were set.\nUse the "
"\"delete\" command to delete unwanted breakpoints."));
@@ -8423,8 +8291,8 @@ break_range_command (char *arg, int from_tty)
CORE_ADDR end;
struct breakpoint *b;
struct symtab_and_line sal_start, sal_end;
- struct symtabs_and_lines sals_start, sals_end;
struct cleanup *cleanup_bkpt;
+ struct linespec_sals *lsal_start, *lsal_end;
/* We don't support software ranged breakpoints. */
if (target_ranged_break_num_registers () < 0)
@@ -8437,71 +8305,59 @@ break_range_command (char *arg, int from_tty)
if (can_use_bp < 0)
error (_("Hardware breakpoints used exceeds limit."));
+ arg = skip_spaces (arg);
if (arg == NULL || arg[0] == '\0')
error(_("No address range specified."));
- sals_start.sals = NULL;
- sals_start.nelts = 0;
init_linespec_result (&canonical_start);
- while (*arg == ' ' || *arg == '\t')
- arg++;
-
- parse_breakpoint_sals (&arg, &sals_start, &canonical_start);
+ parse_breakpoint_sals (&arg, &canonical_start);
- sal_start = sals_start.sals[0];
- addr_string_start = canonical_start.canonical[0];
- cleanup_bkpt = make_cleanup (xfree, addr_string_start);
- xfree (sals_start.sals);
- xfree (canonical_start.canonical);
+ cleanup_bkpt = make_cleanup_destroy_linespec_result (&canonical_start);
if (arg[0] != ',')
error (_("Too few arguments."));
- else if (sals_start.nelts == 0)
+ else if (VEC_empty (linespec_sals, canonical_start.sals))
error (_("Could not find location of the beginning of the range."));
- else if (sals_start.nelts != 1)
+
+ lsal_start = VEC_index (linespec_sals, canonical_start.sals, 0);
+
+ if (VEC_length (linespec_sals, canonical_start.sals) > 1
+ || lsal_start->sals.nelts != 1)
error (_("Cannot create a ranged breakpoint with multiple locations."));
- resolve_sal_pc (&sal_start);
+ sal_start = lsal_start->sals.sals[0];
+ addr_string_start = lsal_start->canonical;
arg++; /* Skip the comma. */
- while (*arg == ' ' || *arg == '\t')
- arg++;
+ arg = skip_spaces (arg);
/* Parse the end location. */
- sals_end.sals = NULL;
- sals_end.nelts = 0;
init_linespec_result (&canonical_end);
arg_start = arg;
- /* We call decode_line_1 directly here instead of using
+ /* We call decode_line_full directly here instead of using
parse_breakpoint_sals because we need to specify the start location's
symtab and line as the default symtab and line for the end of the
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 can be NULL if it was of the form "*0xdeadbeef". */
- if (canonical_end.canonical == NULL)
- canonical_end.canonical = xcalloc (1, sizeof (char *));
- /* Add the string if not present. */
- if (arg_start != arg && canonical_end.canonical[0] == NULL)
- canonical_end.canonical[0] = savestring (arg_start, arg - arg_start);
-
- sal_end = sals_end.sals[0];
- addr_string_end = canonical_end.canonical[0];
- make_cleanup (xfree, addr_string_end);
- xfree (sals_end.sals);
- xfree (canonical_end.canonical);
-
- if (sals_end.nelts == 0)
+ decode_line_full (&arg, DECODE_LINE_FUNFIRSTLINE,
+ sal_start.symtab, sal_start.line,
+ &canonical_end, NULL, NULL);
+
+ make_cleanup_destroy_linespec_result (&canonical_end);
+
+ if (VEC_empty (linespec_sals, canonical_end.sals))
error (_("Could not find location of the end of the range."));
- else if (sals_end.nelts != 1)
+
+ lsal_end = VEC_index (linespec_sals, canonical_end.sals, 0);
+ if (VEC_length (linespec_sals, canonical_end.sals) > 1
+ || lsal_end->sals.nelts != 1)
error (_("Cannot create a ranged breakpoint with multiple locations."));
- resolve_sal_pc (&sal_end);
+ sal_end = lsal_end->sals.sals[0];
+ addr_string_end = lsal_end->canonical;
end = find_breakpoint_range_end (sal_end);
if (sal_start.pc > end)
@@ -8528,11 +8384,11 @@ break_range_command (char *arg, int from_tty)
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
b->disposition = disp_donttouch;
- b->addr_string = addr_string_start;
- b->addr_string_range_end = addr_string_end;
+ b->addr_string = xstrdup (addr_string_start);
+ b->addr_string_range_end = xstrdup (addr_string_end);
b->loc->length = length;
- discard_cleanups (cleanup_bkpt);
+ do_cleanups (cleanup_bkpt);
mention (b);
observer_notify_breakpoint_created (b);
@@ -9639,12 +9495,12 @@ until_break_command (char *arg, int from_tty, int anywhere)
this function. */
if (last_displayed_sal_is_valid ())
- sals = decode_line_1 (&arg, 1,
+ sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
get_last_displayed_symtab (),
- get_last_displayed_line (),
- NULL);
+ get_last_displayed_line ());
else
- sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL);
+ sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
+ (struct symtab *) NULL, 0);
if (sals.nelts != 1)
error (_("Couldn't get information on specified line."));
@@ -10155,7 +10011,8 @@ clear_command (char *arg, int from_tty)
if (arg)
{
- sals = decode_line_spec (arg, 1);
+ sals = decode_line_spec (arg, (DECODE_LINE_FUNFIRSTLINE
+ | DECODE_LINE_LIST_MODE));
default_match = 0;
}
else
@@ -10227,18 +10084,21 @@ clear_command (char *arg, int from_tty)
struct bp_location *loc = b->loc;
for (; loc; loc = loc->next)
{
- int pc_match = sal.pc
- && (loc->pspace == sal.pspace)
- && (loc->address == sal.pc)
- && (!section_is_overlay (loc->section)
- || loc->section == sal.section);
- int line_match = ((default_match || (0 == sal.pc))
- && b->source_file != NULL
+ /* If the user specified file:line, don't allow a PC
+ match. This matches historical gdb behavior. */
+ int pc_match = (!sal.explicit_line
+ && sal.pc
+ && (loc->pspace == sal.pspace)
+ && (loc->address == sal.pc)
+ && (!section_is_overlay (loc->section)
+ || loc->section == sal.section));
+ int line_match = ((default_match || sal.explicit_line)
+ && loc->source_file != NULL
&& sal.symtab != NULL
&& sal.pspace == loc->pspace
- && filename_cmp (b->source_file,
+ && filename_cmp (loc->source_file,
sal.symtab->filename) == 0
- && b->line_number == sal.line);
+ && loc->line_number == sal.line);
if (pc_match || line_match)
{
match = 1;
@@ -10830,15 +10690,25 @@ say_where (struct breakpoint *b)
}
else
{
- if (opts.addressprint || b->source_file == NULL)
+ if (opts.addressprint || b->loc->source_file == NULL)
{
printf_filtered (" at ");
fputs_filtered (paddress (b->loc->gdbarch, b->loc->address),
gdb_stdout);
}
- if (b->source_file)
- printf_filtered (": file %s, line %d.",
- b->source_file, b->line_number);
+ if (b->loc->source_file)
+ {
+ /* If there is a single location, we can print the location
+ more nicely. */
+ if (b->loc->next == NULL)
+ printf_filtered (": file %s, line %d.",
+ b->loc->source_file, b->loc->line_number);
+ else
+ /* This is not ideal, but each location may have a
+ different file name, and this at least reflects the
+ real situation somewhat. */
+ printf_filtered (": %s.", b->addr_string);
+ }
if (b->loc->next)
{
@@ -10858,6 +10728,7 @@ bp_location_dtor (struct bp_location *self)
{
xfree (self->cond);
xfree (self->function_name);
+ xfree (self->source_file);
}
static const struct bp_location_ops bp_location_ops =
@@ -10874,8 +10745,8 @@ base_breakpoint_dtor (struct breakpoint *self)
decref_counted_command_line (&self->commands);
xfree (self->cond_string);
xfree (self->addr_string);
+ xfree (self->filter);
xfree (self->addr_string_range_end);
- xfree (self->source_file);
}
static struct bp_location *
@@ -11710,17 +11581,18 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
ui_out_field_int (uiout, "line", sal.line);
ui_out_text (uiout, "\n");
- b->line_number = sal.line;
+ b->loc->line_number = sal.line;
- xfree (b->source_file);
+ xfree (b->loc->source_file);
if (sym)
- b->source_file = xstrdup (sal.symtab->filename);
+ b->loc->source_file = xstrdup (sal.symtab->filename);
else
- b->source_file = NULL;
+ b->loc->source_file = NULL;
xfree (b->addr_string);
b->addr_string = xstrprintf ("%s:%d",
- sal.symtab->filename, b->line_number);
+ sal.symtab->filename,
+ b->loc->line_number);
/* Might be nice to check if function changed, and warn if
so. */
@@ -11770,8 +11642,17 @@ update_breakpoint_locations (struct breakpoint *b,
int i;
struct bp_location *existing_locations = b->loc;
- /* Ranged breakpoints have only one start location and one end location. */
- gdb_assert (sals_end.nelts == 0 || (sals.nelts == 1 && sals_end.nelts == 1));
+ if (sals_end.nelts != 0 && (sals.nelts != 1 || sals_end.nelts != 1))
+ {
+ /* Ranged breakpoints have only one start location and one end
+ location. */
+ b->enable_state = bp_disabled;
+ update_global_location_list (1);
+ printf_unfiltered (_("Could not reset ranged breakpoint %d: "
+ "multiple locations found\n"),
+ b->number);
+ return;
+ }
/* If there's no new locations, and all existing locations are
pending, don't do anything. This optimizes the common case where
@@ -11786,8 +11667,11 @@ update_breakpoint_locations (struct breakpoint *b,
for (i = 0; i < sals.nelts; ++i)
{
- struct bp_location *new_loc =
- add_location_to_breakpoint (b, &(sals.sals[i]));
+ struct bp_location *new_loc;
+
+ switch_to_program_space_and_thread (sals.sals[i].pspace);
+
+ new_loc = add_location_to_breakpoint (b, &(sals.sals[i]));
/* Reparse conditions, they might contain references to the
old symtab. */
@@ -11811,16 +11695,6 @@ update_breakpoint_locations (struct breakpoint *b,
}
}
- if (b->source_file != NULL)
- xfree (b->source_file);
- if (sals.sals[i].symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file = xstrdup (sals.sals[i].symtab->filename);
-
- if (b->line_number == 0)
- b->line_number = sals.sals[i].line;
-
if (sals_end.nelts)
{
CORE_ADDR end = find_breakpoint_range_end (sals_end.sals[0]);
@@ -11887,7 +11761,7 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
char *s;
int marker_spec;
struct symtabs_and_lines sals = {0};
- struct gdb_exception e;
+ volatile struct gdb_exception e;
s = addr_string;
marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s);
@@ -11908,7 +11782,31 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
error (_("marker %s not found"), tp->static_trace_marker_id);
}
else
- sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, NULL);
+ {
+ struct linespec_result canonical;
+
+ init_linespec_result (&canonical);
+ decode_line_full (&s, DECODE_LINE_FUNFIRSTLINE,
+ (struct symtab *) NULL, 0,
+ &canonical, multiple_symbols_all,
+ b->filter);
+
+ /* We should get 0 or 1 resulting SALs. */
+ gdb_assert (VEC_length (linespec_sals, canonical.sals) < 2);
+
+ if (VEC_length (linespec_sals, canonical.sals) > 0)
+ {
+ struct linespec_sals *lsal;
+
+ lsal = VEC_index (linespec_sals, canonical.sals, 0);
+ sals = lsal->sals;
+ /* Arrange it so the destructor does not free the
+ contents. */
+ lsal->sals.sals = NULL;
+ }
+
+ destroy_linespec_result (&canonical);
+ }
}
if (e.reason < 0)
{
@@ -11942,9 +11840,10 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
if (e.reason == 0 || e.error != NOT_FOUND_ERROR)
{
- gdb_assert (sals.nelts == 1);
+ int i;
- resolve_sal_pc (&sals.sals[0]);
+ for (i = 0; i < sals.nelts; ++i)
+ resolve_sal_pc (&sals.sals[i]);
if (b->condition_not_parsed && s && s[0])
{
char *cond_string = 0;
@@ -11987,7 +11886,7 @@ breakpoint_re_set_default (struct breakpoint *b)
if (found)
{
make_cleanup (xfree, sals.sals);
- expanded = expand_line_sal_maybe (sals.sals[0]);
+ expanded = sals;
}
if (b->addr_string_range_end)
@@ -11996,7 +11895,7 @@ breakpoint_re_set_default (struct breakpoint *b)
if (found)
{
make_cleanup (xfree, sals_end.sals);
- expanded_end = expand_line_sal_maybe (sals_end.sals[0]);
+ expanded_end = sals_end;
}
}
@@ -12525,20 +12424,18 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len,
if they aren't valid. */
struct symtabs_and_lines
-decode_line_spec_1 (char *string, int funfirstline)
+decode_line_spec_1 (char *string, int flags)
{
struct symtabs_and_lines sals;
if (string == 0)
error (_("Empty line specification."));
if (last_displayed_sal_is_valid ())
- sals = decode_line_1 (&string, funfirstline,
+ sals = decode_line_1 (&string, flags,
get_last_displayed_symtab (),
- get_last_displayed_line (),
- NULL);
+ get_last_displayed_line ());
else
- sals = decode_line_1 (&string, funfirstline,
- (struct symtab *) NULL, 0, NULL);
+ sals = decode_line_1 (&string, flags, (struct symtab *) NULL, 0);
if (*string)
error (_("Junk at end of line specification: %s"), string);
return sals;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index de1491e..ead3930 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -397,6 +397,14 @@ struct bp_location
This variable keeps a number of events still to go, when
it becomes 0 this location is retired. */
int events_till_retirement;
+
+ /* Line number of this address. */
+
+ int line_number;
+
+ /* Source file name of this address. */
+
+ char *source_file;
};
/* This structure is a collection of function pointers that, if available,
@@ -544,14 +552,6 @@ struct breakpoint
/* Location(s) associated with this high-level breakpoint. */
struct bp_location *loc;
- /* Line number of this address. */
-
- int line_number;
-
- /* Source file name of this address. */
-
- char *source_file;
-
/* Non-zero means a silent breakpoint (don't print frame info
if we stop here). */
unsigned char silent;
@@ -575,6 +575,11 @@ struct breakpoint
/* String we used to set the breakpoint (malloc'd). */
char *addr_string;
+ /* The filter that should be passed to decode_line_full when
+ re-setting this breakpoint. This may be NULL, but otherwise is
+ allocated with xmalloc. */
+ char *filter;
+
/* For a ranged breakpoint, the string we used to find
the end of the range (malloc'd). */
char *addr_string_range_end;
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index d75a6c0..8832e0c 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -92,6 +92,9 @@ void apropos_command (char *, int);
/* Prototypes for local utility functions */
static void ambiguous_line_spec (struct symtabs_and_lines *);
+
+static void filter_sals (struct symtabs_and_lines *);
+
\f
/* Limit the call depth of user-defined commands */
int max_user_call_depth;
@@ -246,16 +249,6 @@ help_command (char *command, int from_tty)
help_cmd (command, gdb_stdout);
}
\f
-/* String compare function for qsort. */
-static int
-compare_strings (const void *arg1, const void *arg2)
-{
- const char **s1 = (const char **) arg1;
- const char **s2 = (const char **) arg2;
-
- return strcmp (*s1, *s2);
-}
-
/* The "complete" command is used by Emacs to implement completion. */
static void
@@ -796,8 +789,9 @@ 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, DECODE_LINE_LIST_MODE, 0, 0);
+ filter_sals (&sals);
if (! sals.nelts)
{
/* C++ */
@@ -926,8 +920,9 @@ 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, DECODE_LINE_LIST_MODE, 0, 0);
+ filter_sals (&sals);
if (!sals.nelts)
return; /* C++ */
if (sals.nelts > 1)
@@ -959,9 +954,11 @@ 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, DECODE_LINE_LIST_MODE, 0, 0);
else
- sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0);
+ sals_end = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE,
+ sal.symtab, sal.line);
+ filter_sals (&sals);
if (sals_end.nelts == 0)
return;
if (sals_end.nelts > 1)
@@ -1472,6 +1469,85 @@ ambiguous_line_spec (struct symtabs_and_lines *sals)
sals->sals[i].symtab->filename, sals->sals[i].line);
}
+/* Sort function for filter_sals. */
+
+static int
+compare_symtabs (const void *a, const void *b)
+{
+ const struct symtab_and_line *sala = a;
+ const struct symtab_and_line *salb = b;
+ int r;
+
+ if (!sala->symtab->dirname)
+ {
+ if (salb->symtab->dirname)
+ return -1;
+ }
+ else if (!salb->symtab->dirname)
+ {
+ if (sala->symtab->dirname)
+ return 1;
+ }
+ else
+ {
+ r = filename_cmp (sala->symtab->dirname, salb->symtab->dirname);
+ if (r)
+ return r;
+ }
+
+ r = filename_cmp (sala->symtab->filename, salb->symtab->filename);
+ if (r)
+ return r;
+
+ if (sala->line < salb->line)
+ return -1;
+ return sala->line == salb->line ? 0 : 1;
+}
+
+/* Remove any SALs that do not match the current program space, or
+ which appear to be "file:line" duplicates. */
+
+static void
+filter_sals (struct symtabs_and_lines *sals)
+{
+ int i, out, prev;
+
+ out = 0;
+ for (i = 0; i < sals->nelts; ++i)
+ {
+ if (sals->sals[i].pspace == current_program_space
+ || sals->sals[i].symtab == NULL)
+ {
+ sals->sals[out] = sals->sals[i];
+ ++out;
+ }
+ }
+ sals->nelts = out;
+
+ qsort (sals->sals, sals->nelts, sizeof (struct symtab_and_line),
+ compare_symtabs);
+
+ out = 1;
+ prev = 0;
+ for (i = 1; i < sals->nelts; ++i)
+ {
+ if (compare_symtabs (&sals->sals[prev], &sals->sals[i]))
+ {
+ /* Symtabs differ. */
+ sals->sals[out] = sals->sals[i];
+ prev = out;
+ ++out;
+ }
+ }
+ sals->nelts = out;
+
+ if (sals->nelts == 0)
+ {
+ xfree (sals->sals);
+ sals->sals = NULL;
+ }
+}
+
static void
set_debug (char *arg, int from_tty)
{
diff --git a/gdb/defs.h b/gdb/defs.h
index b5bc6c5..040d9c9 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -425,6 +425,7 @@ char *ldirname (const char *filename);
char **gdb_buildargv (const char *);
int compare_positive_ints (const void *ap, const void *bp);
+int compare_strings (const void *ap, const void *bp);
/* A wrapper for bfd_errmsg to produce a more helpful error message
in the case of bfd_error_file_ambiguously recognized.
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 8a7d7e9..7547a40 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -443,9 +443,6 @@ func_addr_to_tail_call_list (struct gdbarch *gdbarch, CORE_ADDR addr)
return sym;
}
-/* Define VEC (CORE_ADDR) functions. */
-DEF_VEC_I (CORE_ADDR);
-
/* Verify function with entry point exact address ADDR can never call itself
via its tail calls (incl. transitively). Throw NO_ENTRY_VALUE_ERROR if it
can call itself via tail calls.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 3f66c67..ba56065 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2439,10 +2439,38 @@ dw2_forget_cached_source_info (struct objfile *objfile)
dw2_free_cached_file_names, NULL);
}
+/* Helper function for dw2_map_symtabs_matching_filename that expands
+ the symtabs and calls the iterator. */
+
+static int
+dw2_map_expand_apply (struct objfile *objfile,
+ struct dwarf2_per_cu_data *per_cu,
+ const char *name,
+ const char *full_path, const char *real_path,
+ int (*callback) (struct symtab *, void *),
+ void *data)
+{
+ struct symtab *last_made = objfile->symtabs;
+
+ /* Don't visit already-expanded CUs. */
+ if (per_cu->v.quick->symtab)
+ return 0;
+
+ /* This may expand more than one symtab, and we want to iterate over
+ all of them. */
+ dw2_instantiate_symtab (objfile, per_cu);
+
+ return iterate_over_some_symtabs (name, full_path, real_path, callback, data,
+ objfile->symtabs, last_made);
+}
+
+/* Implementation of the map_symtabs_matching_filename method. */
+
static int
-dw2_lookup_symtab (struct objfile *objfile, const char *name,
- const char *full_path, const char *real_path,
- struct symtab **result)
+dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
+ const char *full_path, const char *real_path,
+ int (*callback) (struct symtab *, void *),
+ void *data)
{
int i;
const char *name_basename = lbasename (name);
@@ -2472,8 +2500,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (FILENAME_CMP (name, this_name) == 0)
{
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, per_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
if (check_basename && ! base_cu
@@ -2494,8 +2524,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (this_real_name != NULL
&& FILENAME_CMP (full_path, this_real_name) == 0)
{
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, per_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
}
@@ -2507,8 +2539,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (this_real_name != NULL
&& FILENAME_CMP (real_path, this_real_name) == 0)
{
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, per_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
}
}
@@ -2516,8 +2550,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (base_cu)
{
- *result = dw2_instantiate_symtab (objfile, base_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, base_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
return 0;
@@ -2867,7 +2903,7 @@ const struct quick_symbol_functions dwarf2_gdb_index_functions =
dw2_has_symbols,
dw2_find_last_source_symtab,
dw2_forget_cached_source_info,
- dw2_lookup_symtab,
+ dw2_map_symtabs_matching_filename,
dw2_lookup_symbol,
dw2_pre_expand_symtabs_matching,
dw2_print_stats,
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 7b935fe..5d94cd4 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -57,6 +57,7 @@
#include "tracepoint.h"
#include "inf-loop.h"
#include "continuations.h"
+#include "linespec.h"
/* Functions exported for general use, in inferior.h: */
@@ -1116,7 +1117,7 @@ jump_command (char *arg, int from_tty)
if (!arg)
error_no_arg (_("starting address"));
- sals = decode_line_spec_1 (arg, 1);
+ sals = decode_line_spec_1 (arg, DECODE_LINE_FUNFIRSTLINE);
if (sals.nelts != 1)
{
error (_("Unreasonable jump request"));
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 64ba837..2b35dc1 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -45,108 +45,246 @@
#include "cli/cli-utils.h"
#include "filenames.h"
+typedef struct symtab *symtab_p;
+DEF_VEC_P (symtab_p);
+
+typedef struct symbol *symbolp;
+DEF_VEC_P (symbolp);
+
+typedef struct type *typep;
+DEF_VEC_P (typep);
+
+/* An address entry is used to ensure that any given location is only
+ added to the result a single time. It holds an address and the
+ program space from which the address came. */
+
+struct address_entry
+{
+ struct program_space *pspace;
+ CORE_ADDR addr;
+};
+
+/* 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. */
+
+struct linespec_state
+{
+ /* The program space as seen when the module was entered. */
+ struct program_space *program_space;
+
+ /* The default symtab to use, if no other symtab is specified. */
+ struct symtab *default_symtab;
+
+ /* The default line to use. */
+ int default_line;
+
+ /* If the linespec started with "FILE:", this holds all the matching
+ symtabs. Otherwise, it will hold a single NULL entry, meaning
+ that the default symtab should be used. */
+ VEC (symtab_p) *file_symtabs;
+
+ /* If the linespec started with "FILE:", this holds an xmalloc'd
+ copy of "FILE". */
+ char *user_filename;
+
+ /* If the linespec is "FUNCTION:LABEL", this holds an xmalloc'd copy
+ of "FUNCTION". */
+ char *user_function;
+
+ /* The 'funfirstline' value that was passed in to decode_line_1 or
+ decode_line_full. */
+ int funfirstline;
+
+ /* Nonzero if we are running in 'list' mode; see decode_line_list. */
+ int list_mode;
+
+ /* The 'canonical' value passed to decode_line_full, or NULL. */
+ struct linespec_result *canonical;
+
+ /* Canonical strings that mirror the symtabs_and_lines result. */
+ char **canonical_names;
+
+ /* This is a set of address_entry objects which is used to prevent
+ duplicate symbols from being entered into the result. */
+ htab_t addr_set;
+};
+
+/* This is a helper object that is used when collecting symbols into a
+ result. */
+
+struct collect_info
+{
+ /* The linespec object in use. */
+ struct linespec_state *state;
+
+ /* The result being accumulated. */
+ struct symtabs_and_lines result;
+
+ /* The current objfile; used only by the minimal symbol code. */
+ struct objfile *objfile;
+};
+
/* Prototypes for local functions. */
static void initialize_defaults (struct symtab **default_symtab,
int *default_line);
-static struct symtabs_and_lines decode_indirect (char **argptr);
+static struct symtabs_and_lines decode_indirect (struct linespec_state *self,
+ char **argptr);
static char *locate_first_half (char **argptr, int *is_quote_enclosed);
-static struct symtabs_and_lines decode_objc (char **argptr,
- int funfirstline,
- struct symtab *file_symtab,
- struct linespec_result *canonical,
- char *saved_arg);
+static struct symtabs_and_lines decode_objc (struct linespec_state *self,
+ char **argptr);
-static struct symtabs_and_lines decode_compound (char **argptr,
- int funfirstline,
- struct linespec_result *canonical,
- struct symtab *file_symtab,
+static struct symtabs_and_lines decode_compound (struct linespec_state *self,
+ char **argptr,
char *saved_arg,
char *p);
-static struct symbol *lookup_prefix_sym (char **argptr, char *p,
- struct symtab *);
+static VEC (symbolp) *lookup_prefix_sym (char **argptr, char *p,
+ VEC (symtab_p) *,
+ char **);
-static struct symtabs_and_lines find_method (int funfirstline,
- struct linespec_result *canonical,
+static struct symtabs_and_lines find_method (struct linespec_state *self,
char *saved_arg,
char *copy,
- struct type *t,
- struct symbol *sym_class,
- struct symtab *);
+ const char *class_name,
+ VEC (symbolp) *sym_classes);
static void cplusplus_error (const char *name, const char *fmt, ...)
ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 3);
-static int total_number_of_methods (struct type *type);
+static char *find_toplevel_char (char *s, char c);
-static int find_methods (struct type *, char *,
- enum language, struct symbol **, struct symtab *);
+static int is_objc_method_format (const char *s);
-static int add_matching_methods (int method_counter, struct type *t,
- enum language language,
- struct symbol **sym_arr);
+static VEC (symtab_p) *symtabs_from_filename (char **argptr,
+ char *p, int is_quote_enclosed,
+ char **user_filename);
-static int add_constructors (int method_counter, struct type *t,
- enum language language,
- struct symbol **sym_arr);
+static VEC (symbolp) *find_function_symbols (char **argptr, char *p,
+ int is_quote_enclosed,
+ char **user_function);
-static void build_canonical_line_spec (struct symtab_and_line *,
- char *, struct linespec_result *);
+static struct symtabs_and_lines decode_all_digits (struct linespec_state *self,
+ char **argptr,
+ char *q);
-static char *find_toplevel_char (char *s, char c);
+static struct symtabs_and_lines decode_dollar (struct linespec_state *self,
+ char *copy);
-static int is_objc_method_format (const char *s);
+static int decode_label (struct linespec_state *self,
+ VEC (symbolp) *function_symbols,
+ char *copy,
+ struct symtabs_and_lines *result);
+
+static struct symtabs_and_lines decode_variable (struct linespec_state *self,
+ char *copy);
-static struct symtabs_and_lines decode_line_2 (struct symbol *[],
- int, int,
- struct linespec_result *);
+static int symbol_to_sal (struct symtab_and_line *result,
+ int funfirstline, struct symbol *sym);
-static struct symtab *symtab_from_filename (char **argptr,
- char *p, int is_quote_enclosed);
+static void add_matching_symbols_to_info (const char *name,
+ struct collect_info *info,
+ struct program_space *pspace);
-static struct symbol *find_function_symbol (char **argptr, char *p,
- int is_quote_enclosed);
+static void add_all_symbol_names_from_pspace (struct collect_info *info,
+ struct program_space *pspace,
+ VEC (const_char_ptr) *names);
-static struct
-symtabs_and_lines decode_all_digits (char **argptr,
- struct symtab *default_symtab,
- int default_line,
- struct linespec_result *canonical,
- struct symtab *file_symtab,
- char *q);
+/* Helper functions. */
-static struct symtabs_and_lines decode_dollar (char *copy,
- int funfirstline,
- struct symtab *default_symtab,
- struct linespec_result *canonical,
- struct symtab *file_symtab);
+/* Add SAL to SALS. */
-static int decode_label (struct symbol *function_symbol,
- char *copy, struct linespec_result *canonical,
- struct symtabs_and_lines *result);
+static void
+add_sal_to_sals_basic (struct symtabs_and_lines *sals,
+ struct symtab_and_line *sal)
+{
+ ++sals->nelts;
+ sals->sals = xrealloc (sals->sals, sals->nelts * sizeof (sals->sals[0]));
+ sals->sals[sals->nelts - 1] = *sal;
+}
-static struct symtabs_and_lines decode_variable (char *copy,
- int funfirstline,
- struct linespec_result *canonical,
- struct symtab *file_symtab);
+/* Add SAL to SALS, and also update SELF->CANONICAL_NAMES to reflect
+ the new sal, if needed. If not NULL, SYMNAME is the name of the
+ symbol to use when constructing the new canonical name. */
-static struct
-symtabs_and_lines symbol_found (int funfirstline,
- struct linespec_result *canonical,
- char *copy,
- struct symbol *sym,
- struct symtab *file_symtab,
- struct symbol *function_symbol);
+static void
+add_sal_to_sals (struct linespec_state *self,
+ struct symtabs_and_lines *sals,
+ struct symtab_and_line *sal,
+ const char *symname)
+{
+ add_sal_to_sals_basic (sals, sal);
-static struct
-symtabs_and_lines minsym_found (int funfirstline,
- struct minimal_symbol *msymbol);
+ if (self->canonical)
+ {
+ char *canonical_name = NULL;
-/* Helper functions. */
+ self->canonical_names = xrealloc (self->canonical_names,
+ sals->nelts * sizeof (char *));
+ if (sal->symtab && sal->symtab->filename)
+ {
+ char *filename = sal->symtab->filename;
+
+ /* FIXME: this is where we should do "FILE:FUNCTION:LINE",
+ to let us distinguish between different template
+ instantiations. */
+ if (symname != NULL)
+ canonical_name = xstrprintf ("%s:%s", filename, symname);
+ else
+ canonical_name = xstrprintf ("%s:%d", filename, sal->line);
+ }
+
+ self->canonical_names[sals->nelts - 1] = canonical_name;
+ }
+}
+
+/* A hash function for address_entry. */
+
+static hashval_t
+hash_address_entry (const void *p)
+{
+ const struct address_entry *aep = p;
+
+ return iterative_hash_object (*aep, 0);
+}
+
+/* An equality function for address_entry. */
+
+static int
+eq_address_entry (const void *a, const void *b)
+{
+ const struct address_entry *aea = a;
+ const struct address_entry *aeb = b;
+
+ return aea->pspace == aeb->pspace && aea->addr == aeb->addr;
+}
+
+/* Check whether the address, represented by PSPACE and ADDR, is
+ already in the set. If so, return 0. Otherwise, add it and return
+ 1. */
+
+static int
+maybe_add_address (htab_t set, struct program_space *pspace, CORE_ADDR addr)
+{
+ struct address_entry e, *p;
+ void **slot;
+
+ e.pspace = pspace;
+ e.addr = addr;
+ slot = htab_find_slot (set, &e, INSERT);
+ if (*slot)
+ return 0;
+
+ p = XNEW (struct address_entry);
+ memcpy (p, &e, sizeof (struct address_entry));
+ *slot = p;
+
+ return 1;
+}
/* Issue a helpful hint on using the command completion feature on
single quoted demangled C++ symbols as part of the completion
@@ -181,26 +319,64 @@ cplusplus_error (const char *name, const char *fmt, ...)
throw_error (NOT_FOUND_ERROR, "%s", message);
}
-/* Return the number of methods described for TYPE, including the
- methods from types it derives from. This can't be done in the symbol
- reader because the type of the baseclass might still be stubbed
- when the definition of the derived class is parsed. */
+/* A helper for iterate_over_all_matching_symtabs that is passed as a
+ callback to the expand_symtabs_matching method. */
static int
-total_number_of_methods (struct type *type)
+iterate_name_matcher (const char *name, void *d)
{
- int n;
- int count;
+ const char **dname = d;
- CHECK_TYPEDEF (type);
- if (! HAVE_CPLUS_STRUCT (type))
- return 0;
- count = TYPE_NFN_FIELDS_TOTAL (type);
+ if (strcmp_iw (name, *dname) == 0)
+ return 1;
+ return 0;
+}
+
+/* A helper that walks over all matching symtabs in all objfiles and
+ calls CALLBACK for each symbol matching NAME. If SEARCH_PSPACE is
+ not NULL, then the search is restricted to just that program
+ space. */
+
+static void
+iterate_over_all_matching_symtabs (const char *name,
+ const domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data,
+ struct program_space *search_pspace)
+{
+ struct objfile *objfile;
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ {
+ if (search_pspace != NULL && search_pspace != pspace)
+ continue;
+ if (pspace->executing_startup)
+ continue;
- for (n = 0; n < TYPE_N_BASECLASSES (type); n++)
- count += total_number_of_methods (TYPE_BASECLASS (type, n));
+ set_current_program_space (pspace);
- return count;
+ ALL_OBJFILES (objfile)
+ {
+ struct symtab *symtab;
+
+ if (objfile->sf)
+ objfile->sf->qf->expand_symtabs_matching (objfile, NULL,
+ iterate_name_matcher,
+ ALL_DOMAIN,
+ &name);
+
+ ALL_OBJFILE_SYMTABS (objfile, symtab)
+ {
+ if (symtab->primary)
+ {
+ struct block *block;
+ block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+ iterate_over_symbols (block, name, domain, callback, data);
+ }
+ }
+ }
+ }
}
/* Returns the block to be used for symbol searches for the given SYMTAB,
@@ -227,40 +403,24 @@ get_search_block (struct symtab *symtab)
return block;
}
-/* Recursive helper function for decode_line_1.
- Look for methods named NAME in type T.
- Return number of matches.
- Put matches in SYM_ARR, which should have been allocated with
- a size of total_number_of_methods (T) * sizeof (struct symbol *).
- Note that this function is g++ specific. */
+/* A helper for find_method. This finds all methods in type T which
+ match NAME. It adds resulting symbol names to RESULT_NAMES, and
+ adds T's direct superclasses to SUPERCLASSES. */
-static int
-find_methods (struct type *t, char *name, enum language language,
- struct symbol **sym_arr, struct symtab *file_symtab)
+static void
+find_methods (struct type *t, const char *name,
+ VEC (const_char_ptr) **result_names,
+ VEC (typep) **superclasses)
{
int i1 = 0;
int ibase;
char *class_name = type_name_no_tag (t);
- struct cleanup *cleanup;
char *canon;
- /* NAME is typed by the user: it needs to be canonicalized before
- passing to lookup_symbol. */
- canon = cp_canonicalize_string_no_typedefs (name);
- if (canon != NULL)
- {
- name = canon;
- cleanup = make_cleanup (xfree, name);
- }
- else
- cleanup = make_cleanup (null_cleanup, NULL);
-
/* Ignore this class if it doesn't have a name. This is ugly, but
unless we figure out how to get the physname without the name of
the class, then the loop can't do any good. */
- if (class_name
- && (lookup_symbol_in_language (class_name, get_search_block (file_symtab),
- STRUCT_DOMAIN, language, (int *) NULL)))
+ if (class_name)
{
int method_counter;
int name_len = strlen (name);
@@ -288,181 +448,32 @@ find_methods (struct type *t, char *name, enum language language,
method_name = dem_opname;
}
- if (strcmp_iw (name, method_name) == 0)
- /* Find all the overloaded methods with that name. */
- i1 += add_matching_methods (method_counter, t, language,
- sym_arr + i1);
- else if (strncmp (class_name, name, name_len) == 0
- && (class_name[name_len] == '\0'
- || class_name[name_len] == '<'))
- i1 += add_constructors (method_counter, t, language,
- sym_arr + i1);
- }
- }
-
- /* Only search baseclasses if there is no match yet, since names in
- derived classes override those in baseclasses.
-
- FIXME: The above is not true; it is only true of member functions
- if they have the same number of arguments (??? - section 13.1 of the
- ARM says the function members are not in the same scope but doesn't
- really spell out the rules in a way I understand. In any case, if
- the number of arguments differ this is a case in which we can overload
- rather than hiding without any problem, and gcc 2.4.5 does overload
- rather than hiding in this case). */
-
- if (i1 == 0)
- for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
- i1 += find_methods (TYPE_BASECLASS (t, ibase), name,
- language, sym_arr + i1, file_symtab);
-
- do_cleanups (cleanup);
- return i1;
-}
-
-/* Add the symbols associated to methods of the class whose type is T
- and whose name matches the method indexed by METHOD_COUNTER in the
- array SYM_ARR. Return the number of methods added. */
-
-static int
-add_matching_methods (int method_counter, struct type *t,
- enum language language, struct symbol **sym_arr)
-{
- int field_counter;
- int i1 = 0;
-
- for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
- field_counter >= 0;
- --field_counter)
- {
- struct fn_field *f;
- const char *phys_name;
-
- f = TYPE_FN_FIELDLIST1 (t, method_counter);
+ if (strcmp_iw (method_name, name) == 0)
+ {
+ int field_counter;
- if (TYPE_FN_FIELD_STUB (f, field_counter))
- {
- char *tmp_name, *tmp2;
-
- tmp_name = gdb_mangle_name (t,
- method_counter,
- field_counter);
- tmp2 = alloca (strlen (tmp_name) + 1);
- strcpy (tmp2, tmp_name);
- xfree (tmp_name);
- phys_name = tmp2;
- }
- else
- phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
-
- sym_arr[i1] = lookup_symbol_in_language (phys_name,
- NULL, VAR_DOMAIN,
- language,
- (int *) NULL);
- if (sym_arr[i1])
- i1++;
- else
- {
- /* This error message gets printed, but the method
- still seems to be found.
- fputs_filtered("(Cannot find method ", gdb_stdout);
- fprintf_symbol_filtered (gdb_stdout, phys_name,
- language_cplus,
- DMGL_PARAMS | DMGL_ANSI);
- fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
- */
+ for (field_counter = (TYPE_FN_FIELDLIST_LENGTH (t, method_counter)
+ - 1);
+ field_counter >= 0;
+ --field_counter)
+ {
+ struct fn_field *f;
+ const char *phys_name;
+
+ f = TYPE_FN_FIELDLIST1 (t, method_counter);
+ if (TYPE_FN_FIELD_STUB (f, field_counter))
+ continue;
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+ VEC_safe_push (const_char_ptr, *result_names, phys_name);
+ }
+ }
}
}
- return i1;
-}
-
-/* Add the symbols associated to constructors of the class whose type
- is CLASS_TYPE and which are indexed by by METHOD_COUNTER to the
- array SYM_ARR. Return the number of methods added. */
-
-static int
-add_constructors (int method_counter, struct type *t,
- enum language language, struct symbol **sym_arr)
-{
- int field_counter;
- int i1 = 0;
-
- /* For GCC 3.x and stabs, constructors and destructors
- have names like __base_ctor and __complete_dtor.
- Check the physname for now if we're looking for a
- constructor. */
- for (field_counter
- = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
- field_counter >= 0;
- --field_counter)
- {
- struct fn_field *f;
- const char *phys_name;
-
- f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
- /* GCC 3.x will never produce stabs stub methods, so
- we don't need to handle this case. */
- if (TYPE_FN_FIELD_STUB (f, field_counter))
- continue;
- phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
- if (! is_constructor_name (phys_name))
- continue;
-
- /* If this method is actually defined, include it in the
- list. */
- sym_arr[i1] = lookup_symbol_in_language (phys_name,
- NULL, VAR_DOMAIN,
- language,
- (int *) NULL);
- if (sym_arr[i1])
- i1++;
- }
-
- return i1;
-}
-
-/* Helper function for decode_line_1.
- Build a canonical line spec in CANONICAL if it is non-NULL and if
- the SAL has a symtab.
- If SYMNAME is non-NULL the canonical line spec is `filename:symname'.
- If SYMNAME is NULL the line number from SAL is used and the canonical
- line spec is `filename:linenum'. */
-
-static void
-build_canonical_line_spec (struct symtab_and_line *sal, char *symname,
- struct linespec_result *canonical)
-{
- char **canonical_arr;
- char *canonical_name;
- char *filename;
- struct symtab *s = sal->symtab;
-
- if (s == (struct symtab *) NULL
- || s->filename == (char *) NULL
- || canonical == NULL)
- return;
-
- canonical_arr = (char **) xmalloc (sizeof (char *));
- canonical->canonical = canonical_arr;
-
- filename = s->filename;
- if (symname != NULL)
- {
- canonical_name = xmalloc (strlen (filename) + strlen (symname) + 2);
- sprintf (canonical_name, "%s:%s", filename, symname);
- }
- else
- {
- canonical_name = xmalloc (strlen (filename) + 30);
- sprintf (canonical_name, "%s:%d", filename, sal->line);
- }
- canonical_arr[0] = canonical_name;
+ for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
+ VEC_safe_push (typep, *superclasses, TYPE_BASECLASS (t, ibase));
}
-
-
/* Find an instance of the character C in the string S that is outside
of all parenthesis pairs, single-quoted strings, and double-quoted
strings. Also, ignore the char within a template name, like a ','
@@ -518,147 +529,154 @@ is_objc_method_format (const char *s)
return 0;
}
-/* Given a list of NELTS symbols in SYM_ARR, return a list of lines to
- operate on (ask user if necessary).
- If CANONICAL is non-NULL return a corresponding array of mangled names
- as canonical line specs there. */
+/* Given FILTERS, a list of canonical names, filter the sals in RESULT
+ and store the result in SELF->CANONICAL. */
-static struct symtabs_and_lines
-decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
- struct linespec_result *canonical)
+static void
+filter_results (struct linespec_state *self,
+ struct symtabs_and_lines *result,
+ VEC (const_char_ptr) *filters)
+{
+ int i;
+ const char *name;
+
+ for (i = 0; VEC_iterate (const_char_ptr, filters, i, name); ++i)
+ {
+ struct linespec_sals lsal;
+ int j;
+
+ memset (&lsal, 0, sizeof (lsal));
+
+ for (j = 0; j < result->nelts; ++j)
+ {
+ if (strcmp (name, self->canonical_names[j]) == 0)
+ add_sal_to_sals_basic (&lsal.sals, &result->sals[j]);
+ }
+
+ if (lsal.sals.nelts > 0)
+ {
+ lsal.canonical = xstrdup (name);
+ VEC_safe_push (linespec_sals, self->canonical->sals, &lsal);
+ }
+ }
+
+ self->canonical->pre_expanded = 0;
+}
+
+/* Store RESULT into SELF->CANONICAL. */
+
+static void
+convert_results_to_lsals (struct linespec_state *self,
+ struct symtabs_and_lines *result)
+{
+ struct linespec_sals lsal;
+
+ lsal.canonical = NULL;
+ lsal.sals = *result;
+ VEC_safe_push (linespec_sals, self->canonical->sals, &lsal);
+}
+
+/* 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
+ in SELF->CANONICAL is set up properly. */
+
+static void
+decode_line_2 (struct linespec_state *self,
+ struct symtabs_and_lines *result,
+ const char *select_mode)
{
- struct symtabs_and_lines values, return_values;
- char *args, *arg1;
+ const char *iter;
+ char *args, *prompt;
int i;
- char *prompt;
- char *symname;
struct cleanup *old_chain;
- char **canonical_arr = (char **) NULL;
- const char *select_mode = multiple_symbols_select_mode ();
+ VEC (const_char_ptr) *item_names = NULL, *filters = NULL;
+ struct get_number_or_range_state state;
- if (select_mode == multiple_symbols_cancel)
- error (_("canceled because the command is ambiguous\n"
- "See set/show multiple-symbol."));
-
- values.sals = (struct symtab_and_line *)
- alloca (nelts * sizeof (struct symtab_and_line));
- return_values.sals = (struct symtab_and_line *)
- xmalloc (nelts * sizeof (struct symtab_and_line));
- old_chain = make_cleanup (xfree, return_values.sals);
+ gdb_assert (select_mode != multiple_symbols_all);
+ gdb_assert (self->canonical != NULL);
- if (canonical)
+ 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)
{
- canonical_arr = (char **) xmalloc (nelts * sizeof (char *));
- make_cleanup (xfree, canonical_arr);
- memset (canonical_arr, 0, nelts * sizeof (char *));
- canonical->canonical = canonical_arr;
+ int j, found = 0;
+ const char *iter;
+
+ gdb_assert (self->canonical_names[i] != NULL);
+ for (j = 0; VEC_iterate (const_char_ptr, item_names, j, iter); ++j)
+ {
+ if (strcmp (iter, self->canonical_names[i]) == 0)
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ VEC_safe_push (const_char_ptr, item_names, self->canonical_names[i]);
}
- i = 0;
- while (i < nelts)
+ if (select_mode == multiple_symbols_cancel
+ && VEC_length (const_char_ptr, item_names) > 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)
{
- init_sal (&return_values.sals[i]); /* Initialize to zeroes. */
- init_sal (&values.sals[i]);
- if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
- values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
- i++;
+ do_cleanups (old_chain);
+ convert_results_to_lsals (self, result);
+ return;
}
- /* If select_mode is "all", then do not print the multiple-choice
- menu and act as if the user had chosen choice "1" (all). */
- if (select_mode == multiple_symbols_all
- || ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
- args = "1";
- else
+ 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);
+
+ prompt = getenv ("PS2");
+ if (prompt == NULL)
{
- i = 0;
- printf_unfiltered (_("[0] cancel\n[1] all\n"));
- while (i < nelts)
- {
- if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
- {
- if (values.sals[i].symtab)
- printf_unfiltered ("[%d] %s at %s:%d\n",
- (i + 2),
- SYMBOL_PRINT_NAME (sym_arr[i]),
- values.sals[i].symtab->filename,
- values.sals[i].line);
- else
- printf_unfiltered (_("[%d] %s at ?FILE:%d [No symtab? "
- "Probably broken debug info...]\n"),
- (i + 2),
- SYMBOL_PRINT_NAME (sym_arr[i]),
- values.sals[i].line);
-
- }
- else
- printf_unfiltered (_("?HERE\n"));
- i++;
- }
-
- prompt = getenv ("PS2");
- if (prompt == NULL)
- {
- prompt = "> ";
- }
- args = command_line_input (prompt, 0, "overload-choice");
+ prompt = "> ";
}
+ args = command_line_input (prompt, 0, "overload-choice");
if (args == 0 || *args == 0)
error_no_arg (_("one or more choice numbers"));
- i = 0;
- while (*args)
+ init_number_or_range (&state, args);
+ while (!state.finished)
{
int num;
- arg1 = args;
- while (*arg1 >= '0' && *arg1 <= '9')
- arg1++;
- if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
- error (_("Arguments must be choice numbers."));
-
- num = atoi (args);
+ num = get_number_or_range (&state);
if (num == 0)
error (_("canceled"));
else if (num == 1)
{
- if (canonical_arr)
- {
- for (i = 0; i < nelts; i++)
- {
- if (canonical_arr[i] == NULL)
- {
- symname = SYMBOL_LINKAGE_NAME (sym_arr[i]);
- canonical_arr[i] = xstrdup (symname);
- }
- }
- }
- memcpy (return_values.sals, values.sals,
- (nelts * sizeof (struct symtab_and_line)));
- return_values.nelts = nelts;
- discard_cleanups (old_chain);
- return return_values;
+ /* We intentionally make this result in a single breakpoint,
+ contrary to what older versions of gdb did. The
+ rationale is that this lets a user get the
+ multiple_symbols_all behavior even with the 'ask'
+ setting; and he can get separate breakpoints by entering
+ "2-57" at the query. */
+ do_cleanups (old_chain);
+ convert_results_to_lsals (self, result);
+ return;
}
- if (num >= nelts + 2)
- {
- printf_unfiltered (_("No choice number %d.\n"), num);
- }
+ num -= 2;
+ if (num >= VEC_length (const_char_ptr, item_names))
+ printf_unfiltered (_("No choice number %d.\n"), num);
else
{
- num -= 2;
- if (values.sals[num].pc)
+ const char *elt = VEC_index (const_char_ptr, item_names, num);
+
+ if (elt != NULL)
{
- if (canonical_arr)
- {
- symname = SYMBOL_LINKAGE_NAME (sym_arr[num]);
- make_cleanup (xfree, symname);
- canonical_arr[i] = xstrdup (symname);
- }
- return_values.sals[i++] = values.sals[num];
- values.sals[num].pc = 0;
+ VEC_safe_push (const_char_ptr, filters, elt);
+ VEC_replace (const_char_ptr, item_names, num, NULL);
}
else
{
@@ -666,14 +684,10 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
num);
}
}
-
- args = arg1;
- while (*args == ' ' || *args == '\t')
- args++;
}
- return_values.nelts = i;
- discard_cleanups (old_chain);
- return return_values;
+
+ filter_results (self, result, filters);
+ do_cleanups (old_chain);
}
/* Valid delimiters for linespec keywords "if", "thread" or "task". */
@@ -813,13 +827,10 @@ keep_name_info (char *p, int on_boundary)
can use as appropriate instead of make_symbol_completion_list. */
struct symtabs_and_lines
-decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
- int default_line, struct linespec_result *canonical)
+decode_line_internal (struct linespec_state *self, char **argptr)
{
char *p;
char *q;
- /* If a file name is specified, this is its symtab. */
- struct symtab *file_symtab = NULL;
char *copy;
/* This says whether or not something in *ARGPTR is quoted with
@@ -836,21 +847,26 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
/* The "first half" of the linespec. */
char *first_half;
- /* If we are parsing `function:label', this holds the symbol for the
- function. */
- struct symbol *function_symbol = NULL;
- /* If FUNCTION_SYMBOL is not NULL, then this is the exception that
+ /* If we are parsing `function:label', this holds the symbols
+ matching the function name. */
+ VEC (symbolp) *function_symbols = NULL;
+ /* If FUNCTION_SYMBOLS is not NULL, then this is the exception that
was thrown when trying to parse a filename. */
volatile struct gdb_exception file_exception;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+
/* Defaults have defaults. */
- initialize_defaults (&default_symtab, &default_line);
+ initialize_defaults (&self->default_symtab, &self->default_line);
/* See if arg is *PC. */
if (**argptr == '*')
- return decode_indirect (argptr);
+ {
+ do_cleanups (cleanup);
+ return decode_indirect (self, argptr);
+ }
is_quoted = (strchr (get_gdb_completer_quote_characters (),
**argptr) != NULL);
@@ -877,7 +893,14 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
symtab and strip the filename from ARGPTR. */
TRY_CATCH (file_exception, RETURN_MASK_ERROR)
{
- file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed);
+ self->file_symtabs = symtabs_from_filename (argptr, p, is_quote_enclosed,
+ &self->user_filename);
+ }
+
+ if (VEC_empty (symtab_p, self->file_symtabs))
+ {
+ /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB. */
+ VEC_safe_push (symtab_p, self->file_symtabs, NULL);
}
if (file_exception.reason >= 0)
@@ -903,10 +926,12 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
{
struct symtabs_and_lines values;
- values = decode_objc (argptr, funfirstline, file_symtab,
- canonical, saved_arg);
+ values = decode_objc (self, argptr);
if (values.sals != NULL)
- return values;
+ {
+ do_cleanups (cleanup);
+ return values;
+ }
}
/* Does it look like there actually were two parts? */
@@ -934,14 +959,16 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
TRY_CATCH (ex, RETURN_MASK_ERROR)
{
- values = decode_compound (argptr, funfirstline, canonical,
- file_symtab, saved_arg, p);
+ values = decode_compound (self, argptr, saved_arg, p);
}
if ((is_quoted || is_squote_enclosed) && **argptr == '\'')
*argptr = *argptr + 1;
if (ex.reason >= 0)
- return values;
+ {
+ do_cleanups (cleanup);
+ return values;
+ }
if (ex.error != NOT_FOUND_ERROR)
throw_exception (ex);
@@ -954,12 +981,16 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
then check whether we were really given `function:label'. */
if (file_exception.reason < 0)
{
- function_symbol = find_function_symbol (argptr, p,
- is_quote_enclosed);
+ function_symbols = find_function_symbols (argptr, p,
+ is_quote_enclosed,
+ &self->user_function);
+
/* If we did not find a function, re-throw the original
exception. */
- if (!function_symbol)
+ if (!function_symbols)
throw_exception (file_exception);
+
+ make_cleanup (VEC_cleanup (symbolp), &function_symbols);
}
/* Check for single quotes on the non-filename part. */
@@ -974,9 +1005,10 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
}
}
- /* file_symtab is specified file's symtab, or 0 if no file specified.
- If we are parsing `function:symbol', then FUNCTION_SYMBOL is the
- function before the `:'.
+ /* self->file_symtabs holds the specified file symtabs, or 0 if no file
+ specified.
+ If we are parsing `function:symbol', then FUNCTION_SYMBOLS holds the
+ functions before the `:'.
arg no longer contains the file name. */
/* If the filename was quoted, we must re-check the quotation. */
@@ -999,10 +1031,15 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
q++;
if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ',')
- && function_symbol == NULL)
- /* We found a token consisting of all digits -- at least one digit. */
- return decode_all_digits (argptr, default_symtab, default_line,
- canonical, file_symtab, q);
+ && function_symbols == NULL)
+ {
+ struct symtabs_and_lines values;
+
+ /* We found a token consisting of all digits -- at least one digit. */
+ values = decode_all_digits (self, argptr, q);
+ do_cleanups (cleanup);
+ return values;
+ }
/* Arg token is not digits => try it as a variable name
Find the next token (everything up to end or next whitespace). */
@@ -1042,91 +1079,218 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
}
else if (is_quoted || is_squote_enclosed)
copy[p - *argptr - 1] = '\0';
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
+
+ *argptr = skip_spaces (p);
/* If it starts with $: may be a legitimate variable or routine name
(e.g. HP-UX millicode routines such as $$dyncall), or it may
be history value, or it may be a convenience variable. */
- if (*copy == '$' && function_symbol == NULL)
- return decode_dollar (copy, funfirstline, default_symtab,
- canonical, file_symtab);
+ if (*copy == '$' && function_symbols == NULL)
+ {
+ struct symtabs_and_lines values;
+
+ values = decode_dollar (self, copy);
+ do_cleanups (cleanup);
+ return values;
+ }
/* Try the token as a label, but only if no file was specified,
because we can only really find labels in the current scope. */
- if (!file_symtab)
+ if (VEC_length (symtab_p, self->file_symtabs) == 1
+ && VEC_index (symtab_p, self->file_symtabs, 0) == NULL)
{
struct symtabs_and_lines label_result;
- if (decode_label (function_symbol, copy, canonical, &label_result))
- return label_result;
+ if (decode_label (self, function_symbols, copy, &label_result))
+ {
+ do_cleanups (cleanup);
+ return label_result;
+ }
}
- if (function_symbol)
+ if (function_symbols)
throw_exception (file_exception);
/* Look up that token as a variable.
If file specified, use that file's per-file block to start with. */
- return decode_variable (copy, funfirstline, canonical, file_symtab);
+ {
+ struct symtabs_and_lines values;
+
+ values = decode_variable (self, copy);
+ do_cleanups (cleanup);
+ return values;
+ }
}
-\f
+/* A constructor for linespec_state. */
-/* Now, more helper functions for decode_line_1. Some conventions
- that these functions follow:
-
- Decode_line_1 typically passes along some of its arguments or local
- variables to the subfunctions. It passes the variables by
- reference if they are modified by the subfunction, and by value
- otherwise.
-
- Some of the functions have side effects that don't arise from
- variables that are passed by reference. In particular, if a
- function is passed ARGPTR as an argument, it modifies what ARGPTR
- points to; typically, it advances *ARGPTR past whatever substring
- it has just looked at. (If it doesn't modify *ARGPTR, then the
- function gets passed *ARGPTR instead, which is then called ARG.)
- Also, functions that return a struct symtabs_and_lines may modify
- CANONICAL, as in the description of decode_line_1.
-
- If a function returns a struct symtabs_and_lines, then that struct
- will immediately make its way up the call chain to be returned by
- decode_line_1. In particular, all of the functions decode_XXX
- calculate the appropriate struct symtabs_and_lines, under the
- assumption that their argument is of the form XXX. */
+static void
+linespec_state_constructor (struct linespec_state *self,
+ int flags,
+ struct symtab *default_symtab,
+ int default_line,
+ struct linespec_result *canonical)
+{
+ memset (self, 0, sizeof (*self));
+ self->funfirstline = (flags & DECODE_LINE_FUNFIRSTLINE) ? 1 : 0;
+ self->list_mode = (flags & DECODE_LINE_LIST_MODE) ? 1 : 0;
+ self->default_symtab = default_symtab;
+ self->default_line = default_line;
+ self->canonical = canonical;
+ self->program_space = current_program_space;
+ self->addr_set = htab_create_alloc (10, hash_address_entry, eq_address_entry,
+ xfree, xcalloc, xfree);
+}
-/* First, some functions to initialize stuff at the beggining of the
- function. */
+/* A destructor for linespec_state. */
static void
-initialize_defaults (struct symtab **default_symtab, int *default_line)
+linespec_state_destructor (void *arg)
{
- if (*default_symtab == 0)
- {
- /* Use whatever we have for the default source line. We don't use
- get_current_or_default_symtab_and_line as it can recurse and call
- us back! */
- struct symtab_and_line cursal =
- get_current_source_symtab_and_line ();
-
- *default_symtab = cursal.symtab;
- *default_line = cursal.line;
- }
-}
+ struct linespec_state *self = arg;
-\f
+ xfree (self->user_filename);
+ xfree (self->user_function);
+ VEC_free (symtab_p, self->file_symtabs);
+ htab_delete (self->addr_set);
+}
-/* Decode arg of the form *PC. */
+/* See linespec.h. */
-static struct symtabs_and_lines
-decode_indirect (char **argptr)
+void
+decode_line_full (char **argptr, int flags,
+ struct symtab *default_symtab,
+ int default_line, struct linespec_result *canonical,
+ const char *select_mode,
+ const char *filter)
{
- struct symtabs_and_lines values;
- CORE_ADDR pc;
+ struct symtabs_and_lines result;
+ struct linespec_state state;
+ struct cleanup *cleanups;
+ char *arg_start = *argptr;
+ VEC (const_char_ptr) *filters = NULL;
+
+ gdb_assert (canonical != NULL);
+ /* The filter only makes sense for 'all'. */
+ gdb_assert (filter == NULL || select_mode == multiple_symbols_all);
+ gdb_assert (select_mode == NULL
+ || select_mode == multiple_symbols_all
+ || select_mode == multiple_symbols_ask
+ || select_mode == multiple_symbols_cancel);
+ gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
+
+ linespec_state_constructor (&state, flags,
+ default_symtab, default_line, canonical);
+ cleanups = make_cleanup (linespec_state_destructor, &state);
+ save_current_program_space ();
+
+ result = decode_line_internal (&state, argptr);
+
+ gdb_assert (result.nelts == 1 || canonical->pre_expanded);
+ gdb_assert (canonical->addr_string != NULL);
+ canonical->pre_expanded = 1;
+
+ /* Fill in the missing canonical names. */
+ if (result.nelts > 0)
+ {
+ int i;
+
+ if (state.canonical_names == NULL)
+ state.canonical_names = xcalloc (result.nelts, sizeof (char *));
+ make_cleanup (xfree, state.canonical_names);
+ for (i = 0; i < result.nelts; ++i)
+ {
+ if (state.canonical_names[i] == NULL)
+ state.canonical_names[i] = savestring (arg_start,
+ *argptr - arg_start);
+ make_cleanup (xfree, state.canonical_names[i]);
+ }
+ }
+
+ if (select_mode == NULL)
+ {
+ if (ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
+ select_mode = multiple_symbols_all;
+ else
+ select_mode = multiple_symbols_select_mode ();
+ }
+
+ if (select_mode == multiple_symbols_all)
+ {
+ if (filter != NULL)
+ {
+ make_cleanup (VEC_cleanup (const_char_ptr), &filters);
+ VEC_safe_push (const_char_ptr, filters, filter);
+ filter_results (&state, &result, filters);
+ }
+ else
+ convert_results_to_lsals (&state, &result);
+ }
+ else
+ decode_line_2 (&state, &result, select_mode);
+
+ do_cleanups (cleanups);
+}
+
+struct symtabs_and_lines
+decode_line_1 (char **argptr, int flags,
+ struct symtab *default_symtab,
+ int default_line)
+{
+ struct symtabs_and_lines result;
+ struct linespec_state state;
+ struct cleanup *cleanups;
+
+ linespec_state_constructor (&state, flags,
+ default_symtab, default_line, NULL);
+ cleanups = make_cleanup (linespec_state_destructor, &state);
+ save_current_program_space ();
+
+ result = decode_line_internal (&state, argptr);
+ do_cleanups (cleanups);
+ return result;
+}
+
+\f
+
+/* First, some functions to initialize stuff at the beggining of the
+ function. */
+
+static void
+initialize_defaults (struct symtab **default_symtab, int *default_line)
+{
+ if (*default_symtab == 0)
+ {
+ /* Use whatever we have for the default source line. We don't use
+ get_current_or_default_symtab_and_line as it can recurse and call
+ us back! */
+ struct symtab_and_line cursal =
+ get_current_source_symtab_and_line ();
+
+ *default_symtab = cursal.symtab;
+ *default_line = cursal.line;
+ }
+}
+
+\f
+
+/* Decode arg of the form *PC. */
+
+static struct symtabs_and_lines
+decode_indirect (struct linespec_state *self, char **argptr)
+{
+ struct symtabs_and_lines values;
+ CORE_ADDR pc;
+ char *initial = *argptr;
+ if (current_program_space->executing_startup)
+ /* The error message doesn't really matter, because this case
+ should only hit during breakpoint reset. */
+ throw_error (NOT_FOUND_ERROR, _("cannot evaluate expressions while "
+ "program space is in startup"));
+
(*argptr)++;
pc = value_as_address (parse_to_comma_and_eval (argptr));
@@ -1139,6 +1303,9 @@ decode_indirect (char **argptr)
values.sals[0].section = find_pc_overlay (pc);
values.sals[0].explicit_pc = 1;
+ if (self->canonical)
+ self->canonical->addr_string = savestring (initial, *argptr - initial);
+
return values;
}
@@ -1246,8 +1413,7 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
break;
}
}
- while (p[0] == ' ' || p[0] == '\t')
- p++;
+ p = skip_spaces (p);
/* If the closing double quote was left at the end, remove it. */
if (*is_quote_enclosed)
@@ -1275,94 +1441,52 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
than one method that could represent the selector, then use some of
the existing C++ code to let the user choose one. */
-struct symtabs_and_lines
-decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab,
- struct linespec_result *canonical, char *saved_arg)
+static struct symtabs_and_lines
+decode_objc (struct linespec_state *self, char **argptr)
{
- struct symtabs_and_lines values;
- struct symbol **sym_arr = NULL;
- struct symbol *sym = NULL;
- struct block *block = NULL;
- unsigned i1 = 0;
- unsigned i2 = 0;
+ struct collect_info info;
+ VEC (const_char_ptr) *symbol_names = NULL;
+ char *new_argptr;
+ struct cleanup *cleanup = make_cleanup (VEC_cleanup (const_char_ptr),
+ &symbol_names);
+
+ info.state = self;
+ info.result.sals = NULL;
+ info.result.nelts = 0;
+ info.objfile = NULL;
+
+ new_argptr = find_imps (*argptr, &symbol_names);
+ if (VEC_empty (const_char_ptr, symbol_names))
+ {
+ do_cleanups (cleanup);
+ return info.result;
+ }
- values.sals = NULL;
- values.nelts = 0;
+ add_all_symbol_names_from_pspace (&info, NULL, symbol_names);
- find_imps (file_symtab, get_search_block (file_symtab), *argptr,
- NULL, &i1, &i2);
-
- if (i1 > 0)
+ if (info.result.nelts > 0)
{
- sym_arr = (struct symbol **)
- alloca ((i1 + 1) * sizeof (struct symbol *));
- sym_arr[i1] = NULL;
+ char *saved_arg;
- *argptr = find_imps (file_symtab, block, *argptr, sym_arr, &i1, &i2);
- }
+ saved_arg = alloca (new_argptr - *argptr + 1);
+ memcpy (saved_arg, *argptr, new_argptr - *argptr);
+ saved_arg[new_argptr - *argptr] = '\0';
- /* i1 now represents the TOTAL number of matches found.
- i2 represents how many HIGH-LEVEL (struct symbol) matches,
- which will come first in the sym_arr array. Any low-level
- (minimal_symbol) matches will follow those. */
-
- if (i1 == 1)
- {
- if (i2 > 0)
- {
- /* Already a struct symbol. */
- sym = sym_arr[0];
- }
- else
- {
- sym = find_pc_function (SYMBOL_VALUE_ADDRESS (sym_arr[0]));
- if ((sym != NULL) && strcmp (SYMBOL_LINKAGE_NAME (sym_arr[0]),
- SYMBOL_LINKAGE_NAME (sym)) != 0)
- {
- warning (_("debugging symbol \"%s\" does "
- "not match selector; ignoring"),
- SYMBOL_LINKAGE_NAME (sym));
- sym = NULL;
- }
- }
-
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
-
- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+ if (self->canonical)
{
- /* Canonicalize this, so it remains resolved for dylib loads. */
- values.sals[0] = find_function_start_sal (sym, funfirstline);
- build_canonical_line_spec (values.sals,
- SYMBOL_NATURAL_NAME (sym), canonical);
- }
- else
- {
- /* The only match was a non-debuggable symbol, which might point
- to a function descriptor; resolve it to the actual code address
- instead. */
- struct minimal_symbol *msymbol = (struct minimal_symbol *)sym_arr[0];
- struct objfile *objfile = msymbol_objfile (msymbol);
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
- CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol);
-
- pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
- ¤t_target);
-
- init_sal (&values.sals[0]);
- values.sals[0].pc = pc;
+ self->canonical->pre_expanded = 1;
+ if (self->user_filename)
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", self->user_filename, saved_arg);
+ else
+ self->canonical->addr_string = xstrdup (saved_arg);
}
- return values;
}
- if (i1 > 1)
- {
- /* More than one match. The user must choose one or more. */
- return decode_line_2 (sym_arr, i2, funfirstline, canonical);
- }
+ *argptr = new_argptr;
- return values;
+ do_cleanups (cleanup);
+ return info.result;
}
/* This handles C++ and Java compound data structures. P should point
@@ -1371,9 +1495,8 @@ decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab,
pointing to "AAA::inA::fun" and P pointing to "::inA::fun". */
static struct symtabs_and_lines
-decode_compound (char **argptr, int funfirstline,
- struct linespec_result *canonical, struct symtab *file_symtab,
- char *the_real_saved_arg, char *p)
+decode_compound (struct linespec_state *self,
+ char **argptr, char *the_real_saved_arg, char *p)
{
struct symtabs_and_lines values;
char *p2, *name, *canon;
@@ -1381,10 +1504,9 @@ decode_compound (char **argptr, int funfirstline,
char *temp_end;
struct symbol *sym;
char *copy;
- struct symbol *sym_class;
- struct type *t;
- char *saved_arg;
- struct cleanup *cleanup;
+ VEC (symbolp) *sym_classes;
+ char *saved_arg, *class_name;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
/* If the user specified any completer quote characters in the input,
strip them. They are superfluous. */
@@ -1419,8 +1541,7 @@ decode_compound (char **argptr, int funfirstline,
2) AAA::inA isn't the name of a class. In that case, either the
user made a typo, AAA::inA is the name of a namespace, or it is
the name of a minimal symbol.
- We just look up AAA::inA::fun with lookup_symbol. If that fails,
- try lookup_minimal_symbol.
+ In this case we just delegate to decode_variable.
Thus, our first task is to find everything before the last set of
double-colons and figure out if it's the name of a class. So we
@@ -1520,15 +1641,14 @@ decode_compound (char **argptr, int funfirstline,
/* Before the call, argptr->"AAA::inA::fun",
p->"", p2->"::fun". After the call: argptr->"fun", p, p2
unchanged. */
- sym_class = lookup_prefix_sym (argptr, p2, file_symtab);
-
- /* If sym_class has been found, and if "AAA::inA" is a class, then
- we're in case 1 above. So we look up "fun" as a method of that
- class. */
- if (sym_class &&
- (t = check_typedef (SYMBOL_TYPE (sym_class)),
- (TYPE_CODE (t) == TYPE_CODE_STRUCT
- || TYPE_CODE (t) == TYPE_CODE_UNION)))
+ sym_classes = lookup_prefix_sym (argptr, p2, self->file_symtabs,
+ &class_name);
+ make_cleanup (VEC_cleanup (symbolp), &sym_classes);
+ make_cleanup (xfree, class_name);
+
+ /* If a class has been found, then we're in case 1 above. So we
+ look up "fun" as a method of those classes. */
+ if (!VEC_empty (symbolp, sym_classes))
{
/* Arg token is not digits => try it as a function name.
Find the next token (everything up to end or next
@@ -1578,9 +1698,7 @@ decode_compound (char **argptr, int funfirstline,
/* At this point copy->"fun", p->"". */
/* No line number may be specified. */
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
+ *argptr = skip_spaces (p);
/* At this point arptr->"". */
/* Look for copy as a method of sym_class. */
@@ -1590,8 +1708,10 @@ decode_compound (char **argptr, int funfirstline,
here, we return. If not, and we are at the and of the string,
we'll lookup the whole string in the symbol tables. */
- return find_method (funfirstline, canonical, saved_arg, copy, t,
- sym_class, file_symtab);
+ values = find_method (self, saved_arg, copy, class_name, sym_classes);
+
+ do_cleanups (cleanup);
+ return values;
} /* End if symbol found. */
@@ -1611,7 +1731,6 @@ decode_compound (char **argptr, int funfirstline,
/* Look up entire name. */
name = copy;
- cleanup = make_cleanup (null_cleanup, NULL);
canon = cp_canonicalize_string_no_typedefs (copy);
if (canon != NULL)
{
@@ -1619,213 +1738,400 @@ decode_compound (char **argptr, int funfirstline,
make_cleanup (xfree, name);
}
- sym = lookup_symbol (name, get_selected_block (0), VAR_DOMAIN, 0);
- do_cleanups (cleanup);
- if (sym)
- return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL);
- else
- {
- struct minimal_symbol *msym;
+ return decode_variable (self, copy);
+}
- /* Couldn't find any interpretation as classes/namespaces. As a last
- resort, try the minimal symbol tables. */
- msym = lookup_minimal_symbol (copy, NULL, NULL);
- if (msym != NULL)
- return minsym_found (funfirstline, msym);
- }
+/* An instance of this type is used when collecting prefix symbols for
+ decode_compound. */
- /* Couldn't find a minimal symbol, either, so give up. */
- cplusplus_error (the_real_saved_arg,
- "Can't find member of namespace, "
- "class, struct, or union named \"%s\"\n",
- copy);
-}
+struct decode_compound_collector
+{
+ /* The result vector. */
+ VEC (symbolp) *symbols;
+
+ /* A hash table of all symbols we found. We use this to avoid
+ adding any symbol more than once. */
+ htab_t unique_syms;
+};
+
+/* A callback for iterate_over_symbols that is used by
+ lookup_prefix_sym to collect type symbols. */
+
+static int
+collect_one_symbol (struct symbol *sym, void *d)
+{
+ struct decode_compound_collector *collector = d;
+ void **slot;
+ struct type *t;
+
+ if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+ return 1;
+
+ t = SYMBOL_TYPE (sym);
+ CHECK_TYPEDEF (t);
+ if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION
+ && TYPE_CODE (t) != TYPE_CODE_NAMESPACE)
+ return 1;
-/* Next come some helper functions for decode_compound. */
+ slot = htab_find_slot (collector->unique_syms, sym, INSERT);
+ if (!*slot)
+ {
+ *slot = sym;
+ VEC_safe_push (symbolp, collector->symbols, sym);
+ }
+
+ return 1;
+}
/* Return the symbol corresponding to the substring of *ARGPTR ending
at P, allowing whitespace. Also, advance *ARGPTR past the symbol
name in question, the compound object separator ("::" or "."), and
whitespace. Note that *ARGPTR is changed whether or not the
- lookup_symbol call finds anything (i.e we return NULL). As an
+ this call finds anything (i.e we return NULL). As an
example, say ARGPTR is "AAA::inA::fun" and P is "::inA::fun". */
-static struct symbol *
-lookup_prefix_sym (char **argptr, char *p, struct symtab *file_symtab)
+static VEC (symbolp) *
+lookup_prefix_sym (char **argptr, char *p, VEC (symtab_p) *file_symtabs,
+ char **class_name)
{
char *p1;
char *copy;
- struct symbol *sym;
+ int ix;
+ struct symtab *elt;
+ struct decode_compound_collector collector;
+ struct cleanup *outer;
+ struct cleanup *cleanup;
+ struct block *search_block;
/* Extract the class name. */
p1 = p;
while (p != *argptr && p[-1] == ' ')
--p;
- copy = (char *) alloca (p - *argptr + 1);
+ copy = (char *) xmalloc (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = 0;
+ *class_name = copy;
+ outer = make_cleanup (xfree, copy);
/* Discard the class name from the argptr. */
p = p1 + (p1[0] == ':' ? 2 : 1);
- while (*p == ' ' || *p == '\t')
- p++;
+ p = skip_spaces (p);
*argptr = p;
/* At this point p1->"::inA::fun", p->"inA::fun" copy->"AAA",
argptr->"inA::fun". */
- sym = lookup_symbol (copy, get_search_block (file_symtab), STRUCT_DOMAIN, 0);
- if (sym == NULL)
- {
- /* Typedefs are in VAR_DOMAIN so the above symbol lookup will
- fail when the user attempts to lookup a method of a class
- via a typedef'd name (NOT via the class's name, which is already
- handled in symbol_matches_domain). So try the lookup again
- using VAR_DOMAIN (where typedefs live) and double-check that we
- found a struct/class type. */
- struct symbol *s = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
+ collector.symbols = NULL;
+ make_cleanup (VEC_cleanup (symbolp), &collector.symbols);
- if (s != NULL)
- {
- struct type *t = SYMBOL_TYPE (s);
+ collector.unique_syms = htab_create_alloc (1, htab_hash_pointer,
+ htab_eq_pointer, NULL,
+ xcalloc, xfree);
+ cleanup = make_cleanup_htab_delete (collector.unique_syms);
- CHECK_TYPEDEF (t);
- if (TYPE_CODE (t) == TYPE_CODE_STRUCT)
- return s;
+ for (ix = 0; VEC_iterate (symtab_p, file_symtabs, ix, elt); ++ix)
+ {
+ if (elt == NULL)
+ {
+ iterate_over_all_matching_symtabs (copy, STRUCT_DOMAIN,
+ collect_one_symbol, &collector,
+ NULL);
+ iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
+ collect_one_symbol, &collector,
+ NULL);
+ }
+ else
+ {
+ struct block *search_block;
+
+ /* Program spaces that are executing startup should have
+ been filtered out earlier. */
+ gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
+ set_current_program_space (SYMTAB_PSPACE (elt));
+ search_block = get_search_block (elt);
+ iterate_over_symbols (search_block, copy, STRUCT_DOMAIN,
+ collect_one_symbol, &collector);
+ iterate_over_symbols (search_block, copy, VAR_DOMAIN,
+ collect_one_symbol, &collector);
}
}
- return sym;
+ do_cleanups (cleanup);
+ discard_cleanups (outer);
+ return collector.symbols;
}
-/* This finds the method COPY in the class whose type is T and whose
- symbol is SYM_CLASS. */
+/* A qsort comparison function for symbols. The resulting order does
+ not actually matter; we just need to be able to sort them so that
+ symbols with the same program space end up next to each other. */
-static struct symtabs_and_lines
-find_method (int funfirstline, struct linespec_result *canonical,
- char *saved_arg,
- char *copy, struct type *t, struct symbol *sym_class,
- struct symtab *file_symtab)
+static int
+compare_symbols (const void *a, const void *b)
{
- struct symtabs_and_lines values;
- struct symbol *sym = NULL;
- int i1; /* Counter for the symbol array. */
- struct symbol **sym_arr = alloca (total_number_of_methods (t)
- * sizeof (struct symbol *));
+ struct symbol * const *sa = a;
+ struct symbol * const *sb = b;
+ uintptr_t uia, uib;
- /* Find all methods with a matching name, and put them in
- sym_arr. */
+ uia = (uintptr_t) SYMTAB_PSPACE (SYMBOL_SYMTAB (*sa));
+ uib = (uintptr_t) SYMTAB_PSPACE (SYMBOL_SYMTAB (*sb));
- i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr,
- file_symtab);
+ if (uia < uib)
+ return -1;
+ if (uia > uib)
+ return 1;
+
+ uia = (uintptr_t) *sa;
+ uib = (uintptr_t) *sb;
+
+ if (uia < uib)
+ return -1;
+ if (uia > uib)
+ return 1;
+
+ return 0;
+}
- /* If we were given a specific overload instance in COPY, defer the field
- acceptance till the strcmp_iw verification below, even if we found just
- a single field with that name. */
- if (i1 == 1 && strchr (copy, '(') == NULL)
+/* Look for all the matching instances of each symbol in NAMES. Only
+ instances from PSPACE are considered; other program spaces are
+ handled by our caller. If PSPACE is NULL, then all program spaces
+ are considered. Results are stored into INFO. */
+
+static void
+add_all_symbol_names_from_pspace (struct collect_info *info,
+ struct program_space *pspace,
+ VEC (const_char_ptr) *names)
+{
+ int ix;
+ const char *iter;
+
+ for (ix = 0; VEC_iterate (const_char_ptr, names, ix, iter); ++ix)
+ add_matching_symbols_to_info (iter, info, pspace);
+}
+
+static void
+find_superclass_methods (VEC (typep) *superclasses,
+ const char *name,
+ VEC (const_char_ptr) **result_names)
+{
+ int old_len = VEC_length (const_char_ptr, *result_names);
+ VEC (typep) *iter_classes;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+
+ iter_classes = superclasses;
+ while (1)
{
- /* There is exactly one field with that name. */
- sym = sym_arr[0];
+ VEC (typep) *new_supers = NULL;
+ int ix;
+ struct type *t;
- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- values.sals[0] = find_function_start_sal (sym,
- funfirstline);
- }
- else
+ make_cleanup (VEC_cleanup (typep), &new_supers);
+ for (ix = 0; VEC_iterate (typep, iter_classes, ix, t); ++ix)
+ find_methods (t, name, result_names, &new_supers);
+
+ if (VEC_length (const_char_ptr, *result_names) != old_len
+ || VEC_empty (typep, new_supers))
+ break;
+
+ iter_classes = new_supers;
+ }
+
+ do_cleanups (cleanup);
+}
+
+/* This finds the method COPY in the class whose type is given by one
+ of the symbols in SYM_CLASSES. */
+
+static struct symtabs_and_lines
+find_method (struct linespec_state *self, char *saved_arg,
+ char *copy, const char *class_name, VEC (symbolp) *sym_classes)
+{
+ char *canon;
+ struct symbol *sym;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+ int ix;
+ int last_result_len;
+ VEC (typep) *superclass_vec;
+ VEC (const_char_ptr) *result_names;
+ struct collect_info info;
+ char *name_iter;
+
+ /* NAME is typed by the user: it needs to be canonicalized before
+ searching the symbol tables. */
+ canon = cp_canonicalize_string_no_typedefs (copy);
+ if (canon != NULL)
+ {
+ copy = canon;
+ make_cleanup (xfree, copy);
+ }
+
+ /* Sort symbols so that symbols with the same program space are next
+ to each other. */
+ qsort (VEC_address (symbolp, sym_classes),
+ VEC_length (symbolp, sym_classes),
+ sizeof (symbolp),
+ compare_symbols);
+
+ info.state = self;
+ info.result.sals = NULL;
+ info.result.nelts = 0;
+ info.objfile = NULL;
+
+ /* Iterate over all the types, looking for the names of existing
+ methods matching COPY. If we cannot find a direct method in a
+ given program space, then we consider inherited methods; this is
+ not ideal (ideal would be to respect C++ hiding rules), but it
+ seems good enough and is what GDB has historically done. We only
+ need to collect the names because later we find all symbols with
+ those names. This loop is written in a somewhat funny way
+ because we collect data across the program space before deciding
+ what to do. */
+ superclass_vec = NULL;
+ make_cleanup (VEC_cleanup (typep), &superclass_vec);
+ result_names = NULL;
+ make_cleanup (VEC_cleanup (const_char_ptr), &result_names);
+ last_result_len = 0;
+ for (ix = 0; VEC_iterate (symbolp, sym_classes, ix, sym); ++ix)
+ {
+ struct type *t;
+ struct program_space *pspace;
+
+ /* Program spaces that are executing startup should have
+ been filtered out earlier. */
+ gdb_assert (!SYMTAB_PSPACE (SYMBOL_SYMTAB (sym))->executing_startup);
+ pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ set_current_program_space (pspace);
+ t = check_typedef (SYMBOL_TYPE (sym));
+ find_methods (t, copy, &result_names, &superclass_vec);
+
+ /* Handle all items from a single program space at once; and be
+ sure not to miss the last batch. */
+ if (ix == VEC_length (symbolp, sym_classes) - 1
+ || (pspace
+ != SYMTAB_PSPACE (SYMBOL_SYMTAB (VEC_index (symbolp, sym_classes,
+ ix + 1)))))
{
- values.sals = NULL;
- values.nelts = 0;
+ /* If we did not find a direct implementation anywhere in
+ this program space, consider superclasses. */
+ if (VEC_length (const_char_ptr, result_names) == last_result_len)
+ find_superclass_methods (superclass_vec, copy, &result_names);
+
+ /* We have a list of candidate symbol names, so now we
+ iterate over the symbol tables looking for all
+ matches in this pspace. */
+ add_all_symbol_names_from_pspace (&info, pspace, result_names);
+
+ VEC_truncate (typep, superclass_vec, 0);
+ last_result_len = VEC_length (const_char_ptr, result_names);
}
- return values;
}
- if (i1 > 0)
+
+ if (info.result.nelts > 0)
{
- /* If we were given a specific overload instance, use that
- (or error if no matches were found). Otherwise ask the user
- which one to use. */
- if (strchr (copy, '('))
+ if (self->canonical)
{
- int i;
- char *name;
- char *canon;
- struct cleanup *cleanup;
-
- /* Construct the proper search name based on SYM_CLASS and COPY.
- SAVED_ARG may contain a valid name, but that name might not be
- what is actually stored in the symbol table. For example,
- if SAVED_ARG (and SYM_CLASS) were found via an import
- ("using namespace" in C++), then the physname of
- SYM_CLASS ("A::myclass") may not be the same as SAVED_ARG
- ("myclass"). */
- name = xmalloc (strlen (SYMBOL_NATURAL_NAME (sym_class))
- + 2 /* "::" */ + strlen (copy) + 1);
- strcpy (name, SYMBOL_NATURAL_NAME (sym_class));
- strcat (name, "::");
- strcat (name, copy);
- canon = cp_canonicalize_string_no_typedefs (name);
- if (canon != NULL)
- {
- xfree (name);
- name = canon;
- }
- cleanup = make_cleanup (xfree, name);
-
- for (i = 0; i < i1; ++i)
- {
- if (strcmp_iw (name, SYMBOL_LINKAGE_NAME (sym_arr[i])) == 0)
- {
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- values.sals[0] = find_function_start_sal (sym_arr[i],
- funfirstline);
- do_cleanups (cleanup);
- return values;
- }
- }
-
- cplusplus_error (saved_arg, _("the class `%s' does not have "
- "any method instance named %s"),
- SYMBOL_PRINT_NAME (sym_class), copy);
+ self->canonical->pre_expanded = 1;
+ if (self->user_filename)
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", self->user_filename, saved_arg);
+ else
+ self->canonical->addr_string = xstrdup (saved_arg);
}
- return decode_line_2 (sym_arr, i1, funfirstline, canonical);
+ do_cleanups (cleanup);
+
+ return info.result;
}
+
+ if (copy[0] == '~')
+ cplusplus_error (saved_arg,
+ "the class `%s' does not have destructor defined\n",
+ class_name);
else
+ cplusplus_error (saved_arg,
+ "the class %s does not have any method named %s\n",
+ class_name, copy);
+}
+
+\f
+
+/* This object is used when collecting all matching symtabs. */
+
+struct symtab_collector
+{
+ /* The result vector of symtabs. */
+ VEC (symtab_p) *symtabs;
+
+ /* This is used to ensure the symtabs are unique. */
+ htab_t symtab_table;
+};
+
+/* Callback for iterate_over_symtabs. */
+
+static int
+add_symtabs_to_list (struct symtab *symtab, void *d)
+{
+ struct symtab_collector *data = d;
+ void **slot;
+
+ slot = htab_find_slot (data->symtab_table, symtab, INSERT);
+ if (!*slot)
{
- if (copy[0] == '~')
- cplusplus_error (saved_arg,
- "the class `%s' does not have destructor defined\n",
- SYMBOL_PRINT_NAME (sym_class));
- else
- cplusplus_error (saved_arg,
- "the class %s does not have any method named %s\n",
- SYMBOL_PRINT_NAME (sym_class), copy);
+ *slot = symtab;
+ VEC_safe_push (symtab_p, data->symtabs, symtab);
}
+
+ return 0;
}
-\f
+/* Given a file name, return a VEC of all matching symtabs. */
+
+static VEC (symtab_p) *
+collect_symtabs_from_filename (const char *file)
+{
+ struct symtab_collector collector;
+ struct cleanup *cleanups;
+ struct program_space *pspace;
+
+ collector.symtabs = NULL;
+ collector.symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
+ NULL);
+ cleanups = make_cleanup_htab_delete (collector.symtab_table);
-/* Return the symtab associated to the filename given by the substring
- of *ARGPTR ending at P, and advance ARGPTR past that filename. */
+ /* Find that file's data. */
+ ALL_PSPACES (pspace)
+ {
+ if (pspace->executing_startup)
+ continue;
-static struct symtab *
-symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
+ set_current_program_space (pspace);
+ iterate_over_symtabs (file, add_symtabs_to_list, &collector);
+ }
+
+ do_cleanups (cleanups);
+ return collector.symtabs;
+}
+
+/* Return all the symtabs associated to the filename given by the
+ substring of *ARGPTR ending at P, and advance ARGPTR past that
+ filename. */
+
+static VEC (symtab_p) *
+symtabs_from_filename (char **argptr, char *p, int is_quote_enclosed,
+ char **user_filename)
{
char *p1;
char *copy;
- struct symtab *file_symtab;
+ struct cleanup *outer;
+ VEC (symtab_p) *result;
p1 = p;
while (p != *argptr && p[-1] == ' ')
--p;
if ((*p == '"') && is_quote_enclosed)
--p;
- copy = (char *) alloca (p - *argptr + 1);
+ copy = xmalloc (p - *argptr + 1);
+ outer = make_cleanup (xfree, copy);
memcpy (copy, *argptr, p - *argptr);
/* It may have the ending quote right after the file name. */
if ((is_quote_enclosed && copy[p - *argptr - 1] == '"')
@@ -1834,9 +2140,9 @@ symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
else
copy[p - *argptr] = 0;
- /* Find that file's data. */
- file_symtab = lookup_symtab (copy);
- if (file_symtab == 0)
+ result = collect_symtabs_from_filename (copy);
+
+ if (VEC_empty (symtab_p, result))
{
if (!have_full_symbols () && !have_partial_symbols ())
throw_error (NOT_FOUND_ERROR,
@@ -1847,31 +2153,47 @@ symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
/* Discard the file name from the arg. */
if (*p1 == '\0')
- return file_symtab;
- p = p1 + 1;
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
+ *argptr = p1;
+ else
+ *argptr = skip_spaces (p1 + 1);
+
+ discard_cleanups (outer);
+ *user_filename = copy;
+ return result;
+}
+
+/* A callback used by iterate_over_all_matching_symtabs that collects
+ symbols for find_function_symbols. */
+
+static int
+collect_function_symbols (struct symbol *sym, void *arg)
+{
+ VEC (symbolp) **syms = arg;
- return file_symtab;
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ VEC_safe_push (symbolp, *syms, sym);
+
+ return 1;
}
/* Look up a function symbol in *ARGPTR. If found, advance *ARGPTR
and return the symbol. If not found, return NULL. */
-static struct symbol *
-find_function_symbol (char **argptr, char *p, int is_quote_enclosed)
+static VEC (symbolp) *
+find_function_symbols (char **argptr, char *p, int is_quote_enclosed,
+ char **user_function)
{
char *p1;
char *copy;
- struct symbol *function_symbol;
+ VEC (symbolp) *result = NULL;
p1 = p;
while (p != *argptr && p[-1] == ' ')
--p;
if ((*p == '"') && is_quote_enclosed)
--p;
- copy = (char *) alloca (p - *argptr + 1);
+ copy = (char *) xmalloc (p - *argptr + 1);
+ *user_function = copy;
memcpy (copy, *argptr, p - *argptr);
/* It may have the ending quote right after the file name. */
if ((is_quote_enclosed && copy[p - *argptr - 1] == '"')
@@ -1880,34 +2202,128 @@ find_function_symbol (char **argptr, char *p, int is_quote_enclosed)
else
copy[p - *argptr] = 0;
- function_symbol = lookup_symbol (copy, get_selected_block (0),
- VAR_DOMAIN, 0);
- if (!function_symbol || SYMBOL_CLASS (function_symbol) != LOC_BLOCK)
- return NULL;
+ iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
+ collect_function_symbols, &result, NULL);
- /* Discard the file name from the arg. */
- p = p1 + 1;
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
+ /* If looking up the given name failed, try using the current
+ language to look up a symbol. This may augment the search. If a
+ symbol is found this way, repeat the iteration, but using the
+ discovered name. */
+ if (VEC_empty (symbolp, result)
+ && current_language->la_language == language_ada)
+ {
+ struct symbol *function_symbol;
- return function_symbol;
+ function_symbol = lookup_symbol (copy, get_selected_block (0),
+ VAR_DOMAIN, 0);
+ if (function_symbol && SYMBOL_CLASS (function_symbol) == LOC_BLOCK)
+ {
+ xfree (copy);
+ copy = xstrdup (SYMBOL_SEARCH_NAME (function_symbol));
+ *user_function = copy;
+ iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
+ collect_function_symbols,
+ &result, NULL);
+ }
+ }
+
+ if (VEC_empty (symbolp, result))
+ VEC_free (symbolp, result);
+ else
+ {
+ /* Discard the file name from the arg. */
+ *argptr = skip_spaces (p1 + 1);
+ }
+
+ return result;
}
\f
+/* A helper for decode_all_digits that handles the 'list_mode' case. */
+
+static void
+decode_digits_line_mode (struct linespec_state *self,
+ struct symtabs_and_lines *values,
+ struct symtab_and_line val)
+{
+ int ix;
+ struct symtab *elt;
+
+ gdb_assert (self->list_mode);
+
+ for (ix = 0; VEC_iterate (symtab_p, self->file_symtabs, ix, elt); ++ix)
+ {
+ /* The logic above should ensure this. */
+ gdb_assert (elt != NULL);
+
+ set_current_program_space (SYMTAB_PSPACE (elt));
+
+ /* Simplistic search just for the list command. */
+ val.symtab = find_line_symtab (elt, val.line, NULL, NULL);
+ if (val.symtab == NULL)
+ val.symtab = elt;
+ val.pspace = SYMTAB_PSPACE (elt);
+ val.pc = 0;
+ val.explicit_line = 1;
+
+ add_sal_to_sals (self, values, &val, NULL);
+ }
+}
+
+/* A helper for decode_all_digits that iterates over the symtabs,
+ adding lines to the VEC. */
+
+static void
+decode_digits_ordinary (struct linespec_state *self,
+ int line,
+ struct symtabs_and_lines *sals,
+ struct linetable_entry **best_entry)
+{
+ int ix;
+ struct symtab *elt;
+
+ for (ix = 0; VEC_iterate (symtab_p, self->file_symtabs, ix, elt); ++ix)
+ {
+ int i;
+ VEC (CORE_ADDR) *pcs;
+ CORE_ADDR pc;
+
+ /* The logic above should ensure this. */
+ gdb_assert (elt != NULL);
+
+ set_current_program_space (SYMTAB_PSPACE (elt));
+
+ pcs = find_pcs_for_symtab_line (elt, line, best_entry);
+ for (i = 0; VEC_iterate (CORE_ADDR, pcs, i, pc); ++i)
+ {
+ struct symtab_and_line sal;
+
+ init_sal (&sal);
+ sal.pspace = SYMTAB_PSPACE (elt);
+ sal.symtab = elt;
+ sal.line = line;
+ sal.pc = pc;
+ add_sal_to_sals_basic (sals, &sal);
+ }
+
+ VEC_free (CORE_ADDR, pcs);
+ }
+}
+
/* This decodes a line where the argument is all digits (possibly
preceded by a sign). Q should point to the end of those digits;
the other arguments are as usual. */
static struct symtabs_and_lines
-decode_all_digits (char **argptr, struct symtab *default_symtab,
- int default_line, struct linespec_result *canonical,
- struct symtab *file_symtab, char *q)
-
+decode_all_digits (struct linespec_state *self,
+ char **argptr,
+ char *q)
{
struct symtabs_and_lines values;
struct symtab_and_line val;
+ int use_default = 0;
+ char *saved_arg = *argptr;
enum sign
{
@@ -1915,12 +2331,9 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
}
sign = none;
- /* We might need a canonical line spec if no file was specified. */
- int need_canonical = (file_symtab == NULL) ? 1 : 0;
-
init_sal (&val);
-
- val.pspace = current_program_space;
+ values.sals = NULL;
+ values.nelts = 0;
/* This is where we need to make sure that we have good defaults.
We must guarantee that this section of code is never executed
@@ -1928,11 +2341,19 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
set_default_source_symtab_and_line uses
select_source_symtab that calls us with such an argument. */
- if (file_symtab == 0 && default_symtab == 0)
+ if (VEC_length (symtab_p, self->file_symtabs) == 1
+ && VEC_index (symtab_p, self->file_symtabs, 0) == NULL)
{
+ set_current_program_space (self->program_space);
+
/* Make sure we have at least a default source file. */
set_default_source_symtab_and_line ();
- initialize_defaults (&default_symtab, &default_line);
+ initialize_defaults (&self->default_symtab, &self->default_line);
+ VEC_pop (symtab_p, self->file_symtabs);
+ VEC_free (symtab_p, self->file_symtabs);
+ self->file_symtabs
+ = collect_symtabs_from_filename (self->default_symtab->filename);
+ use_default = 1;
}
if (**argptr == '+')
@@ -1945,14 +2366,14 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
case plus:
if (q == *argptr)
val.line = 5;
- if (file_symtab == 0)
- val.line = default_line + val.line;
+ if (use_default)
+ val.line = self->default_line + val.line;
break;
case minus:
if (q == *argptr)
val.line = 15;
- if (file_symtab == 0)
- val.line = default_line - val.line;
+ if (use_default)
+ val.line = self->default_line - val.line;
else
val.line = 1;
break;
@@ -1960,28 +2381,109 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
break; /* No need to adjust val.line. */
}
- while (*q == ' ' || *q == '\t')
- q++;
- *argptr = q;
- if (file_symtab == 0)
- file_symtab = default_symtab;
-
- /* It is possible that this source file has more than one symtab,
- and that the new line number specification has moved us from the
- default (in file_symtab) to a new one. */
- val.symtab = find_line_symtab (file_symtab, val.line, NULL, NULL);
- if (val.symtab == 0)
- val.symtab = file_symtab;
-
- val.pspace = SYMTAB_PSPACE (val.symtab);
- val.pc = 0;
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = val;
- values.nelts = 1;
- if (need_canonical)
- build_canonical_line_spec (values.sals, NULL, canonical);
- values.sals[0].explicit_line = 1;
+ *argptr = skip_spaces (q);
+
+ if (self->list_mode)
+ decode_digits_line_mode (self, &values, val);
+ else
+ {
+ struct linetable_entry *best_entry = NULL;
+ int *filter;
+ struct block **blocks;
+ struct cleanup *cleanup;
+ struct symtabs_and_lines intermediate_results;
+ int i, j;
+
+ intermediate_results.sals = NULL;
+ intermediate_results.nelts = 0;
+
+ decode_digits_ordinary (self, val.line, &intermediate_results,
+ &best_entry);
+ if (intermediate_results.nelts == 0 && best_entry != NULL)
+ decode_digits_ordinary (self, best_entry->line, &intermediate_results,
+ &best_entry);
+
+ cleanup = make_cleanup (xfree, intermediate_results.sals);
+
+ /* For optimized code, compiler can scatter one source line
+ accross disjoint ranges of PC values, even when no duplicate
+ functions or inline functions are involved. For example,
+ 'for (;;)' inside non-template non-inline non-ctor-or-dtor
+ function can result in two PC ranges. In this case, we don't
+ want to set breakpoint on first PC of each range. To filter
+ such cases, we use containing blocks -- for each PC found
+ above we see if there are other PCs that are in the same
+ block. If yes, the other PCs are filtered out. */
+
+ filter = xmalloc (intermediate_results.nelts * sizeof (int));
+ make_cleanup (xfree, filter);
+ blocks = xmalloc (intermediate_results.nelts * sizeof (struct block *));
+ make_cleanup (xfree, blocks);
+
+ for (i = 0; i < intermediate_results.nelts; ++i)
+ {
+ set_current_program_space (intermediate_results.sals[i].pspace);
+
+ filter[i] = 1;
+ blocks[i] = block_for_pc_sect (intermediate_results.sals[i].pc,
+ intermediate_results.sals[i].section);
+ }
+
+ for (i = 0; i < intermediate_results.nelts; ++i)
+ {
+ if (blocks[i] != NULL)
+ for (j = i + 1; j < intermediate_results.nelts; ++j)
+ {
+ if (blocks[j] == blocks[i])
+ {
+ filter[j] = 0;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < intermediate_results.nelts; ++i)
+ if (filter[i])
+ {
+ struct symbol *sym = (blocks[i]
+ ? block_containing_function (blocks[i])
+ : NULL);
+
+ /* Make sure the line matches the request, not what was
+ found. */
+ skip_prologue_sal (&intermediate_results.sals[i]);
+ intermediate_results.sals[i].line = val.line;
+ add_sal_to_sals (self, &values, &intermediate_results.sals[i],
+ sym ? SYMBOL_NATURAL_NAME (sym) : NULL);
+ }
+
+ do_cleanups (cleanup);
+ }
+
+ if (values.nelts == 0)
+ {
+ if (self->user_filename)
+ throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."),
+ val.line, self->user_filename);
+ else
+ throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."),
+ val.line);
+ }
+
+ if (self->canonical)
+ {
+ char *copy = savestring (saved_arg, q - saved_arg);
+
+ self->canonical->pre_expanded = 1;
+ gdb_assert (self->user_filename || use_default);
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", (self->user_filename
+ ? self->user_filename
+ : self->default_symtab->filename),
+ copy);
+ xfree (copy);
+ }
+
return values;
}
@@ -1990,17 +2492,17 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
/* Decode a linespec starting with a dollar sign. */
static struct symtabs_and_lines
-decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
- struct linespec_result *canonical, struct symtab *file_symtab)
+decode_dollar (struct linespec_state *self, char *copy)
{
LONGEST valx;
int index = 0;
- int need_canonical = 0;
struct symtabs_and_lines values;
struct symtab_and_line val;
char *p;
struct symbol *sym;
struct minimal_symbol *msymbol;
+ int ix;
+ struct symtab *elt;
p = (copy[1] == '$') ? copy + 2 : copy + 1;
while (*p >= '0' && *p <= '9')
@@ -2022,19 +2524,18 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
/* Not all digits -- may be user variable/function or a
convenience variable. */
- /* Look up entire name as a symbol first. */
- sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
- file_symtab = (struct symtab *) NULL;
- need_canonical = 1;
- /* Symbol was found --> jump to normal symbol processing. */
- if (sym)
- return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL);
+ volatile struct gdb_exception exc;
+
+ TRY_CATCH (exc, RETURN_MASK_ERROR)
+ {
+ values = decode_variable (self, copy);
+ }
+
+ if (exc.reason == 0)
+ return values;
- /* If symbol was not found, look in minimal symbol tables. */
- msymbol = lookup_minimal_symbol (copy, NULL, NULL);
- /* Min symbol was found --> jump to minsym processing. */
- if (msymbol)
- return minsym_found (funfirstline, msymbol);
+ if (exc.error != NOT_FOUND_ERROR)
+ throw_exception (exc);
/* Not a user variable or function -- must be convenience variable. */
if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx))
@@ -2044,18 +2545,37 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
init_sal (&val);
- /* Either history value or convenience value from above, in valx. */
- val.symtab = file_symtab ? file_symtab : default_symtab;
- val.line = valx;
- val.pc = 0;
- val.pspace = current_program_space;
+ values.sals = NULL;
+ values.nelts = 0;
- values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
- values.sals[0] = val;
- values.nelts = 1;
+ for (ix = 0; VEC_iterate (symtab_p, self->file_symtabs, ix, elt); ++ix)
+ {
+ if (elt == NULL)
+ {
+ elt = self->default_symtab;
+ set_current_program_space (self->program_space);
+ }
+ else
+ set_current_program_space (SYMTAB_PSPACE (elt));
+
+ /* Either history value or convenience value from above, in valx. */
+ val.symtab = elt;
+ val.line = valx;
+ val.pc = 0;
+ val.pspace = elt ? SYMTAB_PSPACE (elt) : current_program_space;
- if (need_canonical)
- build_canonical_line_spec (values.sals, NULL, canonical);
+ add_sal_to_sals (self, &values, &val, NULL);
+ }
+
+ if (self->canonical)
+ {
+ self->canonical->pre_expanded = 1;
+ if (self->user_filename)
+ self->canonical->addr_string = xstrprintf ("%s:%s",
+ self->user_filename, copy);
+ else
+ self->canonical->addr_string = xstrdup (copy);
+ }
return values;
}
@@ -2064,7 +2584,7 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
/* A helper for decode_line_1 that tries to find a label. The label
is searched for in the current block.
- FUNCTION_SYMBOL is the enclosing function; or NULL if none
+ FUNCTION_SYMBOLS is a list of the enclosing functions; or NULL if none
specified.
COPY is the name of the label to find.
CANONICAL is the same as the "canonical" argument to decode_line_1.
@@ -2073,78 +2593,308 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
This function returns 1 if a label was found, 0 otherwise. */
static int
-decode_label (struct symbol *function_symbol, char *copy,
- struct linespec_result *canonical,
+decode_label (struct linespec_state *self,
+ VEC (symbolp) *function_symbols, char *copy,
struct symtabs_and_lines *result)
{
- struct symbol *sym;
- struct block *block;
+ struct symbol *fn_sym;
+ int ix;
- if (function_symbol)
- block = SYMBOL_BLOCK_VALUE (function_symbol);
- else
+ if (function_symbols == NULL)
{
- block = get_selected_block (0);
+ struct block *block;
+ struct symbol *sym;
+ struct symtab_and_line sal;
+ struct symtabs_and_lines values;
+
+ values.nelts = 0;
+ values.sals = NULL;
+
+ set_current_program_space (self->program_space);
+ block = get_search_block (NULL);
+
for (;
block && !BLOCK_FUNCTION (block);
block = BLOCK_SUPERBLOCK (block))
;
if (!block)
return 0;
- function_symbol = BLOCK_FUNCTION (block);
+ fn_sym = BLOCK_FUNCTION (block);
+
+ sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0);
+
+ if (sym == NULL)
+ return 0;
+
+ symbol_to_sal (&sal, self->funfirstline, sym);
+ add_sal_to_sals (self, &values, &sal,
+ SYMBOL_NATURAL_NAME (fn_sym));
+
+ if (self->canonical)
+ {
+ self->canonical->special_display = 1;
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", SYMBOL_NATURAL_NAME (fn_sym),
+ copy);
+ }
+
+ *result = values;
+
+ return 1;
+ }
+
+ result->sals = NULL;
+ result->nelts = 0;
+
+ for (ix = 0; VEC_iterate (symbolp, function_symbols, ix, fn_sym); ++ix)
+ {
+ struct block *block;
+ struct symbol *sym;
+
+ set_current_program_space (SYMTAB_PSPACE (SYMBOL_SYMTAB (fn_sym)));
+ block = SYMBOL_BLOCK_VALUE (fn_sym);
+ sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0);
+
+ if (sym != NULL)
+ {
+ struct symtab_and_line sal;
+ char *symname;
+
+ symbol_to_sal (&sal, self->funfirstline, sym);
+ symname = xstrprintf ("%s:%s",
+ SYMBOL_NATURAL_NAME (fn_sym),
+ SYMBOL_NATURAL_NAME (sym));
+ add_sal_to_sals (self, result, &sal, symname);
+ xfree (symname);
+ }
}
- sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0);
+ if (self->canonical && result->nelts > 0)
+ {
+ self->canonical->pre_expanded = 1;
+ self->canonical->special_display = 1;
+
+ gdb_assert (self->user_function);
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", self->user_function, copy);
+ }
- if (sym != NULL)
- *result = symbol_found (0, canonical, copy, sym, NULL, function_symbol);
+ return result->nelts > 0;
+}
+
+/* A callback used to possibly add a symbol to the results. */
+
+static int
+collect_symbols (struct symbol *sym, void *data)
+{
+ struct collect_info *info = data;
+ struct symtab_and_line sal;
+
+ if ((SYMBOL_CLASS (sym) == LOC_STATIC
+ && !info->state->funfirstline
+ && !maybe_add_address (info->state->addr_set,
+ SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)),
+ SYMBOL_VALUE_ADDRESS (sym)))
+ || (SYMBOL_CLASS (sym) == LOC_BLOCK
+ && !maybe_add_address (info->state->addr_set,
+ SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)),
+ BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))))
+ {
+ /* Nothing. */
+ }
+ else if (symbol_to_sal (&sal, info->state->funfirstline, sym))
+ add_sal_to_sals (info->state, &info->result, &sal,
+ SYMBOL_NATURAL_NAME (sym));
- return sym != NULL;
+ return 1;
+}
+
+/* We've found a minimal symbol MSYMBOL to associate with our
+ linespec; add it to the result symtabs_and_lines. */
+
+static void
+minsym_found (struct linespec_state *self, struct objfile *objfile,
+ struct minimal_symbol *msymbol,
+ struct symtabs_and_lines *result)
+{
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ CORE_ADDR pc;
+ struct symtab_and_line sal;
+
+ sal = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
+ (struct obj_section *) 0, 0);
+ sal.section = SYMBOL_OBJ_SECTION (msymbol);
+
+ /* The minimal symbol might point to a function descriptor;
+ resolve it to the actual code address instead. */
+ pc = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc, ¤t_target);
+ if (pc != sal.pc)
+ sal = find_pc_sect_line (pc, NULL, 0);
+
+ if (self->funfirstline)
+ skip_prologue_sal (&sal);
+
+ add_sal_to_sals (self, result, &sal, SYMBOL_NATURAL_NAME (msymbol));
+}
+
+/* Callback for iterate_over_minimal_symbols that may add the symbol
+ to the result. */
+
+static void
+check_minsym (struct minimal_symbol *minsym, void *d)
+{
+ struct collect_info *info = d;
+
+ if (MSYMBOL_TYPE (minsym) == mst_unknown
+ || MSYMBOL_TYPE (minsym) == mst_slot_got_plt
+ || MSYMBOL_TYPE (minsym) == mst_solib_trampoline)
+ {
+ /* Reject some odd ones. */
+ }
+ else if (info->state->funfirstline
+ && MSYMBOL_TYPE (minsym) != mst_text
+ && MSYMBOL_TYPE (minsym) != mst_text_gnu_ifunc
+ && MSYMBOL_TYPE (minsym) != mst_file_text)
+ {
+ /* When FUNFIRSTLINE, only allow text symbols. */
+ }
+ else if (maybe_add_address (info->state->addr_set, info->objfile->pspace,
+ SYMBOL_VALUE_ADDRESS (minsym)))
+ minsym_found (info->state, info->objfile, minsym, &info->result);
+}
+
+/* Search minimal symbols in all objfiles for NAME. If SEARCH_PSPACE
+ is not NULL, the search is restricted to just that program
+ space. */
+
+static void
+search_minsyms_for_name (struct collect_info *info, const char *name,
+ struct program_space *search_pspace)
+{
+ struct objfile *objfile;
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ {
+ if (search_pspace != NULL && search_pspace != pspace)
+ continue;
+ if (pspace->executing_startup)
+ continue;
+
+ set_current_program_space (pspace);
+
+ ALL_OBJFILES (objfile)
+ {
+ info->objfile = objfile;
+ iterate_over_minimal_symbols (objfile, name, check_minsym, info);
+ }
+ }
+}
+
+/* A helper function to add all symbols matching NAME to INFO. If
+ PSPACE is not NULL, the search is restricted to just that program
+ space. */
+
+static void
+add_matching_symbols_to_info (const char *name,
+ struct collect_info *info,
+ struct program_space *pspace)
+{
+ int ix;
+ struct symtab *elt;
+
+ for (ix = 0; VEC_iterate (symtab_p, info->state->file_symtabs, ix, elt); ++ix)
+ {
+ struct symbol *sym;
+
+ if (elt == NULL)
+ {
+ iterate_over_all_matching_symtabs (name, VAR_DOMAIN,
+ collect_symbols, info,
+ pspace);
+ search_minsyms_for_name (info, name, pspace);
+ }
+ else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt))
+ {
+ /* Program spaces that are executing startup should have
+ been filtered out earlier. */
+ gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
+ set_current_program_space (SYMTAB_PSPACE (elt));
+ iterate_over_symbols (get_search_block (elt), name,
+ VAR_DOMAIN, collect_symbols,
+ info);
+ }
+ }
}
/* Decode a linespec that's a variable. If FILE_SYMTAB is non-NULL,
look in that symtab's static variables first. */
static struct symtabs_and_lines
-decode_variable (char *copy, int funfirstline,
- struct linespec_result *canonical,
- struct symtab *file_symtab)
+decode_variable (struct linespec_state *self, char *copy)
{
- char *name, *canon;
- struct symbol *sym;
+ struct collect_info info;
+ const char *lookup_name;
+ char *canon;
struct cleanup *cleanup;
- struct minimal_symbol *msymbol;
- name = copy;
- cleanup = make_cleanup (null_cleanup, NULL);
+ info.state = self;
+ info.result.sals = NULL;
+ info.result.nelts = 0;
+ info.objfile = NULL;
+
+ cleanup = demangle_for_lookup (copy, current_language->la_language,
+ &lookup_name);
+
canon = cp_canonicalize_string_no_typedefs (copy);
if (canon != NULL)
{
- name = canon;
- make_cleanup (xfree, name);
+ make_cleanup (xfree, canon);
+ lookup_name = canon;
}
- sym = lookup_symbol (name, get_search_block (file_symtab), VAR_DOMAIN, 0);
+ add_matching_symbols_to_info (lookup_name, &info, NULL);
- if (sym != NULL)
+ /* If looking up the given name failed, try using the current
+ language to look up a symbol. This may augment the search. If a
+ symbol is found this way, repeat the iteration, but using the
+ discovered name. */
+ if (info.result.nelts == 0 && current_language->la_language == language_ada)
{
- do_cleanups (cleanup);
- return symbol_found (funfirstline, canonical, copy, sym,
- file_symtab, NULL);
- }
+ struct symbol *sym;
- msymbol = lookup_minimal_symbol (name, NULL, NULL);
- do_cleanups (cleanup);
+ sym = lookup_symbol (lookup_name, get_selected_block (0), VAR_DOMAIN, 0);
+ if (sym)
+ {
+ copy = SYMBOL_SEARCH_NAME (sym);
+ add_matching_symbols_to_info (copy, &info, NULL);
+ }
+ }
- if (msymbol != NULL)
- return minsym_found (funfirstline, msymbol);
+ if (info.result.nelts > 0)
+ {
+ if (self->canonical)
+ {
+ self->canonical->pre_expanded = 1;
+ if (self->user_filename)
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", self->user_filename, copy);
+ else
+ self->canonical->addr_string = xstrdup (copy);
+ }
+ return info.result;
+ }
if (!have_full_symbols ()
&& !have_partial_symbols ()
&& !have_minimal_symbols ())
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. Use the \"file\" command."));
- throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy);
+ if (self->user_filename)
+ throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined in \"%s\"."),
+ copy, self->user_filename);
+ else
+ throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy);
}
@@ -2153,130 +2903,82 @@ decode_variable (char *copy, int funfirstline,
/* Now come some functions that are called from multiple places within
decode_line_1. */
-/* We've found a symbol SYM to associate with our linespec; build a
- corresponding struct symtabs_and_lines. */
-
-static struct symtabs_and_lines
-symbol_found (int funfirstline, struct linespec_result *canonical, char *copy,
- struct symbol *sym, struct symtab *file_symtab,
- struct symbol *function_symbol)
+static int
+symbol_to_sal (struct symtab_and_line *result,
+ int funfirstline, struct symbol *sym)
{
- struct symtabs_and_lines values;
-
if (SYMBOL_CLASS (sym) == LOC_BLOCK)
{
- /* Arg is the name of a function. */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = find_function_start_sal (sym, funfirstline);
- values.nelts = 1;
-
- /* Don't use the SYMBOL_LINE; if used at all it points to
- the line containing the parameters or thereabouts, not
- the first line of code. */
-
- /* We might need a canonical line spec if it is a static
- function. */
- if (file_symtab == 0)
- {
- struct blockvector *bv = BLOCKVECTOR (SYMBOL_SYMTAB (sym));
- struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-
- if (lookup_block_symbol (b, copy, VAR_DOMAIN) != NULL)
- build_canonical_line_spec (values.sals, copy, canonical);
- }
- return values;
+ *result = find_function_start_sal (sym, funfirstline);
+ return 1;
}
else
{
if (SYMBOL_CLASS (sym) == LOC_LABEL && SYMBOL_VALUE_ADDRESS (sym) != 0)
{
- /* We know its line number. */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- init_sal (&values.sals[0]);
- values.sals[0].symtab = SYMBOL_SYMTAB (sym);
- values.sals[0].line = SYMBOL_LINE (sym);
- values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym);
- values.sals[0].pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
- values.sals[0].explicit_pc = 1;
-
- if (canonical)
- {
- canonical->special_display = 1;
- canonical->canonical = xmalloc (sizeof (char *));
- canonical->canonical[0]
- = xstrprintf ("%s:%s",
- SYMBOL_NATURAL_NAME (function_symbol),
- SYMBOL_NATURAL_NAME (sym));
- }
-
- return values;
+ init_sal (result);
+ result->symtab = SYMBOL_SYMTAB (sym);
+ result->line = SYMBOL_LINE (sym);
+ result->pc = SYMBOL_VALUE_ADDRESS (sym);
+ result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ result->explicit_pc = 1;
+ return 1;
}
else if (funfirstline)
{
- /* NOT_FOUND_ERROR is not correct but it ensures COPY will be
- searched also as a minimal symbol. */
-
- throw_error (NOT_FOUND_ERROR, _("\"%s\" is not a function"), copy);
+ /* Nothing. */
}
else if (SYMBOL_LINE (sym) != 0)
{
/* We know its line number. */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- memset (&values.sals[0], 0, sizeof (values.sals[0]));
- values.sals[0].symtab = SYMBOL_SYMTAB (sym);
- values.sals[0].line = SYMBOL_LINE (sym);
- values.sals[0].pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
- return values;
+ init_sal (result);
+ result->symtab = SYMBOL_SYMTAB (sym);
+ result->line = SYMBOL_LINE (sym);
+ result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ return 1;
}
- else
- /* This can happen if it is compiled with a compiler which doesn't
- put out line numbers for variables. */
- /* FIXME: Shouldn't we just set .line and .symtab to zero
- and return? For example, "info line foo" could print
- the address. */
- error (_("Line number not known for symbol \"%s\""), copy);
}
+
+ return 0;
}
-/* We've found a minimal symbol MSYMBOL to associate with our
- linespec; build a corresponding struct symtabs_and_lines. */
+/* See the comment in linespec.h. */
-static struct symtabs_and_lines
-minsym_found (int funfirstline, struct minimal_symbol *msymbol)
+void
+init_linespec_result (struct linespec_result *lr)
{
- struct objfile *objfile = msymbol_objfile (msymbol);
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
- struct symtabs_and_lines values;
- CORE_ADDR pc;
+ memset (lr, 0, sizeof (*lr));
+}
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
- (struct obj_section *) 0, 0);
- values.sals[0].section = SYMBOL_OBJ_SECTION (msymbol);
+/* See the comment in linespec.h. */
- /* The minimal symbol might point to a function descriptor;
- resolve it to the actual code address instead. */
- pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
- values.sals[0].pc,
- ¤t_target);
- if (pc != values.sals[0].pc)
- values.sals[0] = find_pc_sect_line (pc, NULL, 0);
+void
+destroy_linespec_result (struct linespec_result *ls)
+{
+ int i;
+ struct linespec_sals *lsal;
- if (funfirstline)
- skip_prologue_sal (&values.sals[0]);
+ xfree (ls->addr_string);
+ for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i)
+ {
+ xfree (lsal->canonical);
+ xfree (lsal->sals.sals);
+ }
+ VEC_free (linespec_sals, ls->sals);
+}
- values.nelts = 1;
- return values;
+/* Cleanup function for a linespec_result. */
+
+static void
+cleanup_linespec_result (void *a)
+{
+ destroy_linespec_result (a);
}
-void
-init_linespec_result (struct linespec_result *lr)
+/* See the comment in linespec.h. */
+
+struct cleanup *
+make_cleanup_destroy_linespec_result (struct linespec_result *ls)
{
- memset (lr, 0, sizeof (*lr));
+ return make_cleanup (cleanup_linespec_result, ls);
}
diff --git a/gdb/linespec.h b/gdb/linespec.h
index 3c86af3..401158c 100644
--- a/gdb/linespec.h
+++ b/gdb/linespec.h
@@ -20,8 +20,44 @@
struct symtab;
+#include "vec.h"
+
+/* Flags to pass to decode_line_1 and decode_line_full. */
+
+enum decode_line_flags
+ {
+ /* Set this flag if you want the resulting SALs to describe the
+ first line of indicated functions. */
+ DECODE_LINE_FUNFIRSTLINE = 1,
+
+ /* Set this flag if you want "list mode". In this mode, a
+ FILE:LINE linespec will always return a result, and such
+ linespecs will not be expanded to all matches. */
+ DECODE_LINE_LIST_MODE = 2
+ };
+
+/* decode_line_full returns a vector of these. */
+
+struct linespec_sals
+{
+ /* This is the linespec corresponding to the sals contained in this
+ object. It can be passed as the FILTER argument to future calls
+ to decode_line_full. This is freed by
+ destroy_linespec_result. */
+ char *canonical;
+
+ /* Sals. The 'sals' field is destroyed by
+ destroy_linespec_result. */
+ struct symtabs_and_lines sals;
+};
+
+typedef struct linespec_sals linespec_sals;
+DEF_VEC_O (linespec_sals);
+
/* An instance of this may be filled in by decode_line_1. The caller
- must call init_linespec_result to initialize it. */
+ must call init_linespec_result to initialize it and
+ destroy_linespec_result to destroy it. The caller must make copies
+ of any data that it needs to keep. */
struct linespec_result
{
@@ -30,22 +66,78 @@ struct linespec_result
display mechanism would do the wrong thing. */
int special_display;
- /* If non-NULL, an array of canonical names for returned
- symtab_and_line objects. The array has as many elements as the
- `nelts' field in the symtabs_and_line returned by decode_line_1.
- An element in the array may be NULL. The array and each non-NULL
- element in it are allocated with xmalloc and must be freed by the
- caller. */
- char **canonical;
+ /* If non-zero, the linespec result should be considered to be a
+ "pre-expanded" multi-location linespec. A pre-expanded linespec
+ holds all matching locations in a single linespec_sals
+ object. */
+ int pre_expanded;
+
+ /* If PRE_EXPANDED is non-zero, this is set to the linespec entered
+ by the user. This will be freed by destroy_linespec_result. */
+ char *addr_string;
+
+ /* The sals. The vector will be freed by
+ destroy_linespec_result. */
+ VEC (linespec_sals) *sals;
};
/* Initialize a linespec_result. */
extern void init_linespec_result (struct linespec_result *);
+/* Destroy a linespec_result. */
+
+extern void destroy_linespec_result (struct linespec_result *);
+
+/* Return a cleanup that destroys a linespec_result. */
+
+extern struct cleanup *
+ make_cleanup_destroy_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);
+ decode_line_1 (char **argptr, int flags,
+ struct symtab *default_symtab, int default_line);
+
+/* Parse *ARGPTR as a linespec and return results. This is the "full"
+ interface to this module, which handles multiple results
+ properly.
+
+ For FLAGS, see decode_line_flags. DECODE_LINE_LIST_MODE is not
+ valid for this function.
+
+ DEFAULT_SYMTAB and DEFAULT_LINE describe the default location.
+ DEFAULT_SYMTAB can be NULL, in which case the current symtab and
+ line are used.
+
+ CANONICAL is where the results are stored. It must not be NULL.
+
+ SELECT_MODE must be one of the multiple_symbols_* constants, or
+ NULL. It determines how multiple results will be handled. If
+ NULL, the appropriate CLI value will be used.
+
+ FILTER can either be NULL or a string holding a canonical name.
+ This is only valid when SELECT_MODE is multiple_symbols_all.
+
+ Multiple results are handled differently depending on the
+ arguments:
+
+ . With multiple_symbols_cancel, an exception is thrown.
+
+ . With multiple_symbols_ask, a menu is presented to the user. The
+ user may select none, in which case an exception is thrown; or all,
+ which is handled like multiple_symbols_all, below. Otherwise,
+ CANONICAL->SALS will have one entry for each name the user chose.
+
+ . With multiple_symbols_all, CANONICAL->SALS will have a single
+ entry describing all the matching locations. If FILTER is
+ non-NULL, then only locations whose canonical name is equal (in the
+ strcmp sense) to FILTER will be returned; all others will be
+ filtered out. */
+
+extern void decode_line_full (char **argptr, int flags,
+ struct symtab *default_symtab, int default_line,
+ struct linespec_result *canonical,
+ const char *select_mode,
+ const char *filter);
#endif /* defined (LINESPEC_H) */
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 5270fe4..eefe9ec 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -53,6 +53,7 @@
#include "splay-tree.h"
#include "tracepoint.h"
#include "ada-lang.h"
+#include "linespec.h"
#include <ctype.h>
#include <sys/time.h>
@@ -2437,7 +2438,7 @@ mi_cmd_trace_find (char *command, char **argv, int argc)
if (argc != 2)
error (_("Line is required"));
- sals = decode_line_spec (argv[1], 1);
+ sals = decode_line_spec (argv[1], DECODE_LINE_FUNFIRSTLINE);
back_to = make_cleanup (xfree, sals.sals);
sal = sals.sals[0];
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 70871cd..f90f036 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -310,6 +310,46 @@ lookup_minimal_symbol (const char *name, const char *sfile,
return NULL;
}
+/* Iterate over all the minimal symbols in the objfile OBJF which
+ match NAME. Both the ordinary and demangled names of each symbol
+ are considered. The caller is responsible for canonicalizing NAME,
+ should that need to be done.
+
+ For each matching symbol, CALLBACK is called with the symbol and
+ USER_DATA as arguments. */
+
+void
+iterate_over_minimal_symbols (struct objfile *objf, const char *name,
+ void (*callback) (struct minimal_symbol *,
+ void *),
+ void *user_data)
+{
+ unsigned int hash;
+ struct minimal_symbol *iter;
+ int (*cmp) (const char *, const char *);
+
+ /* The first pass is over the ordinary hash table. */
+ hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
+ iter = objf->msymbol_hash[hash];
+ cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
+ while (iter)
+ {
+ if (cmp (SYMBOL_LINKAGE_NAME (iter), name) == 0)
+ (*callback) (iter, user_data);
+ iter = iter->hash_next;
+ }
+
+ /* The second pass is over the demangled table. */
+ hash = msymbol_hash_iw (name) % MINIMAL_SYMBOL_HASH_SIZE;
+ iter = objf->msymbol_demangled_hash[hash];
+ while (iter)
+ {
+ if (SYMBOL_MATCHES_SEARCH_NAME (iter, name))
+ (*callback) (iter, user_data);
+ iter = iter->demangled_hash_next;
+ }
+}
+
/* Look through all the current minimal symbol tables and find the
first minimal symbol that matches NAME and has text type. If OBJF
is non-NULL, limit the search to that objfile. Returns a pointer
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index 592b52e..dcf9459 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -952,49 +952,7 @@ classes_info (char *regexp, int from_tty)
printf_filtered (_("No classes matching \"%s\"\n"), regexp ? regexp : "*");
}
-/*
- * Function: find_imps (char *selector, struct symbol **sym_arr)
- *
- * Input: a string representing a selector
- * a pointer to an array of symbol pointers
- * possibly a pointer to a symbol found by the caller.
- *
- * Output: number of methods that implement that selector. Side
- * effects: The array of symbol pointers is filled with matching syms.
- *
- * By analogy with function "find_methods" (symtab.c), builds a list
- * of symbols matching the ambiguous input, so that "decode_line_2"
- * (symtab.c) can list them and ask the user to choose one or more.
- * In this case the matches are objective c methods
- * ("implementations") matching an objective c selector.
- *
- * Note that it is possible for a normal (c-style) function to have
- * the same name as an objective c selector. To prevent the selector
- * from eclipsing the function, we allow the caller (decode_line_1) to
- * search for such a function first, and if it finds one, pass it in
- * to us. We will then integrate it into the list. We also search
- * for one here, among the minsyms.
- *
- * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
- * into two parts: debuggable (struct symbol) syms, and
- * non_debuggable (struct minimal_symbol) syms. The debuggable
- * ones will come first, before NUM_DEBUGGABLE (which will thus
- * be the index of the first non-debuggable one).
- */
-
-/*
- * Function: total_number_of_imps (char *selector);
- *
- * Input: a string representing a selector
- * Output: number of methods that implement that selector.
- *
- * By analogy with function "total_number_of_methods", this allows
- * decode_line_1 (symtab.c) to detect if there are objective c methods
- * matching the input, and to allocate an array of pointers to them
- * which can be manipulated by "decode_line_2" (also in symtab.c).
- */
-
-char *
+static char *
parse_selector (char *method, char **selector)
{
char *s1 = NULL;
@@ -1050,7 +1008,7 @@ parse_selector (char *method, char **selector)
return s2;
}
-char *
+static char *
parse_method (char *method, char *type, char **class,
char **category, char **selector)
{
@@ -1154,15 +1112,11 @@ parse_method (char *method, char *type, char **class,
}
static void
-find_methods (struct symtab *symtab, char type,
- const char *class, const char *category,
- const char *selector, struct symbol **syms,
- unsigned int *nsym, unsigned int *ndebug)
+find_methods (char type, const char *class, const char *category,
+ const char *selector,
+ VEC (const_char_ptr) **symbol_names)
{
struct objfile *objfile = NULL;
- struct minimal_symbol *msymbol = NULL;
- struct block *block = NULL;
- struct symbol *sym = NULL;
char *symname = NULL;
@@ -1171,21 +1125,15 @@ find_methods (struct symtab *symtab, char type,
char *ncategory = NULL;
char *nselector = NULL;
- unsigned int csym = 0;
- unsigned int cdebug = 0;
-
static char *tmp = NULL;
static unsigned int tmplen = 0;
- gdb_assert (nsym != NULL);
- gdb_assert (ndebug != NULL);
-
- if (symtab)
- block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+ gdb_assert (symbol_names != NULL);
ALL_OBJFILES (objfile)
{
unsigned int *objc_csym;
+ struct minimal_symbol *msymbol = NULL;
/* The objfile_csym variable counts the number of ObjC methods
that this objfile defines. We save that count as a private
@@ -1202,7 +1150,6 @@ find_methods (struct symtab *symtab, char type,
ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
- CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol);
QUIT;
@@ -1216,18 +1163,8 @@ find_methods (struct symtab *symtab, char type,
/* Not a method name. */
continue;
- /* The minimal symbol might point to a function descriptor;
- resolve it to the actual code address instead. */
- pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
- ¤t_target);
-
objfile_csym++;
- if (symtab)
- if (pc < BLOCK_START (block) || pc >= BLOCK_END (block))
- /* Not in the specified symtab. */
- continue;
-
/* Now that thinks are a bit sane, clean up the symname. */
while ((strlen (symname) + 1) >= tmplen)
{
@@ -1255,41 +1192,9 @@ find_methods (struct symtab *symtab, char type,
((nselector == NULL) || (strcmp (selector, nselector) != 0)))
continue;
- sym = find_pc_function (pc);
- if (sym != NULL)
- {
- const char *newsymname = SYMBOL_NATURAL_NAME (sym);
-
- if (strcmp (symname, newsymname) == 0)
- {
- /* Found a high-level method sym: swap it into the
- lower part of sym_arr (below num_debuggable). */
- if (syms != NULL)
- {
- syms[csym] = syms[cdebug];
- syms[cdebug] = sym;
- }
- csym++;
- cdebug++;
- }
- else
- {
- warning (
-"debugging symbol \"%s\" does not match minimal symbol (\"%s\"); ignoring",
- newsymname, symname);
- if (syms != NULL)
- syms[csym] = (struct symbol *) msymbol;
- csym++;
- }
- }
- else
- {
- /* Found a non-debuggable method symbol. */
- if (syms != NULL)
- syms[csym] = (struct symbol *) msymbol;
- csym++;
- }
+ VEC_safe_push (const_char_ptr, *symbol_names, symname);
}
+
if (objc_csym == NULL)
{
objc_csym = obstack_alloc (&objfile->objfile_obstack,
@@ -1301,38 +1206,79 @@ find_methods (struct symtab *symtab, char type,
/* Count of ObjC methods in this objfile should be constant. */
gdb_assert (*objc_csym == objfile_csym);
}
+}
+
+/* Uniquify a VEC of strings. */
- if (nsym != NULL)
- *nsym = csym;
- if (ndebug != NULL)
- *ndebug = cdebug;
+static void
+uniquify_strings (VEC (const_char_ptr) **strings)
+{
+ int ix;
+ const char *elem, *last = NULL;
+ int out;
+
+ qsort (VEC_address (const_char_ptr, *strings),
+ VEC_length (const_char_ptr, *strings),
+ sizeof (const_char_ptr),
+ compare_strings);
+ out = 0;
+ for (ix = 0; VEC_iterate (const_char_ptr, *strings, ix, elem); ++ix)
+ {
+ if (last == NULL || strcmp (last, elem) != 0)
+ {
+ /* Keep ELEM. */
+ VEC_replace (const_char_ptr, *strings, out, elem);
+ ++out;
+ }
+ last = elem;
+ }
+ VEC_truncate (const_char_ptr, *strings, out);
}
-char *find_imps (struct symtab *symtab, struct block *block,
- char *method, struct symbol **syms,
- unsigned int *nsym, unsigned int *ndebug)
+/*
+ * Function: find_imps (char *selector, struct symbol **sym_arr)
+ *
+ * Input: a string representing a selector
+ * a pointer to an array of symbol pointers
+ * possibly a pointer to a symbol found by the caller.
+ *
+ * Output: number of methods that implement that selector. Side
+ * effects: The array of symbol pointers is filled with matching syms.
+ *
+ * By analogy with function "find_methods" (symtab.c), builds a list
+ * of symbols matching the ambiguous input, so that "decode_line_2"
+ * (symtab.c) can list them and ask the user to choose one or more.
+ * In this case the matches are objective c methods
+ * ("implementations") matching an objective c selector.
+ *
+ * Note that it is possible for a normal (c-style) function to have
+ * the same name as an objective c selector. To prevent the selector
+ * from eclipsing the function, we allow the caller (decode_line_1) to
+ * search for such a function first, and if it finds one, pass it in
+ * to us. We will then integrate it into the list. We also search
+ * for one here, among the minsyms.
+ *
+ * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
+ * into two parts: debuggable (struct symbol) syms, and
+ * non_debuggable (struct minimal_symbol) syms. The debuggable
+ * ones will come first, before NUM_DEBUGGABLE (which will thus
+ * be the index of the first non-debuggable one).
+ */
+
+char *
+find_imps (char *method, VEC (const_char_ptr) **symbol_names)
{
char type = '\0';
char *class = NULL;
char *category = NULL;
char *selector = NULL;
- unsigned int csym = 0;
- unsigned int cdebug = 0;
-
- unsigned int ncsym = 0;
- unsigned int ncdebug = 0;
-
char *buf = NULL;
char *tmp = NULL;
- gdb_assert (nsym != NULL);
- gdb_assert (ndebug != NULL);
+ int selector_case = 0;
- if (nsym != NULL)
- *nsym = 0;
- if (ndebug != NULL)
- *ndebug = 0;
+ gdb_assert (symbol_names != NULL);
buf = (char *) alloca (strlen (method) + 1);
strcpy (buf, method);
@@ -1340,99 +1286,37 @@ char *find_imps (struct symtab *symtab, struct block *block,
if (tmp == NULL)
{
- struct symbol *sym = NULL;
- struct minimal_symbol *msym = NULL;
-
strcpy (buf, method);
tmp = parse_selector (buf, &selector);
if (tmp == NULL)
return NULL;
- sym = lookup_symbol (selector, block, VAR_DOMAIN, 0);
- if (sym != NULL)
- {
- if (syms)
- syms[csym] = sym;
- csym++;
- cdebug++;
- }
-
- if (sym == NULL)
- msym = lookup_minimal_symbol (selector, 0, 0);
-
- if (msym != NULL)
- {
- if (syms)
- syms[csym] = (struct symbol *)msym;
- csym++;
- }
+ selector_case = 1;
}
- if (syms != NULL)
- find_methods (symtab, type, class, category, selector,
- syms + csym, &ncsym, &ncdebug);
- else
- find_methods (symtab, type, class, category, selector,
- NULL, &ncsym, &ncdebug);
-
- /* If we didn't find any methods, just return. */
- if (ncsym == 0 && ncdebug == 0)
- return method;
+ find_methods (type, class, category, selector, symbol_names);
- /* Take debug symbols from the second batch of symbols and swap them
- * with debug symbols from the first batch. Repeat until either the
- * second section is out of debug symbols or the first section is
- * full of debug symbols. Either way we have all debug symbols
- * packed to the beginning of the buffer.
- */
-
- if (syms != NULL)
+ /* If we hit the "selector" case, and we found some methods, then
+ add the selector itself as a symbol, if it exists. */
+ if (selector_case && !VEC_empty (const_char_ptr, *symbol_names))
{
- while ((cdebug < csym) && (ncdebug > 0))
+ struct symbol *sym = lookup_symbol (selector, NULL, VAR_DOMAIN, 0);
+
+ if (sym != NULL)
+ VEC_safe_push (const_char_ptr, *symbol_names,
+ SYMBOL_NATURAL_NAME (sym));
+ else
{
- struct symbol *s = NULL;
- /* First non-debugging symbol. */
- unsigned int i = cdebug;
- /* Last of second batch of debug symbols. */
- unsigned int j = csym + ncdebug - 1;
-
- s = syms[j];
- syms[j] = syms[i];
- syms[i] = s;
-
- /* We've moved a symbol from the second debug section to the
- first one. */
- cdebug++;
- ncdebug--;
+ struct minimal_symbol *msym = lookup_minimal_symbol (selector, 0, 0);
+
+ if (msym != NULL)
+ VEC_safe_push (const_char_ptr, *symbol_names,
+ SYMBOL_NATURAL_NAME (msym));
}
}
- csym += ncsym;
- cdebug += ncdebug;
-
- if (nsym != NULL)
- *nsym = csym;
- if (ndebug != NULL)
- *ndebug = cdebug;
-
- if (syms == NULL)
- return method + (tmp - buf);
-
- if (csym > 1)
- {
- /* Sort debuggable symbols. */
- if (cdebug > 1)
- qsort (syms, cdebug, sizeof (struct minimal_symbol *),
- compare_classes);
-
- /* Sort minimal_symbols. */
- if ((csym - cdebug) > 1)
- qsort (&syms[cdebug], csym - cdebug,
- sizeof (struct minimal_symbol *), compare_classes);
- }
- /* Terminate the sym_arr list. */
- syms[csym] = 0;
+ uniquify_strings (symbol_names);
return method + (tmp - buf);
}
diff --git a/gdb/objc-lang.h b/gdb/objc-lang.h
index ee4cc29..351af7b 100644
--- a/gdb/objc-lang.h
+++ b/gdb/objc-lang.h
@@ -21,6 +21,8 @@
#if !defined(OBJC_LANG_H)
#define OBJC_LANG_H
+#include "cp-support.h" /* For VEC (const_char_ptr) */
+
struct stoken;
struct value;
@@ -39,15 +41,7 @@ extern char *objc_demangle (const char *mangled, int options);
extern int find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc);
-extern char *parse_selector (char *method, char **selector);
-
-extern char *parse_method (char *method, char *type,
- char **class, char **category,
- char **selector);
-
-extern char *find_imps (struct symtab *symtab, struct block *block,
- char *method, struct symbol **syms,
- unsigned int *nsym, unsigned int *ndebug);
+extern char *find_imps (char *method, VEC (const_char_ptr) **symbol_names);
extern struct value *value_nsstring (struct gdbarch *gdbarch,
char *ptr, int len);
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 6c4507d..c20fd78 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -125,13 +125,42 @@ require_partial_symbols (struct objfile *objfile, int verbose)
ALL_OBJFILES (objfile) \
ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p)
-/* Lookup the partial symbol table of a source file named NAME.
- *If* there is no '/' in the name, a match after a '/'
- in the psymtab filename will also work. */
+/* Helper function for partial_map_symtabs_matching_filename that
+ expands the symtabs and calls the iterator. */
-static struct partial_symtab *
-lookup_partial_symtab (struct objfile *objfile, const char *name,
- const char *full_path, const char *real_path)
+static int
+partial_map_expand_apply (struct objfile *objfile,
+ const char *name,
+ const char *full_path,
+ const char *real_path,
+ struct partial_symtab *pst,
+ int (*callback) (struct symtab *, void *),
+ void *data)
+{
+ struct symtab *last_made = objfile->symtabs;
+
+ /* Don't visit already-expanded psymtabs. */
+ if (pst->readin)
+ return 0;
+
+ /* This may expand more than one symtab, and we want to iterate over
+ all of them. */
+ psymtab_to_symtab (pst);
+
+ return iterate_over_some_symtabs (name, full_path, real_path, callback, data,
+ objfile->symtabs, last_made);
+}
+
+/* Implementation of the map_symtabs_matching_filename method. */
+
+static int
+partial_map_symtabs_matching_filename (struct objfile *objfile,
+ const char *name,
+ const char *full_path,
+ const char *real_path,
+ int (*callback) (struct symtab *,
+ void *),
+ void *data)
{
struct partial_symtab *pst;
const char *name_basename = lbasename (name);
@@ -140,7 +169,9 @@ lookup_partial_symtab (struct objfile *objfile, const char *name,
{
if (FILENAME_CMP (name, pst->filename) == 0)
{
- return (pst);
+ if (partial_map_expand_apply (objfile, name, full_path, real_path,
+ pst, callback, data))
+ return 1;
}
/* Before we invoke realpath, which can get expensive when many
@@ -157,7 +188,9 @@ lookup_partial_symtab (struct objfile *objfile, const char *name,
if (pst->fullname != NULL
&& FILENAME_CMP (full_path, pst->fullname) == 0)
{
- return pst;
+ if (partial_map_expand_apply (objfile, name, full_path, real_path,
+ pst, callback, data))
+ return 1;
}
}
@@ -172,7 +205,9 @@ lookup_partial_symtab (struct objfile *objfile, const char *name,
}
if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
{
- return pst;
+ if (partial_map_expand_apply (objfile, name, full_path, real_path,
+ pst, callback, data))
+ return 1;
}
}
}
@@ -183,29 +218,12 @@ lookup_partial_symtab (struct objfile *objfile, const char *name,
ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
{
if (FILENAME_CMP (lbasename (pst->filename), name) == 0)
- return (pst);
+ if (partial_map_expand_apply (objfile, name, full_path, real_path, pst,
+ callback, data))
+ return 1;
}
- return (NULL);
-}
-
-static int
-lookup_symtab_via_partial_symtab (struct objfile *objfile, const char *name,
- const char *full_path, const char *real_path,
- struct symtab **result)
-{
- struct partial_symtab *ps;
-
- ps = lookup_partial_symtab (objfile, name, full_path, real_path);
- if (!ps)
- return 0;
-
- if (ps->readin)
- error (_("Internal: readin %s pst for `%s' found when no symtab found."),
- ps->filename, name);
-
- *result = PSYMTAB_TO_SYMTAB (ps);
- return 1;
+ return 0;
}
/* Find which partial symtab contains PC and SECTION starting at psymtab PST.
@@ -1304,7 +1322,7 @@ const struct quick_symbol_functions psym_functions =
objfile_has_psyms,
find_last_source_symtab_from_partial,
forget_cached_source_info_partial,
- lookup_symtab_via_partial_symtab,
+ partial_map_symtabs_matching_filename,
lookup_symbol_aux_psymtabs,
pre_expand_symtabs_matching_psymtabs,
print_psymtab_stats_for_objfile,
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index b671cef..ab6c0ec 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -947,7 +947,7 @@ DEF_VEC_O (type_equality_entry_d);
the same, 0 otherwise. Handles NULLs properly. */
static int
-compare_strings (const char *s, const char *t)
+compare_maybe_null_strings (const char *s, const char *t)
{
if (s == NULL && t != NULL)
return 0;
@@ -983,9 +983,10 @@ check_types_equal (struct type *type1, struct type *type2,
|| TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2))
return Py_NE;
- if (!compare_strings (TYPE_TAG_NAME (type1), TYPE_TAG_NAME (type2)))
+ if (!compare_maybe_null_strings (TYPE_TAG_NAME (type1),
+ TYPE_TAG_NAME (type2)))
return Py_NE;
- if (!compare_strings (TYPE_NAME (type1), TYPE_NAME (type2)))
+ if (!compare_maybe_null_strings (TYPE_NAME (type1), TYPE_NAME (type2)))
return Py_NE;
if (TYPE_CODE (type1) == TYPE_CODE_RANGE)
@@ -1008,7 +1009,8 @@ check_types_equal (struct type *type1, struct type *type2,
|| FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2)
|| FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2))
return Py_NE;
- if (!compare_strings (FIELD_NAME (*field1), FIELD_NAME (*field2)))
+ if (!compare_maybe_null_strings (FIELD_NAME (*field1),
+ FIELD_NAME (*field2)))
return Py_NE;
switch (FIELD_LOC_KIND (*field1))
{
@@ -1022,8 +1024,8 @@ check_types_equal (struct type *type1, struct type *type2,
return Py_NE;
break;
case FIELD_LOC_KIND_PHYSNAME:
- if (!compare_strings (FIELD_STATIC_PHYSNAME (*field1),
- FIELD_STATIC_PHYSNAME (*field2)))
+ if (!compare_maybe_null_strings (FIELD_STATIC_PHYSNAME (*field1),
+ FIELD_STATIC_PHYSNAME (*field2)))
return Py_NE;
break;
case FIELD_LOC_KIND_DWARF_BLOCK:
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 6022572..b0b9a9c 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -512,7 +512,7 @@ gdbpy_decode_line (PyObject *self, PyObject *args)
{
copy = xstrdup (arg);
make_cleanup (xfree, copy);
- sals = decode_line_1 (©, 0, 0, 0, 0);
+ sals = decode_line_1 (©, 0, 0, 0);
make_cleanup (xfree, sals.sals);
}
else
diff --git a/gdb/skip.c b/gdb/skip.c
index 9f15c2f..07ca3f7 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -164,7 +164,7 @@ skip_function_command (char *arg, int from_tty)
TRY_CATCH (decode_exception, RETURN_MASK_ERROR)
{
- sals = decode_line_1 (&arg, 1, 0, 0, 0);
+ sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE, 0, 0);
}
if (decode_exception.reason < 0)
@@ -514,7 +514,7 @@ skip_re_set (void)
TRY_CATCH (decode_exception, RETURN_MASK_ERROR)
{
- sals = decode_line_1 (&func_name, 1, 0, 0, 0);
+ sals = decode_line_1 (&func_name, DECODE_LINE_FUNFIRSTLINE, 0, 0);
}
if (decode_exception.reason >= 0
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
index 888aa34..21efbdf 100644
--- a/gdb/solib-target.c
+++ b/gdb/solib-target.c
@@ -28,8 +28,6 @@
#include "gdb_string.h"
-DEF_VEC_I(CORE_ADDR);
-
/* Private data for each loaded library. */
struct lm_info
{
diff --git a/gdb/source.c b/gdb/source.c
index 77df541..57f5ad8 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -245,7 +245,7 @@ select_source_symtab (struct symtab *s)
if one exists. */
if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0))
{
- sals = decode_line_spec (main_name (), 1);
+ sals = decode_line_spec (main_name (), DECODE_LINE_FUNFIRSTLINE);
sal = sals.sals[0];
xfree (sals.sals);
current_source_pspace = sal.pspace;
@@ -1413,12 +1413,14 @@ line_info (char *arg, int from_tty)
struct symtab_and_line sal;
CORE_ADDR start_pc, end_pc;
int i;
+ struct cleanup *cleanups;
init_sal (&sal); /* initialize to zeroes */
if (arg == 0)
{
sal.symtab = current_source_symtab;
+ sal.pspace = current_program_space;
sal.line = last_line_listed;
sals.nelts = 1;
sals.sals = (struct symtab_and_line *)
@@ -1427,16 +1429,20 @@ line_info (char *arg, int from_tty)
}
else
{
- sals = decode_line_spec_1 (arg, 0);
+ sals = decode_line_spec_1 (arg, DECODE_LINE_LIST_MODE);
dont_repeat ();
}
+ cleanups = make_cleanup (xfree, sals.sals);
+
/* C++ More than one line may have been specified, as when the user
specifies an overloaded function name. Print info on them all. */
for (i = 0; i < sals.nelts; i++)
{
sal = sals.sals[i];
+ if (sal.pspace != current_program_space)
+ continue;
if (sal.symtab == 0)
{
@@ -1502,7 +1508,7 @@ line_info (char *arg, int from_tty)
printf_filtered (_("Line number %d is out of range for \"%s\".\n"),
sal.line, sal.symtab->filename);
}
- xfree (sals.sals);
+ do_cleanups (cleanups);
}
\f
/* Commands to search the source file for a regexp. */
diff --git a/gdb/stack.c b/gdb/stack.c
index 9136daa..c5c54db 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -47,6 +47,7 @@
#include "cp-support.h"
#include "disasm.h"
#include "inline-frame.h"
+#include "linespec.h"
#include "gdb_assert.h"
#include <ctype.h>
@@ -2444,20 +2445,25 @@ func_command (char *arg, int from_tty)
int i;
int level = 1;
struct function_bounds *func_bounds = NULL;
+ struct cleanup *cleanups;
if (arg != NULL)
return;
frame = parse_frame_specification ("0");
- sals = decode_line_spec (arg, 1);
+ sals = decode_line_spec (arg, DECODE_LINE_FUNFIRSTLINE);
+ cleanups = make_cleanup (xfree, sals.sals);
func_bounds = (struct function_bounds *) xmalloc (
sizeof (struct function_bounds) * sals.nelts);
+ make_cleanup (xfree, func_bounds);
for (i = 0; (i < sals.nelts && !found); i++)
{
- if (sals.sals[i].pc == 0
- || find_pc_partial_function (sals.sals[i].pc, NULL,
- &func_bounds[i].low,
- &func_bounds[i].high) == 0)
+ if (sals.sals[i].pspace != current_program_space)
+ func_bounds[i].low = func_bounds[i].high = 0;
+ else if (sals.sals[i].pc == 0
+ || find_pc_partial_function (sals.sals[i].pc, NULL,
+ &func_bounds[i].low,
+ &func_bounds[i].high) == 0)
{
func_bounds[i].low = func_bounds[i].high = 0;
}
@@ -2476,8 +2482,7 @@ func_command (char *arg, int from_tty)
}
while (!found && level == 0);
- if (func_bounds)
- xfree (func_bounds);
+ do_cleanups (cleanups);
if (!found)
printf_filtered (_("'%s' not within current stack frame.\n"), arg);
diff --git a/gdb/symfile.h b/gdb/symfile.h
index accd20e..dfe5042 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -152,22 +152,24 @@ struct quick_symbol_functions
/* Forget all cached full file names for OBJFILE. */
void (*forget_cached_source_info) (struct objfile *objfile);
- /* Look up the symbol table, in OBJFILE, of a source file named
- NAME. If there is no '/' in the name, a match after a '/' in the
- symbol table's file name will also work. FULL_PATH is the
- absolute file name, and REAL_PATH is the same, run through
- gdb_realpath.
-
- If no such symbol table can be found, returns 0.
-
- Otherwise, sets *RESULT to the symbol table and returns 1. This
- might return 1 and set *RESULT to NULL if the requested file is
- an include file that does not have a symtab of its own. */
- int (*lookup_symtab) (struct objfile *objfile,
- const char *name,
- const char *full_path,
- const char *real_path,
- struct symtab **result);
+ /* Expand and iterate over each "partial" symbol table in OBJFILE
+ where the source file is named NAME.
+
+ If there is no '/' in the name, a match after a '/' in the symbol
+ table's file name will also work. FULL_PATH is the absolute file
+ name, and REAL_PATH is the same, run through gdb_realpath.
+
+ If a match is found, the "partial" symbol table is expanded.
+ Then, this calls iterate_over_some_symtabs (or equivalent) over
+ all newly-created symbol tables, passing CALLBACK and DATA to it.
+ The result of this call is returned. */
+ int (*map_symtabs_matching_filename) (struct objfile *objfile,
+ const char *name,
+ const char *full_path,
+ const char *real_path,
+ int (*callback) (struct symtab *,
+ void *),
+ void *data);
/* Check to see if the symbol is defined in a "partial" symbol table
of OBJFILE. KIND should be either GLOBAL_BLOCK or STATIC_BLOCK,
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 3d94e6b..3ae5cf9 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -81,7 +81,7 @@ static void sources_info (char *, int);
static void output_source_filename (const char *, int *);
-static int find_line_common (struct linetable *, int, int *);
+static int find_line_common (struct linetable *, int, int *, int);
static struct symbol *lookup_symbol_aux (const char *name,
const struct block *block,
@@ -147,44 +147,38 @@ multiple_symbols_select_mode (void)
const struct block *block_found;
-/* Check for a symtab of a specific name; first in symtabs, then in
- psymtabs. *If* there is no '/' in the name, a match after a '/'
- in the symtab filename will also work. */
+/* Check for a symtab of a specific name by searching some symtabs.
+ This is a helper function for callbacks of iterate_over_symtabs.
-struct symtab *
-lookup_symtab (const char *name)
+ The return value, NAME, FULL_PATH, REAL_PATH, CALLBACK, and DATA
+ are identical to the `map_symtabs_matching_filename' method of
+ quick_symbol_functions.
+
+ FIRST and AFTER_LAST indicate the range of symtabs to search.
+ AFTER_LAST is one past the last symtab to search; NULL means to
+ search until the end of the list. */
+
+int
+iterate_over_some_symtabs (const char *name,
+ const char *full_path,
+ const char *real_path,
+ int (*callback) (struct symtab *symtab,
+ void *data),
+ void *data,
+ struct symtab *first,
+ struct symtab *after_last)
{
- int found;
struct symtab *s = NULL;
- struct objfile *objfile;
- char *real_path = NULL;
- char *full_path = NULL;
struct cleanup *cleanup;
const char* base_name = lbasename (name);
- cleanup = make_cleanup (null_cleanup, NULL);
-
- /* Here we are interested in canonicalizing an absolute path, not
- absolutizing a relative path. */
- if (IS_ABSOLUTE_PATH (name))
+ for (s = first; s != NULL && s != after_last; s = s->next)
{
- full_path = xfullpath (name);
- make_cleanup (xfree, full_path);
- real_path = gdb_realpath (name);
- make_cleanup (xfree, real_path);
- }
-
-got_symtab:
-
- /* First, search for an exact match. */
-
- ALL_SYMTABS (objfile, s)
- {
- if (FILENAME_CMP (name, s->filename) == 0)
- {
- do_cleanups (cleanup);
- return s;
- }
+ if (FILENAME_CMP (name, s->filename) == 0)
+ {
+ if (callback (s, data))
+ return 1;
+ }
/* Before we invoke realpath, which can get expensive when many
files are involved, do a quick comparison of the basenames. */
@@ -201,8 +195,8 @@ got_symtab:
if (fp != NULL && FILENAME_CMP (full_path, fp) == 0)
{
- do_cleanups (cleanup);
- return s;
+ if (callback (s, data))
+ return 1;
}
}
@@ -216,62 +210,114 @@ got_symtab:
make_cleanup (xfree, rp);
if (FILENAME_CMP (real_path, rp) == 0)
- {
- do_cleanups (cleanup);
- return s;
- }
+ {
+ if (callback (s, data))
+ return 1;
+ }
}
}
- }
+ }
/* Now, search for a matching tail (only if name doesn't have any dirs). */
if (lbasename (name) == name)
- ALL_SYMTABS (objfile, s)
{
- if (FILENAME_CMP (lbasename (s->filename), name) == 0)
+ for (s = first; s != NULL && s != after_last; s = s->next)
{
- do_cleanups (cleanup);
- return s;
+ if (FILENAME_CMP (lbasename (s->filename), name) == 0)
+ {
+ if (callback (s, data))
+ return 1;
+ }
}
}
+ return 0;
+}
+
+/* Check for a symtab of a specific name; first in symtabs, then in
+ psymtabs. *If* there is no '/' in the name, a match after a '/'
+ in the symtab filename will also work.
+
+ Calls CALLBACK with each symtab that is found and with the supplied
+ DATA. If CALLBACK returns true, the search stops. */
+
+void
+iterate_over_symtabs (const char *name,
+ int (*callback) (struct symtab *symtab,
+ void *data),
+ void *data)
+{
+ struct symtab *s = NULL;
+ struct objfile *objfile;
+ char *real_path = NULL;
+ char *full_path = NULL;
+ struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
+
+ /* Here we are interested in canonicalizing an absolute path, not
+ absolutizing a relative path. */
+ if (IS_ABSOLUTE_PATH (name))
+ {
+ full_path = xfullpath (name);
+ make_cleanup (xfree, full_path);
+ real_path = gdb_realpath (name);
+ make_cleanup (xfree, real_path);
+ }
+
+ ALL_OBJFILES (objfile)
+ {
+ if (iterate_over_some_symtabs (name, full_path, real_path, callback, data,
+ objfile->symtabs, NULL))
+ {
+ do_cleanups (cleanups);
+ return;
+ }
+ }
+
/* Same search rules as above apply here, but now we look thru the
psymtabs. */
- found = 0;
ALL_OBJFILES (objfile)
{
if (objfile->sf
- && objfile->sf->qf->lookup_symtab (objfile, name, full_path, real_path,
- &s))
+ && objfile->sf->qf->map_symtabs_matching_filename (objfile,
+ name,
+ full_path,
+ real_path,
+ callback,
+ data))
{
- found = 1;
- break;
+ do_cleanups (cleanups);
+ return;
}
}
- if (s != NULL)
- {
- do_cleanups (cleanup);
- return s;
- }
- if (!found)
- {
- do_cleanups (cleanup);
- return NULL;
- }
+ do_cleanups (cleanups);
+}
+
+/* The callback function used by lookup_symtab. */
+
+static int
+lookup_symtab_callback (struct symtab *symtab, void *data)
+{
+ struct symtab **result_ptr = data;
- /* At this point, we have located the psymtab for this file, but
- the conversion to a symtab has failed. This usually happens
- when we are looking up an include file. In this case,
- PSYMTAB_TO_SYMTAB doesn't return a symtab, even though one has
- been created. So, we need to run through the symtabs again in
- order to find the file.
- XXX - This is a crock, and should be fixed inside of the
- symbol parsing routines. */
- goto got_symtab;
+ *result_ptr = symtab;
+ return 1;
}
+
+/* A wrapper for iterate_over_symtabs that returns the first matching
+ symtab, or NULL. */
+
+struct symtab *
+lookup_symtab (const char *name)
+{
+ struct symtab *result = NULL;
+
+ iterate_over_symtabs (name, lookup_symtab_callback, &result);
+ return result;
+}
+
\f
/* Mangle a GDB method stub type. This actually reassembles the pieces of the
full method name, which consist of the class name (from T), the unadorned
@@ -1006,33 +1052,16 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
return sym;
}
-/* Find the definition for a specified symbol name NAME
- in domain DOMAIN, visible from lexical block BLOCK.
- Returns the struct symbol pointer, or zero if no symbol is found.
- C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if
- NAME is a field of the current implied argument `this'. If so set
- *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero.
- BLOCK_FOUND is set to the block in which NAME is found (in the case of
- a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */
+/* Compute the demangled form of NAME as used by the various symbol
+ lookup functions. The result is stored in *RESULT_NAME. Returns a
+ cleanup which can be used to clean up the result. */
-/* This function has a bunch of loops in it and it would seem to be
- attractive to put in some QUIT's (though I'm not really sure
- whether it can run long enough to be really important). But there
- are a few calls for which it would appear to be bad news to quit
- out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c. (Note
- that there is C++ code below which can error(), but that probably
- doesn't affect these calls since they are looking for a known
- variable and thus can probably assume it will never hit the C++
- code). */
-
-struct symbol *
-lookup_symbol_in_language (const char *name, const struct block *block,
- const domain_enum domain, enum language lang,
- int *is_a_field_of_this)
+struct cleanup *
+demangle_for_lookup (const char *name, enum language lang,
+ const char **result_name)
{
char *demangled_name = NULL;
const char *modified_name = NULL;
- struct symbol *returnval;
struct cleanup *cleanup = make_cleanup (null_cleanup, 0);
modified_name = name;
@@ -1079,6 +1108,38 @@ lookup_symbol_in_language (const char *name, const struct block *block,
}
}
+ *result_name = modified_name;
+ return cleanup;
+}
+
+/* Find the definition for a specified symbol name NAME
+ in domain DOMAIN, visible from lexical block BLOCK.
+ Returns the struct symbol pointer, or zero if no symbol is found.
+ C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if
+ NAME is a field of the current implied argument `this'. If so set
+ *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero.
+ BLOCK_FOUND is set to the block in which NAME is found (in the case of
+ a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */
+
+/* This function has a bunch of loops in it and it would seem to be
+ attractive to put in some QUIT's (though I'm not really sure
+ whether it can run long enough to be really important). But there
+ are a few calls for which it would appear to be bad news to quit
+ out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c. (Note
+ that there is C++ code below which can error(), but that probably
+ doesn't affect these calls since they are looking for a known
+ variable and thus can probably assume it will never hit the C++
+ code). */
+
+struct symbol *
+lookup_symbol_in_language (const char *name, const struct block *block,
+ const domain_enum domain, enum language lang,
+ int *is_a_field_of_this)
+{
+ const char *modified_name;
+ struct symbol *returnval;
+ struct cleanup *cleanup = demangle_for_lookup (name, lang, &modified_name);
+
returnval = lookup_symbol_aux (modified_name, block, domain, lang,
is_a_field_of_this);
do_cleanups (cleanup);
@@ -1771,6 +1832,44 @@ lookup_block_symbol (const struct block *block, const char *name,
}
}
+/* Iterate over the symbols named NAME, matching DOMAIN, starting with
+ BLOCK.
+
+ For each symbol that matches, CALLBACK is called. The symbol and
+ DATA are passed to the callback.
+
+ If CALLBACK returns zero, the iteration ends. Otherwise, the
+ search continues. This function iterates upward through blocks.
+ When the outermost block has been finished, the function
+ returns. */
+
+void
+iterate_over_symbols (const struct block *block, const char *name,
+ const domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data)
+{
+ while (block)
+ {
+ struct dict_iterator iter;
+ struct symbol *sym;
+
+ for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
+ sym != NULL;
+ sym = dict_iter_name_next (name, &iter))
+ {
+ if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
+ SYMBOL_DOMAIN (sym), domain))
+ {
+ if (!callback (sym, data))
+ return;
+ }
+ }
+
+ block = BLOCK_SUPERBLOCK (block);
+ }
+}
+
/* Find the symtab associated with PC and SECTION. Look through the
psymtabs and read in another symtab if necessary. */
@@ -2196,7 +2295,7 @@ find_line_symtab (struct symtab *symtab, int line,
/* First try looking it up in the given symtab. */
best_linetable = LINETABLE (symtab);
best_symtab = symtab;
- best_index = find_line_common (best_linetable, line, &exact);
+ best_index = find_line_common (best_linetable, line, &exact, 0);
if (best_index < 0 || !exact)
{
/* Didn't find an exact match. So we better keep looking for
@@ -2241,7 +2340,7 @@ find_line_symtab (struct symtab *symtab, int line,
&& FILENAME_CMP (symtab->fullname, s->fullname) != 0)
continue;
l = LINETABLE (s);
- ind = find_line_common (l, line, &exact);
+ ind = find_line_common (l, line, &exact, 0);
if (ind >= 0)
{
if (exact)
@@ -2272,6 +2371,46 @@ done:
return best_symtab;
}
+
+/* Given SYMTAB, returns all the PCs function in the symtab that
+ exactly match LINE. Returns NULL if there are no exact matches,
+ but updates BEST_ITEM in this case. */
+
+VEC (CORE_ADDR) *
+find_pcs_for_symtab_line (struct symtab *symtab, int line,
+ struct linetable_entry **best_item)
+{
+ int start = 0, ix;
+ struct symbol *previous_function = NULL;
+ VEC (CORE_ADDR) *result = NULL;
+
+ /* First, collect all the PCs that are at this line. */
+ while (1)
+ {
+ int was_exact;
+ int idx;
+
+ idx = find_line_common (LINETABLE (symtab), line, &was_exact, start);
+ if (idx < 0)
+ break;
+
+ if (!was_exact)
+ {
+ struct linetable_entry *item = &LINETABLE (symtab)->item[idx];
+
+ if (*best_item == NULL || item->line < (*best_item)->line)
+ *best_item = item;
+
+ break;
+ }
+
+ VEC_safe_push (CORE_ADDR, result, LINETABLE (symtab)->item[idx].pc);
+ start = idx + 1;
+ }
+
+ return result;
+}
+
\f
/* Set the PC value for a given source file and line number and return true.
Returns zero for invalid line number (and sets the PC to 0).
@@ -2340,12 +2479,13 @@ find_line_pc_range (struct symtab_and_line sal, CORE_ADDR *startptr,
/* Given a line table and a line number, return the index into the line
table for the pc of the nearest line whose number is >= the specified one.
Return -1 if none is found. The value is >= 0 if it is an index.
+ START is the index at which to start searching the line table.
Set *EXACT_MATCH nonzero if the value returned is an exact match. */
static int
find_line_common (struct linetable *l, int lineno,
- int *exact_match)
+ int *exact_match, int start)
{
int i;
int len;
@@ -2365,7 +2505,7 @@ find_line_common (struct linetable *l, int lineno,
return -1;
len = l->nitems;
- for (i = 0; i < len; i++)
+ for (i = start; i < len; i++)
{
struct linetable_entry *item = &(l->item[i]);
@@ -4518,7 +4658,7 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
}
\f
struct symtabs_and_lines
-decode_line_spec (char *string, int funfirstline)
+decode_line_spec (char *string, int flags)
{
struct symtabs_and_lines sals;
struct symtab_and_line cursal;
@@ -4530,9 +4670,8 @@ decode_line_spec (char *string, int funfirstline)
and get a default or it will recursively call us! */
cursal = get_current_source_symtab_and_line ();
- sals = decode_line_1 (&string, funfirstline,
- cursal.symtab, cursal.line,
- NULL);
+ sals = decode_line_1 (&string, flags,
+ cursal.symtab, cursal.line);
if (*string)
error (_("Junk at end of line specification: %s"), string);
@@ -4620,211 +4759,6 @@ symtab_observer_executable_changed (void)
set_main_name (NULL);
}
-/* Helper to expand_line_sal below. Appends new sal to SAL,
- initializing it from SYMTAB, LINENO and PC. */
-static void
-append_expanded_sal (struct symtabs_and_lines *sal,
- struct program_space *pspace,
- struct symtab *symtab,
- int lineno, CORE_ADDR pc)
-{
- sal->sals = xrealloc (sal->sals,
- sizeof (sal->sals[0])
- * (sal->nelts + 1));
- init_sal (sal->sals + sal->nelts);
- sal->sals[sal->nelts].pspace = pspace;
- sal->sals[sal->nelts].symtab = symtab;
- sal->sals[sal->nelts].section = NULL;
- sal->sals[sal->nelts].end = 0;
- sal->sals[sal->nelts].line = lineno;
- sal->sals[sal->nelts].pc = pc;
- ++sal->nelts;
-}
-
-/* Helper to expand_line_sal below. Search in the symtabs for any
- linetable entry that exactly matches FULLNAME and LINENO and append
- them to RET. If FULLNAME is NULL or if a symtab has no full name,
- use FILENAME and LINENO instead. If there is at least one match,
- return 1; otherwise, return 0, and return the best choice in BEST_ITEM
- and BEST_SYMTAB. */
-
-static int
-append_exact_match_to_sals (char *filename, char *fullname, int lineno,
- struct symtabs_and_lines *ret,
- struct linetable_entry **best_item,
- struct symtab **best_symtab)
-{
- struct program_space *pspace;
- struct objfile *objfile;
- struct symtab *symtab;
- int exact = 0;
- int j;
- *best_item = 0;
- *best_symtab = 0;
-
- ALL_PSPACES (pspace)
- ALL_PSPACE_SYMTABS (pspace, objfile, symtab)
- {
- if (FILENAME_CMP (filename, symtab->filename) == 0)
- {
- struct linetable *l;
- int len;
-
- if (fullname != NULL
- && symtab_to_fullname (symtab) != NULL
- && FILENAME_CMP (fullname, symtab->fullname) != 0)
- continue;
- l = LINETABLE (symtab);
- if (!l)
- continue;
- len = l->nitems;
-
- for (j = 0; j < len; j++)
- {
- struct linetable_entry *item = &(l->item[j]);
-
- if (item->line == lineno)
- {
- exact = 1;
- append_expanded_sal (ret, objfile->pspace,
- symtab, lineno, item->pc);
- }
- else if (!exact && item->line > lineno
- && (*best_item == NULL
- || item->line < (*best_item)->line))
- {
- *best_item = item;
- *best_symtab = symtab;
- }
- }
- }
- }
- return exact;
-}
-
-/* Compute a set of all sals in all program spaces that correspond to
- same file and line as SAL and return those. If there are several
- sals that belong to the same block, only one sal for the block is
- included in results. */
-
-struct symtabs_and_lines
-expand_line_sal (struct symtab_and_line sal)
-{
- struct symtabs_and_lines ret;
- int i, j;
- struct objfile *objfile;
- int lineno;
- int deleted = 0;
- struct block **blocks = NULL;
- int *filter;
- struct cleanup *old_chain;
-
- ret.nelts = 0;
- ret.sals = NULL;
-
- /* Only expand sals that represent file.c:line. */
- if (sal.symtab == NULL || sal.line == 0 || sal.pc != 0)
- {
- ret.sals = xmalloc (sizeof (struct symtab_and_line));
- ret.sals[0] = sal;
- ret.nelts = 1;
- return ret;
- }
- else
- {
- struct program_space *pspace;
- struct linetable_entry *best_item = 0;
- struct symtab *best_symtab = 0;
- int exact = 0;
- char *match_filename;
-
- lineno = sal.line;
- match_filename = sal.symtab->filename;
-
- /* We need to find all symtabs for a file which name
- is described by sal. We cannot just directly
- iterate over symtabs, since a symtab might not be
- yet created. We also cannot iterate over psymtabs,
- calling PSYMTAB_TO_SYMTAB and working on that symtab,
- since PSYMTAB_TO_SYMTAB will return NULL for psymtab
- corresponding to an included file. Therefore, we do
- first pass over psymtabs, reading in those with
- the right name. Then, we iterate over symtabs, knowing
- that all symtabs we're interested in are loaded. */
-
- old_chain = save_current_program_space ();
- ALL_PSPACES (pspace)
- {
- set_current_program_space (pspace);
- ALL_PSPACE_OBJFILES (pspace, objfile)
- {
- if (objfile->sf)
- objfile->sf->qf->expand_symtabs_with_filename (objfile,
- sal.symtab->filename);
- }
- }
- do_cleanups (old_chain);
-
- /* Now search the symtab for exact matches and append them. If
- none is found, append the best_item and all its exact
- matches. */
- symtab_to_fullname (sal.symtab);
- exact = append_exact_match_to_sals (sal.symtab->filename,
- sal.symtab->fullname, lineno,
- &ret, &best_item, &best_symtab);
- if (!exact && best_item)
- append_exact_match_to_sals (best_symtab->filename,
- best_symtab->fullname, best_item->line,
- &ret, &best_item, &best_symtab);
- }
-
- /* For optimized code, compiler can scatter one source line accross
- disjoint ranges of PC values, even when no duplicate functions
- or inline functions are involved. For example, 'for (;;)' inside
- non-template non-inline non-ctor-or-dtor function can result
- in two PC ranges. In this case, we don't want to set breakpoint
- on first PC of each range. To filter such cases, we use containing
- blocks -- for each PC found above we see if there are other PCs
- that are in the same block. If yes, the other PCs are filtered out. */
-
- old_chain = save_current_program_space ();
- filter = alloca (ret.nelts * sizeof (int));
- blocks = alloca (ret.nelts * sizeof (struct block *));
- for (i = 0; i < ret.nelts; ++i)
- {
- set_current_program_space (ret.sals[i].pspace);
-
- filter[i] = 1;
- blocks[i] = block_for_pc_sect (ret.sals[i].pc, ret.sals[i].section);
- }
- do_cleanups (old_chain);
-
- for (i = 0; i < ret.nelts; ++i)
- if (blocks[i] != NULL)
- for (j = i+1; j < ret.nelts; ++j)
- if (blocks[j] == blocks[i])
- {
- filter[j] = 0;
- ++deleted;
- break;
- }
-
- {
- struct symtab_and_line *final =
- xmalloc (sizeof (struct symtab_and_line) * (ret.nelts-deleted));
-
- for (i = 0, j = 0; i < ret.nelts; ++i)
- if (filter[i])
- final[j++] = ret.sals[i];
-
- ret.nelts -= deleted;
- xfree (ret.sals);
- ret.sals = final;
- }
-
- return ret;
-}
-
/* Return 1 if the supplied producer string matches the ARM RealView
compiler (armcc). */
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 39a61f4..7b52c88 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -22,6 +22,8 @@
#if !defined (SYMTAB_H)
#define SYMTAB_H 1
+#include "vec.h"
+
/* Opaque declarations. */
struct ui_file;
struct frame_info;
@@ -1056,6 +1058,12 @@ extern struct minimal_symbol *lookup_minimal_symbol_by_pc_name
extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR);
+extern void iterate_over_minimal_symbols (struct objfile *objf,
+ const char *name,
+ void (*callback) (struct minimal_symbol *,
+ void *),
+ void *user_data);
+
extern int in_gnu_ifunc_stub (CORE_ADDR pc);
/* Functions for resolving STT_GNU_IFUNC symbols which are implemented only
@@ -1295,8 +1303,6 @@ struct symbol *lookup_global_symbol_from_objfile (const struct objfile *,
const char *name,
const domain_enum domain);
-extern struct symtabs_and_lines expand_line_sal (struct symtab_and_line sal);
-
/* Return 1 if the supplied producer string matches the ARM RealView
compiler (armcc). */
int producer_is_realview (const char *producer);
@@ -1308,4 +1314,31 @@ struct objfile *lookup_objfile_from_block (const struct block *block);
extern int basenames_may_differ;
+int iterate_over_some_symtabs (const char *name,
+ const char *full_path,
+ const char *real_path,
+ int (*callback) (struct symtab *symtab,
+ void *data),
+ void *data,
+ struct symtab *first,
+ struct symtab *after_last);
+
+void iterate_over_symtabs (const char *name,
+ int (*callback) (struct symtab *symtab,
+ void *data),
+ void *data);
+
+DEF_VEC_I (CORE_ADDR);
+
+VEC (CORE_ADDR) *find_pcs_for_symtab_line (struct symtab *symtab, int line,
+ struct linetable_entry **best_entry);
+
+void iterate_over_symbols (const struct block *block, const char *name,
+ const domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data);
+
+struct cleanup *demangle_for_lookup (const char *name, enum language lang,
+ const char **result_name);
+
#endif /* !defined(SYMTAB_H) */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 8c0c1c0..cd3ca73 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,37 @@
+2011-11-18 Tom Tromey <tromey@redhat.com>
+
+ * gdb.base/solib-weak.exp (do_test): Remove kfail.
+ * gdb.trace/tracecmd.exp: Disable pending breakpoints earlier.
+ * gdb.objc/objcdecode.exp: Update for output changes.
+ * gdb.linespec/linespec.exp: New file.
+ * gdb.linespec/lspec.cc: New file.
+ * gdb.linespec/lspec.h: New file.
+ * gdb.linespec/body.h: New file.
+ * gdb.linespec/base/two/thefile.cc: New file.
+ * gdb.linespec/base/one/thefile.cc: New file.
+ * gdb.linespec/Makefile.in: New file.
+ * gdb.cp/templates.exp (test_template_breakpoints): Update for
+ output changes.
+ * gdb.cp/re-set-overloaded.exp: Remove kfail.
+ * gdb.cp/ovldbreak.exp: Update for output changes. "all" test now
+ makes one breakpoint.
+ * gdb.cp/method2.exp (test_break): Update for output changes.
+ * gdb.cp/mb-templates.exp: Update for output changes.
+ * gdb.cp/mb-inline.exp: Update for output changes.
+ * gdb.cp/mb-ctor.exp: Update for output changes.
+ * gdb.cp/ovsrch.exp: Use fully-qualified names.
+ * gdb.base/solib-symbol.exp: Run to main later. Breakpoint now
+ has multiple matches.
+ * gdb.base/sepdebug.exp: Disable pending breakpoints. Update for
+ error message change.
+ * gdb.base/list.exp (test_list_filename_and_number): Update for
+ error message change.
+ * gdb.base/break.exp: Disable pending breakpoints. Update for
+ output changes.
+ * configure.ac: Add gdb.linespec.
+ * configure: Rebuild.
+ * Makefile.in (ALL_SUBDIRS): Add gdb.linespec.
+
2011-11-25 Jan Kratochvil <jan.kratochvil@redhat.com>
PR testsuite/12649
diff --git a/gdb/testsuite/Makefile.in b/gdb/testsuite/Makefile.in
index 8b22324..d3c9cfc 100644
--- a/gdb/testsuite/Makefile.in
+++ b/gdb/testsuite/Makefile.in
@@ -35,7 +35,7 @@ SUBDIRS = @subdirs@
RPATH_ENVVAR = @RPATH_ENVVAR@
ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.cell gdb.cp gdb.disasm \
gdb.dwarf2 gdb.fortran gdb.gdb gdb.hp \
- gdb.java gdb.mi gdb.modula2 gdb.multi \
+ gdb.java gdb.linespec gdb.mi gdb.modula2 gdb.multi \
gdb.objc gdb.opencl gdb.opt gdb.pascal gdb.python gdb.server \
gdb.stabs gdb.reverse gdb.threads gdb.trace gdb.xml \
$(SUBDIRS)
diff --git a/gdb/testsuite/configure b/gdb/testsuite/configure
index 82206b3..fb70b3d 100755
--- a/gdb/testsuite/configure
+++ b/gdb/testsuite/configure
@@ -3448,7 +3448,7 @@ done
-ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
+ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -4166,6 +4166,7 @@ do
"gdb.hp/gdb.aCC/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/gdb.aCC/Makefile" ;;
"gdb.hp/gdb.compat/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/gdb.compat/Makefile" ;;
"gdb.hp/gdb.defects/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/gdb.defects/Makefile" ;;
+ "gdb.linespec/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.linespec/Makefile" ;;
"gdb.mi/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.mi/Makefile" ;;
"gdb.modula2/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.modula2/Makefile" ;;
"gdb.multi/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.multi/Makefile" ;;
diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac
index 8631442..121fd37 100644
--- a/gdb/testsuite/configure.ac
+++ b/gdb/testsuite/configure.ac
@@ -95,7 +95,7 @@ AC_OUTPUT([Makefile \
gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile \
gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile \
gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile \
- gdb.hp/gdb.defects/Makefile \
+ gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile \
gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile \
gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile \
gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile \
diff --git a/gdb/testsuite/gdb.base/break.exp b/gdb/testsuite/gdb.base/break.exp
index 92fcc69..c5885ba 100644
--- a/gdb/testsuite/gdb.base/break.exp
+++ b/gdb/testsuite/gdb.base/break.exp
@@ -540,8 +540,9 @@ gdb_test_multiple "catch exec" "$name" {
# Verify that GDB responds gracefully when asked to set a breakpoint
# on a nonexistent source line.
#
+gdb_test_no_output "set breakpoint pending off"
gdb_test "break 999" \
- "No line 999 in file .*" \
+ "No line 999 in the current file." \
"break on non-existent source line"
# Run to the desired default location. If not positioned here, the
diff --git a/gdb/testsuite/gdb.base/list.exp b/gdb/testsuite/gdb.base/list.exp
index 5b9fe15..d4935ee 100644
--- a/gdb/testsuite/gdb.base/list.exp
+++ b/gdb/testsuite/gdb.base/list.exp
@@ -489,7 +489,7 @@ proc test_list_filename_and_function {} {
gdb_test "list foobar.c:main" "No source file named foobar.c.|Location not found" "list filename:function; nonexistant file"
- gdb_test "list list0.h:foobar" "Function \"foobar\" not defined.|Location not found" "list filename:function; nonexistant function"
+ gdb_test "list list0.h:foobar" "Function \"foobar\" not defined in \"list0.h\"." "list filename:function; nonexistant function"
}
diff --git a/gdb/testsuite/gdb.base/sepdebug.exp b/gdb/testsuite/gdb.base/sepdebug.exp
index 1a9072d..bb0b914 100644
--- a/gdb/testsuite/gdb.base/sepdebug.exp
+++ b/gdb/testsuite/gdb.base/sepdebug.exp
@@ -337,7 +337,8 @@ gdb_test_multiple "catch exec" $name {
# on a nonexistent source line.
#
-gdb_test "break 999" "No line 999 in file .*" \
+gdb_test_no_output "set breakpoint pending off"
+gdb_test "break 999" "No line 999 in the current file." \
"break on non-existent source line"
# Run to the desired default location. If not positioned here, the
diff --git a/gdb/testsuite/gdb.base/solib-symbol.exp b/gdb/testsuite/gdb.base/solib-symbol.exp
index aa723c6..d402ebb 100644
--- a/gdb/testsuite/gdb.base/solib-symbol.exp
+++ b/gdb/testsuite/gdb.base/solib-symbol.exp
@@ -46,11 +46,6 @@ gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
gdb_load_shlibs $binfile_lib
-if ![runto_main] then {
- fail "Can't run to main"
- return 0
-}
-
# Set a breakpoint in the binary.
gdb_test "br foo2" \
"Breakpoint.*file.*${testfile}\\.c.*" \
@@ -58,6 +53,11 @@ gdb_test "br foo2" \
delete_breakpoints
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
# Break in the library.
gdb_test "br foo" \
"Breakpoint.*file.*${libname}\\.c.*" \
@@ -67,9 +67,9 @@ gdb_test "continue" \
"Continuing.*" \
"continue"
-# This symbol is now looked up in the ELF library.
+# This symbol is now looked up in the ELF library and the binary.
gdb_test "br foo2" \
- "Breakpoint.*file.*${libname}\\.c.*" \
+ "Breakpoint.*: foo2. .2 locations..*" \
"foo2 in mdlib"
gdb_exit
diff --git a/gdb/testsuite/gdb.base/solib-weak.exp b/gdb/testsuite/gdb.base/solib-weak.exp
index 1f23aa2..52fd72d 100644
--- a/gdb/testsuite/gdb.base/solib-weak.exp
+++ b/gdb/testsuite/gdb.base/solib-weak.exp
@@ -101,15 +101,6 @@ proc do_test { lib1opts lib2opts lib1first } {
gdb_breakpoint "bar"
- # If the library which will be used is compiled without debugging
- # information, GDB will pick the wrong copy of "bar", i.e. the one
- # with debugging information.
-
- if {(${lib1opts} == "" && ${lib2opts} != "" && ${lib1first} == 1)
- || (${lib1opts} != "" && ${lib2opts} == "" && ${lib1first} == 0)} {
- setup_kfail gdb/1824 *-*-*
- }
-
gdb_test "continue" "Breakpoint .* \\.?bar .*${expected_file}\\..*" \
"run to breakpoint - $testopts"
}
diff --git a/gdb/testsuite/gdb.cp/mb-ctor.exp b/gdb/testsuite/gdb.cp/mb-ctor.exp
index 6a99175..0438424 100644
--- a/gdb/testsuite/gdb.cp/mb-ctor.exp
+++ b/gdb/testsuite/gdb.cp/mb-ctor.exp
@@ -50,13 +50,13 @@ if ![runto_main] then {
# and a condition.
gdb_test "break 'Derived::Derived(int)'" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: Derived::Derived.int.. \\(2 locations\\).*" \
"set-breakpoint at ctor"
gdb_breakpoint [gdb_get_line_number "set breakpoint here"]
gdb_test "break 'Derived::~Derived()'" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: Derived::~Derived... \\(2 locations\\).*" \
"set-breakpoint at dtor"
gdb_test "continue" \
diff --git a/gdb/testsuite/gdb.cp/mb-inline.exp b/gdb/testsuite/gdb.cp/mb-inline.exp
index d670b56..05b378c 100644
--- a/gdb/testsuite/gdb.cp/mb-inline.exp
+++ b/gdb/testsuite/gdb.cp/mb-inline.exp
@@ -62,7 +62,7 @@ set bp_location [gdb_get_line_number "set breakpoint here" $hdrfile]
# Set a breakpoint with multiple locations.
gdb_test "break $hdrfile:$bp_location" \
- "Breakpoint.*at.* file .*$hdrfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $hdrfile:$bp_location. \\(2 locations\\).*" \
"set breakpoint"
gdb_run_cmd
@@ -128,7 +128,7 @@ if { ![runto_main] } {
}
gdb_test "break $hdrfile:$bp_location" \
- "Breakpoint.*at.* file .*$hdrfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $hdrfile:$bp_location. \\(2 locations\\).*" \
"set multi_line_foo breakpoint"
gdb_test "continue" \
".*Breakpoint.*multi_line_foo \\(i=0\\).*" \
diff --git a/gdb/testsuite/gdb.cp/mb-templates.exp b/gdb/testsuite/gdb.cp/mb-templates.exp
index 80c080b..933d690 100644
--- a/gdb/testsuite/gdb.cp/mb-templates.exp
+++ b/gdb/testsuite/gdb.cp/mb-templates.exp
@@ -52,7 +52,7 @@ set bp_location [gdb_get_line_number "set breakpoint here"]
# and a condition.
gdb_test "break $srcfile:$bp_location if i==1" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $srcfile:$bp_location. \\(2 locations\\).*" \
"initial condition: set breakpoint"
gdb_run_cmd
@@ -80,7 +80,7 @@ gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
gdb_test "break $srcfile:$bp_location" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $srcfile:$bp_location. \\(2 locations\\).*" \
"separate condition: set breakpoint"
gdb_test_no_output "condition 1 i==1" \
@@ -177,7 +177,7 @@ if { ![runto_main] } {
}
gdb_test "break $srcfile:$bp_location" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $srcfile:$bp_location. \\(2 locations\\).*" \
"set multi_line_foo breakpoint"
gdb_test "continue" \
".*Breakpoint.*multi_line_foo<int> \\(i=0\\).*" \
diff --git a/gdb/testsuite/gdb.cp/method2.exp b/gdb/testsuite/gdb.cp/method2.exp
index 2fa4169..29a387d 100644
--- a/gdb/testsuite/gdb.cp/method2.exp
+++ b/gdb/testsuite/gdb.cp/method2.exp
@@ -51,7 +51,7 @@ proc test_break { lang } {
"setting language $lang"
gdb_test_multiple "break A::method" "breaking in method ($lang)" {
- -re ".0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. A::method\\(A\\*\\) at .*\[\r\n\]*.3. A::method\\(int\\) at .*\[\r\n\]*\[\r\n\]*.4. A::method\\(\\) at .*\[\r\n\]*> $" {
+ -re ".0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. .*:A::method\\(A\\*\\)\[\r\n\]*.3. .*:A::method\\(int\\)\[\r\n\]*.4. .*:A::method\\(\\)\[\r\n\]*> $" {
gdb_test "0" \
"canceled" \
"breaking in method ($lang)"
diff --git a/gdb/testsuite/gdb.cp/ovldbreak.exp b/gdb/testsuite/gdb.cp/ovldbreak.exp
index f5d4051..f5b41ab 100644
--- a/gdb/testsuite/gdb.cp/ovldbreak.exp
+++ b/gdb/testsuite/gdb.cp/ovldbreak.exp
@@ -130,18 +130,18 @@ proc set_bp_overloaded {name expectedmenu mychoice bpnumber linenumber} {
set menu_overload1arg "\\\[0\\\] cancel\r\n"
append menu_overload1arg "\\\[1\\\] all\r\n"
-append menu_overload1arg "\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n"
-append menu_overload1arg "\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n"
-append menu_overload1arg "\\\[4\\\] foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r\n"
-append menu_overload1arg "\\\[5\\\] foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r\n"
-append menu_overload1arg "\\\[6\\\] foo::overload1arg\\((unsigned int|unsigned)\\) at.*$srcfile:117\r\n"
-append menu_overload1arg "\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n"
-append menu_overload1arg "\\\[8\\\] foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r\n"
-append menu_overload1arg "\\\[9\\\] foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r\n"
-append menu_overload1arg "\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n"
-append menu_overload1arg "\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n"
-append menu_overload1arg "\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n"
-append menu_overload1arg "\\\[13\\\] foo::overload1arg\\((void|)\\) at.*$srcfile:110\r\n"
+append menu_overload1arg "\\\[2\\\] .*$srcfile:foo::overload1arg\\(double\\)\r\n"
+append menu_overload1arg "\\\[3\\\] .*$srcfile:foo::overload1arg\\(float\\)\r\n"
+append menu_overload1arg "\\\[4\\\] .*$srcfile:foo::overload1arg\\((unsigned long|long unsigned)( int)?\\)\r\n"
+append menu_overload1arg "\\\[5\\\] .*$srcfile:foo::overload1arg\\(long( int)?\\)\r\n"
+append menu_overload1arg "\\\[6\\\] .*$srcfile:foo::overload1arg\\((unsigned int|unsigned)\\)\r\n"
+append menu_overload1arg "\\\[7\\\] .*$srcfile:foo::overload1arg\\(int\\)\r\n"
+append menu_overload1arg "\\\[8\\\] .*$srcfile:foo::overload1arg\\((unsigned short|short unsigned)( int)?\\)\r\n"
+append menu_overload1arg "\\\[9\\\] .*$srcfile:foo::overload1arg\\(short( int)?\\)\r\n"
+append menu_overload1arg "\\\[10\\\] .*$srcfile:foo::overload1arg\\(unsigned char\\)\r\n"
+append menu_overload1arg "\\\[11\\\] .*$srcfile:foo::overload1arg\\(signed char\\)\r\n"
+append menu_overload1arg "\\\[12\\\] .*$srcfile:foo::overload1arg\\(char\\)\r\n"
+append menu_overload1arg "\\\[13\\\] .*$srcfile:foo::overload1arg\\((void|)\\)\r\n"
append menu_overload1arg "> $"
# Set multiple-symbols to "ask", to allow us to test the use
@@ -279,7 +279,7 @@ gdb_expect {
# Choose all.
send_gdb "1\n"
gdb_expect {
- -re "Breakpoint $decimal at $hex: file.*$srcfile, line 121.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 120.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 119.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 118.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 117.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 116.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 115.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 114.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 113.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 112.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 111.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 110.\r\nwarning: Multiple breakpoints were set.\r\nUse the .delete. command to delete unwanted breakpoints.\r\n$gdb_prompt $" {
+ -re "Breakpoint $decimal at $hex: foo::overload1arg. .12 locations.\r\n.*$gdb_prompt $" {
pass "set bp on overload1arg all"
}
-re ".*$gdb_prompt $" {
@@ -306,18 +306,19 @@ gdb_expect {
gdb_test "info break" \
"Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((void|)\\) at.*$srcfile:110" \
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+<MULTIPLE>\[\t \]*\r
+\[0-9\]+.1\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
+\[0-9\]+.2\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
+\[0-9\]+.3\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r
+\[0-9\]+.4\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r
+\[0-9\]+.5\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r
+\[0-9\]+.6\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+.7\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r
+\[0-9\]+.8\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r
+\[0-9\]+.9\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+.10\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+.11\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+.12\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((void|)\\) at.*$srcfile:110" \
"breakpoint info (after setting on all)"
@@ -333,10 +334,10 @@ proc continue_to_bp_overloaded {might_kfail bpnumber argtype actuals} {
send_gdb "continue\n"
gdb_expect {
- -re "Continuing.\r\n\r\nBreakpoint ${bpnumber}, (${hex} in )?foo::overload1arg(\\(${argtype}\\))? \\(this=${hex}(, )?${actuals}\\) at.*${srcfile}:${decimal}\r\n${decimal}\[\t \]+int foo::overload1arg \\(${argtype}( arg)?\\).*\r\n.*$gdb_prompt $" {
+ -re "Continuing.\r\n\r\nBreakpoint ${bpnumber}, foo::overload1arg \\(this=${hex}(, )?${actuals}\\) at.*${srcfile}:${decimal}\r\n${decimal}\[\t \]+int foo::overload1arg \\(${argtype}( arg)?\\).*\r\n.*$gdb_prompt $" {
pass "continue to bp overloaded : ${argtype}"
}
- -re "Continuing.\r\n\r\nBreakpoint ${bpnumber}, (${hex} in )?foo::overload1arg(\\(${argtype}\\))? \\(this=${hex}, arg=.*\\) at.*${srcfile}:${decimal}\r\n${decimal}\[\t \]+int foo::overload1arg \\(${argtype}( arg)?\\).*\r\n.*$gdb_prompt $" {
+ -re "Continuing.\r\n\r\nBreakpoint ${bpnumber}, foo::overload1arg \\(this=${hex}, arg=.*\\) at.*${srcfile}:${decimal}\r\n${decimal}\[\t \]+int foo::overload1arg \\(${argtype}( arg)?\\).*\r\n.*$gdb_prompt $" {
if $might_kfail {
kfail "gdb/1025" "continue to bp overloaded : ${argtype}"
} else {
@@ -352,17 +353,17 @@ proc continue_to_bp_overloaded {might_kfail bpnumber argtype actuals} {
}
}
-continue_to_bp_overloaded 0 25 "(void|)" ""
-continue_to_bp_overloaded 1 24 "char" "arg=2 \\'\\\\002\\'"
-continue_to_bp_overloaded 1 23 "signed char" "arg=3 \\'\\\\003\\'"
-continue_to_bp_overloaded 1 22 "unsigned char" "arg=4 \\'\\\\004\\'"
-continue_to_bp_overloaded 1 21 "short" "arg=5"
-continue_to_bp_overloaded 1 20 "unsigned short" "arg=6"
-continue_to_bp_overloaded 0 19 "int" "arg=7"
-continue_to_bp_overloaded 0 18 "(unsigned|unsigned int)" "arg=8"
-continue_to_bp_overloaded 0 17 "long" "arg=9"
-continue_to_bp_overloaded 0 16 "unsigned long" "arg=10"
-continue_to_bp_overloaded 0 15 "float" "arg=100"
+continue_to_bp_overloaded 0 14 "(void|)" ""
+continue_to_bp_overloaded 1 14 "char" "arg=2 \\'\\\\002\\'"
+continue_to_bp_overloaded 1 14 "signed char" "arg=3 \\'\\\\003\\'"
+continue_to_bp_overloaded 1 14 "unsigned char" "arg=4 \\'\\\\004\\'"
+continue_to_bp_overloaded 1 14 "short" "arg=5"
+continue_to_bp_overloaded 1 14 "unsigned short" "arg=6"
+continue_to_bp_overloaded 0 14 "int" "arg=7"
+continue_to_bp_overloaded 0 14 "(unsigned|unsigned int)" "arg=8"
+continue_to_bp_overloaded 0 14 "long" "arg=9"
+continue_to_bp_overloaded 0 14 "unsigned long" "arg=10"
+continue_to_bp_overloaded 0 14 "float" "arg=100"
continue_to_bp_overloaded 1 14 "double" "arg=200"
# Test breaking on an overloaded function when multiple-symbols
@@ -375,7 +376,7 @@ gdb_test "break foo::foofunc" \
# is set to "all"
gdb_test_no_output "set multiple-symbols all"
gdb_test "break foo::foofunc" \
- "Breakpoint \[0-9\]+ at ${hex}: file .*ovldbreak\\.cc, line \[0-9\]+\\.\r\nBreakpoint \[0-9\]+ at ${hex}: file .*ovldbreak\\.cc, line \[0-9\]+\\.\r\nwarning: Multiple breakpoints were set\\.\r\nUse the \"delete\" command to delete unwanted breakpoints\\."
+ "Breakpoint \[0-9\]+ at ${hex}: foo::foofunc. .2 locations..*"
# That's all, folks.
diff --git a/gdb/testsuite/gdb.cp/ovsrch.exp b/gdb/testsuite/gdb.cp/ovsrch.exp
index b509a25..f6ad34b 100644
--- a/gdb/testsuite/gdb.cp/ovsrch.exp
+++ b/gdb/testsuite/gdb.cp/ovsrch.exp
@@ -49,7 +49,7 @@ proc test_class {class} {
# Test whether open parentheses are correctly identified as overload
# information or conditional.
- gdb_test "break ${class}::foo if (a == 3)" "Breakpoint (\[0-9\]).*"
+ gdb_test "break ${class}::hibob if (a_param == 3)" "Breakpoint (\[0-9\]).*"
}
if { [skip_cplus_tests] } { continue }
@@ -73,28 +73,28 @@ if {![runto_main]} {
}
# Break in A::stop_here and run tests.
-if {[gdb_breakpoint "stop_here"]} {
- pass "break stop_here"
+if {[gdb_breakpoint "A::stop_here"]} {
+ pass "break A::stop_here"
}
-if {[gdb_breakpoint "'stop_here'"]} {
- pass "break 'stop_here'"
+if {[gdb_breakpoint "'A::stop_here'"]} {
+ pass "break 'A::stop_here'"
}
gdb_continue_to_breakpoint "stop_here"
-test_class outer
+test_class A::outer
# Break in A::B::stop_here_too and run tests.
-if {[gdb_breakpoint "B::stop_here_too"]} {
- pass "break B::stop_here_too"
+if {[gdb_breakpoint "A::B::stop_here_too"]} {
+ pass "break A::B::stop_here_too"
}
-if {[gdb_breakpoint "'B::stop_here_too'"]} {
- pass "break 'B::stop_here_too'"
+if {[gdb_breakpoint "'A::B::stop_here_too'"]} {
+ pass "break 'A::B::stop_here_too'"
}
gdb_continue_to_breakpoint "stop_here_too"
-test_class inner
+test_class A::B::inner
gdb_exit
return 0
diff --git a/gdb/testsuite/gdb.cp/ovsrch.h b/gdb/testsuite/gdb.cp/ovsrch.h
index b2e518d..983b51e 100644
--- a/gdb/testsuite/gdb.cp/ovsrch.h
+++ b/gdb/testsuite/gdb.cp/ovsrch.h
@@ -24,6 +24,8 @@ namespace A
void foo (int) const;
void foo (char *) const;
bool func (void) { return true; }
+ void hibob (int) const;
+ void hibob (char *) const;
};
namespace B
@@ -34,6 +36,8 @@ namespace A
void foo (void) const;
void foo (int) const;
void foo (char *) const;
+ void hibob (int) const;
+ void hibob (char *) const;
};
}
}
diff --git a/gdb/testsuite/gdb.cp/ovsrch3.cc b/gdb/testsuite/gdb.cp/ovsrch3.cc
index e6e38a4..a7d9551 100644
--- a/gdb/testsuite/gdb.cp/ovsrch3.cc
+++ b/gdb/testsuite/gdb.cp/ovsrch3.cc
@@ -18,11 +18,21 @@
#include "ovsrch.h"
void
-A::outer::foo (int a) const
+A::outer::foo (int a_param) const
{
}
void
-A::B::inner::foo (int a) const
+A::B::inner::foo (int a_param) const
+{
+}
+
+void
+A::outer::hibob (int a_param) const
+{
+}
+
+void
+A::B::inner::hibob (int a_param) const
{
}
diff --git a/gdb/testsuite/gdb.cp/ovsrch4.cc b/gdb/testsuite/gdb.cp/ovsrch4.cc
index 2f0c1a6..5bb08b3 100644
--- a/gdb/testsuite/gdb.cp/ovsrch4.cc
+++ b/gdb/testsuite/gdb.cp/ovsrch4.cc
@@ -18,11 +18,21 @@
#include "ovsrch.h"
void
-A::outer::foo (char *a) const
+A::outer::foo (char *a_param) const
{
}
void
-A::B::inner::foo (char *a) const
+A::B::inner::foo (char *a_param) const
+{
+}
+
+void
+A::outer::hibob (char *a_param) const
+{
+}
+
+void
+A::B::inner::hibob (char *a_param) const
{
}
diff --git a/gdb/testsuite/gdb.cp/re-set-overloaded.exp b/gdb/testsuite/gdb.cp/re-set-overloaded.exp
index 2052552..bd5f3ba 100644
--- a/gdb/testsuite/gdb.cp/re-set-overloaded.exp
+++ b/gdb/testsuite/gdb.cp/re-set-overloaded.exp
@@ -46,7 +46,6 @@ gdb_test_no_output {set variable $brk = $bpnum}
# runto or runto_main would call delete_breakpoints.
gdb_breakpoint "main"
gdb_run_cmd
-setup_kfail breakpoints/11657 *-*-*
gdb_test "" ".*" "start"
set test "breakpoint resolved"
diff --git a/gdb/testsuite/gdb.cp/templates.exp b/gdb/testsuite/gdb.cp/templates.exp
index 6612b4a..8a68f25 100644
--- a/gdb/testsuite/gdb.cp/templates.exp
+++ b/gdb/testsuite/gdb.cp/templates.exp
@@ -109,12 +109,7 @@ proc test_template_breakpoints {} {
global hp_aCC_compiler
gdb_test_multiple "break T5<int>::T5" "constructor breakpoint" {
- -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. T5<int>::T5\\(int\\) at .*\[\r\n\]*.3. T5<int>::T5\\((T5<int> const|const T5<int>) ?&\\) at .*\[\r\n\]*> $" {
- gdb_test "0" \
- "canceled" \
- "constructor breakpoint (obsolete format!)"
- }
- -re ".0. cancel\[\r\n\]*.1. all\[\r\n\]*.2. T5<int>::T5\\((T5<int> const|const T5<int>) ?&\\) at .*templates.cc:.*\[\r\n\]*.3. T5<int>::T5\\(int\\) at .*templates.cc:.*\[\r\n\]*> $" {
+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2.*templates.cc:T5<int>::T5\\((T5<int> const|const T5<int>) ?&\\)\[\r\n\]*.3.*templates.cc:T5<int>::T5\\(int\\)\[\r\n\]*> $" {
gdb_test "0" \
"canceled" \
"constructor breakpoint"
@@ -152,9 +147,26 @@ proc test_template_breakpoints {} {
set bp_location [gdb_get_line_number \
"set breakpoint on a line with no real code"]
- gdb_test "break ${testfile}.cc:${bp_location}" \
- "Breakpoint.*at.* file .*${testfile}.cc, line.*(2 locations).*" \
- "breakpoint on a line with no real code"
+
+ gdb_test_multiple "break ${testfile}.cc:${bp_location}" \
+ "breakpoint on a line with no real code" {
+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2.*templates.cc:GetMax<int>\\(int, int\\)\[\r\n\]*.3.*templates.cc:GetMax<long>\\(long, long\\)\[\r\n\]*> $" {
+ gdb_test "0" \
+ "canceled" \
+ "breakpoint on a line with no real code"
+ }
+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2.*\[\r\n\]*.3.*\[\r\n\]*> $" {
+ gdb_test "0" \
+ "nonsense intended to insure that this test fails" \
+ "breakpoint on a line with no real code"
+ }
+ -re ".*\n> $" {
+ gdb_test "0" \
+ "nonsense intended to insure that this test fails" \
+ "breakpoint on a line with no real code"
+ }
+ }
+
delete_breakpoints
}
@@ -168,7 +180,7 @@ proc test_template_calls {} {
if [target_info exists gdb,cannot_call_functions] {
setup_xfail "*-*-*" 2416
- fail "This target can not call functions"
+fail "This target can not call functions"
return
}
diff --git a/gdb/testsuite/gdb.linespec/Makefile.in b/gdb/testsuite/gdb.linespec/Makefile.in
new file mode 100644
index 0000000..2658a24
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/Makefile.in
@@ -0,0 +1,14 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+EXECUTABLES = lspec
+
+all info install-info dvi install uninstall installcheck check:
+ @echo "Nothing to be done for $@..."
+
+clean mostlyclean:
+ -rm -f *~ *.o *.ci
+ -rm -f core $(EXECUTABLES)
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log gdb.log gdb.sum
diff --git a/gdb/testsuite/gdb.linespec/base/one/thefile.cc b/gdb/testsuite/gdb.linespec/base/one/thefile.cc
new file mode 100644
index 0000000..f8712c2
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/base/one/thefile.cc
@@ -0,0 +1,20 @@
+/* The commented line must have the same line number in the other
+ "thefile.c". */
+
+#define WANT_F1
+#include "../../lspec.h"
+
+
+
+
+
+
+int m(int x)
+{
+ return x + 23; /* thefile breakpoint */
+}
+
+int NameSpace::overload(int x)
+{
+ return x + 23;
+}
diff --git a/gdb/testsuite/gdb.linespec/base/two/thefile.cc b/gdb/testsuite/gdb.linespec/base/two/thefile.cc
new file mode 100644
index 0000000..ffca87a
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/base/two/thefile.cc
@@ -0,0 +1,20 @@
+/* The commented line must have the same line number in the other
+ "thefile.c". */
+
+#define WANT_F2
+#include "../../lspec.h"
+
+static int dupname(int y)
+{
+ label: return y;
+}
+
+int n(int y)
+{
+ return dupname(y) - 23; /* thefile breakpoint */
+}
+
+int NameSpace::overload(double x)
+{
+ return (int) x - 23;
+}
diff --git a/gdb/testsuite/gdb.linespec/body.h b/gdb/testsuite/gdb.linespec/body.h
new file mode 100644
index 0000000..e8765f6
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/body.h
@@ -0,0 +1,5 @@
+/* This is included directly into the body of a function. */
+
+/* body breakpoint no code */
+
+return x;
diff --git a/gdb/testsuite/gdb.linespec/linespec.exp b/gdb/testsuite/gdb.linespec/linespec.exp
new file mode 100644
index 0000000..440233a
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/linespec.exp
@@ -0,0 +1,117 @@
+# Copyright 2011 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/>.
+
+# Tests of ambiguous linespecs.
+
+set testfile linespec
+
+set exefile lspec
+set binfile ${objdir}/${subdir}/${exefile}
+
+set baseone base/one/thefile.cc
+set basetwo base/two/thefile.cc
+
+if {[skip_cplus_tests]} {
+ unsupported linespec.exp
+ return
+}
+
+if {[prepare_for_testing ${testfile}.exp $exefile \
+ [list lspec.cc $baseone $basetwo] \
+ {debug nowarnings}]} {
+ return -1
+}
+
+gdb_test_no_output "set multiple-symbols all" \
+ "set multiple-symbols to all for linespec tests"
+
+set l1 [gdb_get_line_number "thefile breakpoint" $baseone]
+set l2 [gdb_get_line_number "thefile breakpoint" $basetwo]
+
+if {$l1 != $l2} {
+ error "somebody incompatibly modified the source files needed by linespec.exp"
+}
+
+gdb_test "break thefile.cc:$l1" \
+ "Breakpoint 1 at $hex: thefile.cc:$l1. \[(\]2 locations\[)\]" \
+ "multi-location break using file:line"
+
+# We'd like this to work, but it currently does not.
+# gdb_test "break one/thefile.cc:$l1"
+
+gdb_test "break dupname" \
+ "Breakpoint 2 at $hex: dupname. \[(\]2 locations\[)\]" \
+ "multi-location break using duplicate function name"
+
+gdb_test "break dupname:label" \
+ "Breakpoint 3 at $hex: dupname:label. \[(\]2 locations\[)\]" \
+ "multi-location break using duplicate function name and label"
+
+gdb_test_no_output "set breakpoint pending off" \
+ "disable pending breakpoints for linespec tests"
+
+# This is PR breakpoints/12856.
+gdb_test "break lspec.cc:nosuchfunction" \
+ "Function \"nosuchfunction\" not defined in \"lspec.cc\"." \
+ "set breakpoint on non-existent function"
+
+gdb_test "break NameSpace::overload" \
+ "Breakpoint \[0-9\]+ at $hex: NameSpace::overload. \[(\]3 locations\[)\]" \
+ "set breakpoint at all instances of NameSpace::overload"
+
+gdb_test "break lspec.cc:NameSpace::overload" \
+ "Breakpoint \[0-9\]+ at $hex: file .*lspec.cc, line 7." \
+ "set breakpoint at lspec.cc instance of NameSpace::overload"
+
+gdb_test "break lspec.cc:NameSpace::overload(double)" \
+ "Function \"NameSpace::overload\\(double\\)\" not defined in \"lspec.cc\"." \
+ "set breakpoint at non-existent lspec.cc instance of NameSpace::overload"
+
+gdb_test "break NameSpace::overload()" \
+ "Breakpoint \[0-9\]+ at $hex: file .*lspec.cc, line 7." \
+ "set breakpoint at specific instance of NameSpace::overload"
+
+# This should manage to set a breakpoint even though body.h does not
+# include all of the function in question.
+set line [gdb_get_line_number "body breakpoint no code" body.h]
+gdb_test "break body.h:$line" \
+ "Breakpoint \[0-9\]+.*" \
+ "set breakpoint in body.h"
+
+# This should only have a single location -- in f1.
+set line [gdb_get_line_number "f1 breakpoint" lspec.h]
+gdb_test "break lspec.h:$line" \
+ "Breakpoint \[0-9\]+ at $hex: file .*lspec.h, line $line." \
+ "set breakpoint in f1"
+
+#
+# Multi-inferior tests.
+#
+
+gdb_test "add-inferior" "Added inferior 2" \
+ "add inferior for linespec tests"
+
+gdb_test "inferior 2" "Switching to inferior 2 .*" \
+ "switch to inferior 2 for linespec tests"
+
+# Note that in particular this should not cause errors when re-setting
+# breakpoints.
+gdb_test "file $binfile" \
+ "Reading symbols from .*done." \
+ "set the new inferior file for linespec tests"
+
+gdb_test "break main" \
+ "Breakpoint \[0-9\]+ at $hex: main. .2 locations." \
+ "set breakpoint at main in both inferiors"
diff --git a/gdb/testsuite/gdb.linespec/lspec.cc b/gdb/testsuite/gdb.linespec/lspec.cc
new file mode 100644
index 0000000..b1092e2
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/lspec.cc
@@ -0,0 +1,19 @@
+#include "lspec.h"
+
+static int dupname (int x) { label: return x; }
+
+int NameSpace::overload()
+{
+ return 23;
+}
+
+int body_elsewhere()
+{
+ int x = 5;
+#include "body.h"
+}
+
+int main()
+{
+ return dupname(0) + m(0) + n(0) + f1() + f2() + body_elsewhere();
+}
diff --git a/gdb/testsuite/gdb.linespec/lspec.h b/gdb/testsuite/gdb.linespec/lspec.h
new file mode 100644
index 0000000..0a647fa
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/lspec.h
@@ -0,0 +1,26 @@
+extern int m(int x);
+extern int n(int y);
+
+namespace NameSpace {
+ int overload ();
+ int overload (int);
+ int overload (double);
+};
+
+#ifdef WANT_F1
+int f1(void)
+{
+ return 1; /* f1 breakpoint */
+}
+#else
+extern int f1(void);
+#endif
+
+#ifdef WANT_F2
+int f2(void)
+{
+ return 1; /* f2 breakpoint */
+}
+#else
+extern int f2(void);
+#endif
diff --git a/gdb/testsuite/gdb.objc/objcdecode.exp b/gdb/testsuite/gdb.objc/objcdecode.exp
index 720bfd8..e3916f6 100644
--- a/gdb/testsuite/gdb.objc/objcdecode.exp
+++ b/gdb/testsuite/gdb.objc/objcdecode.exp
@@ -52,17 +52,19 @@ proc do_objc_tests {} {
do_objc_tests
+gdb_test_no_output "set multiple-symbols ask"
+
#
# Break on multiply defined method (PR objc/1236)
#
set name "break on multiply defined method"
gdb_test_multiple "break multipleDef" $name \
{
- -re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] -.Decode multipleDef. at .*\r\n\\\[3\\\] multipleDef at .*\r\n> $" {
+ -re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] .*${srcfile}:-.Decode multipleDef.\r\n\\\[3\\\] .*${srcfile}:multipleDef\r\n> $" {
send_gdb "3\n"
exp_continue
}
- -re "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*\r\n$gdb_prompt $" { pass $name }
+ -re "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: .*\r\n$gdb_prompt $" { pass $name }
-re ".*$gdb_prompt $" { kfail "gdb/1236" $name }
}
diff --git a/gdb/testsuite/gdb.trace/tracecmd.exp b/gdb/testsuite/gdb.trace/tracecmd.exp
index 679cc32..89a2e24 100644
--- a/gdb/testsuite/gdb.trace/tracecmd.exp
+++ b/gdb/testsuite/gdb.trace/tracecmd.exp
@@ -74,6 +74,7 @@ gdb_test "info trace" "in gdb_recursion_test.*$srcfile:$testline2" \
# 1.2 trace invalid source line
gdb_delete_tracepoints
+gdb_test_no_output "set breakpoint pending off"
gdb_test "trace $srcfile:99999" "No line 99999 in file \".*$srcfile\"." \
"1.2a: trace invalid line in sourcefile"
gdb_test "info trace" "No tracepoints.*" \
@@ -81,7 +82,6 @@ gdb_test "info trace" "No tracepoints.*" \
# 1.3 trace line in invalid source file
gdb_delete_tracepoints
-gdb_test_no_output "set breakpoint pending off"
gdb_test "trace NoSuChFiLe.c:1" "No source file named NoSuChFiLe.c." \
"1.3a: trace invalid source file"
gdb_test "info trace" "No tracepoints.*" \
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index a2e2cd4..e00538c 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -2456,7 +2456,7 @@ trace_find_line_command (char *args, int from_tty)
}
else
{
- sals = decode_line_spec (args, 1);
+ sals = decode_line_spec (args, DECODE_LINE_FUNFIRSTLINE);
sal = sals.sals[0];
}
@@ -2584,7 +2584,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, DECODE_LINE_FUNFIRSTLINE, NULL, 0);
if (sals.nelts == 0)
return; /* Presumably decode_line_1 has already warned. */
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index 4c8658d..9b936e1 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -455,29 +455,34 @@ tui_update_breakpoint_info (struct tui_win_info *win,
bp != (struct breakpoint *) NULL;
bp = bp->next)
{
+ struct bp_location *loc;
+
gdb_assert (line->line_or_addr.loa == LOA_LINE
|| line->line_or_addr.loa == LOA_ADDRESS);
- if ((win == TUI_SRC_WIN
- && bp->source_file
- && (filename_cmp (src->filename, bp->source_file) == 0)
- && line->line_or_addr.loa == LOA_LINE
- && bp->line_number == line->line_or_addr.u.line_no)
- || (win == TUI_DISASM_WIN
- && line->line_or_addr.loa == LOA_ADDRESS
- && bp->loc != NULL
- && bp->loc->address == line->line_or_addr.u.addr))
- {
- if (bp->enable_state == bp_disabled)
- mode |= TUI_BP_DISABLED;
- else
- mode |= TUI_BP_ENABLED;
- if (bp->hit_count)
- mode |= TUI_BP_HIT;
- if (bp->loc->cond)
- mode |= TUI_BP_CONDITIONAL;
- if (bp->type == bp_hardware_breakpoint)
- mode |= TUI_BP_HARDWARE;
- }
+
+ for (loc = bp->loc; loc != NULL; loc = loc->next)
+ {
+ if ((win == TUI_SRC_WIN
+ && loc->source_file
+ && (filename_cmp (src->filename, loc->source_file) == 0)
+ && line->line_or_addr.loa == LOA_LINE
+ && loc->line_number == line->line_or_addr.u.line_no)
+ || (win == TUI_DISASM_WIN
+ && line->line_or_addr.loa == LOA_ADDRESS
+ && loc->address == line->line_or_addr.u.addr))
+ {
+ if (bp->enable_state == bp_disabled)
+ mode |= TUI_BP_DISABLED;
+ else
+ mode |= TUI_BP_ENABLED;
+ if (bp->hit_count)
+ mode |= TUI_BP_HIT;
+ if (bp->loc->cond)
+ mode |= TUI_BP_CONDITIONAL;
+ if (bp->type == bp_hardware_breakpoint)
+ mode |= TUI_BP_HARDWARE;
+ }
+ }
}
if (line->has_break != mode)
{
diff --git a/gdb/utils.c b/gdb/utils.c
index a43b13d..cc93915 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -3651,6 +3651,17 @@ compare_positive_ints (const void *ap, const void *bp)
return * (int *) ap - * (int *) bp;
}
+/* String compare function for qsort. */
+
+int
+compare_strings (const void *arg1, const void *arg2)
+{
+ const char **s1 = (const char **) arg1;
+ const char **s2 = (const char **) arg2;
+
+ return strcmp (*s1, *s2);
+}
+
#define AMBIGUOUS_MESS1 ".\nMatching formats:"
#define AMBIGUOUS_MESS2 \
".\nUse \"set gnutarget format-name\" to specify the format."
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: ada patch --]
[-- Type: text/x-patch, Size: 9297 bytes --]
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index e396596..e5dbf61 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -5052,6 +5052,35 @@ done:
return ndefns;
}
+/* Implementation of the la_iterate_over_symbols method. */
+
+static void
+ada_iterate_over_symbols (const char *name, domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data)
+{
+ int ndefs, i;
+ struct ada_symbol_info *results;
+ char *canon;
+ int nlen = strlen (name);
+
+ if (name[0] == '<' && name[nlen - 1] == '>')
+ {
+ canon = alloca (nlen - 1);
+ memcpy (canon, name + 1, nlen - 2);
+ canon[nlen - 2] = '\0';
+ }
+ else
+ canon = ada_encode (ada_fold_name (name));
+
+ ndefs = ada_lookup_symbol_list (canon, NULL, domain, &results);
+ for (i = 0; i < ndefs; ++i)
+ {
+ if (! (*callback) (results[i].sym, data))
+ break;
+ }
+}
+
struct symbol *
ada_lookup_encoded_symbol (const char *name, const struct block *block0,
domain_enum namespace, struct block **block_found)
@@ -12282,6 +12311,7 @@ const struct language_defn ada_language_defn = {
ada_print_array_index,
default_pass_by_reference,
c_get_string,
+ ada_iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 3a35a78..b9101d3 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -863,6 +863,7 @@ const struct language_defn c_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ NULL,
LANG_MAGIC
};
@@ -984,6 +985,7 @@ const struct language_defn cplus_language_defn =
default_print_array_index,
cp_pass_by_reference,
c_get_string,
+ NULL,
LANG_MAGIC
};
@@ -1023,6 +1025,7 @@ const struct language_defn asm_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ NULL,
LANG_MAGIC
};
@@ -1067,6 +1070,7 @@ const struct language_defn minimal_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ NULL,
LANG_MAGIC
};
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index c0599a5..44ff68a 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -273,6 +273,7 @@ static const struct language_defn d_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ NULL,
LANG_MAGIC
};
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index f538eee..fb48069 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -309,6 +309,7 @@ const struct language_defn f_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ NULL,
LANG_MAGIC
};
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index 4eae356..e957255 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1197,6 +1197,7 @@ const struct language_defn java_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ NULL,
LANG_MAGIC
};
diff --git a/gdb/language.c b/gdb/language.c
index 825c02d..d798c38 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -1200,6 +1200,7 @@ const struct language_defn unknown_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ NULL,
LANG_MAGIC
};
@@ -1241,6 +1242,7 @@ const struct language_defn auto_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ NULL,
LANG_MAGIC
};
@@ -1280,6 +1282,7 @@ const struct language_defn local_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ NULL,
LANG_MAGIC
};
\f
diff --git a/gdb/language.h b/gdb/language.h
index 1ff575f..ede6a92 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -318,6 +318,19 @@ struct language_defn
void (*la_get_string) (struct value *value, gdb_byte **buffer, int *length,
struct type **chartype, const char **charset);
+ /* Find all symbols in the current program space matching NAME in
+ DOMAIN, according to this language's rules. For each one, call
+ CALLBACK with the symbol and the DATA argument. If CALLBACK
+ returns zero, the iteration ends at that point.
+
+ This field can be NULL, meaning that this language doesn't need
+ any special code aside from ordinary searches of the symbol
+ table. */
+ void (*la_iterate_over_symbols) (const char *name,
+ domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data);
+
/* Add fields above this point, so the magic number is always last. */
/* Magic number for compat checking. */
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 2b35dc1..06b1dd2 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -376,6 +376,10 @@ iterate_over_all_matching_symtabs (const char *name,
}
}
}
+
+ if (current_language->la_iterate_over_symbols)
+ (*current_language->la_iterate_over_symbols) (name, domain,
+ callback, data);
}
}
@@ -2205,28 +2209,6 @@ find_function_symbols (char **argptr, char *p, int is_quote_enclosed,
iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
collect_function_symbols, &result, NULL);
- /* If looking up the given name failed, try using the current
- language to look up a symbol. This may augment the search. If a
- symbol is found this way, repeat the iteration, but using the
- discovered name. */
- if (VEC_empty (symbolp, result)
- && current_language->la_language == language_ada)
- {
- struct symbol *function_symbol;
-
- function_symbol = lookup_symbol (copy, get_selected_block (0),
- VAR_DOMAIN, 0);
- if (function_symbol && SYMBOL_CLASS (function_symbol) == LOC_BLOCK)
- {
- xfree (copy);
- copy = xstrdup (SYMBOL_SEARCH_NAME (function_symbol));
- *user_function = copy;
- iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
- collect_function_symbols,
- &result, NULL);
- }
- }
-
if (VEC_empty (symbolp, result))
VEC_free (symbolp, result);
else
@@ -2855,22 +2837,6 @@ decode_variable (struct linespec_state *self, char *copy)
add_matching_symbols_to_info (lookup_name, &info, NULL);
- /* If looking up the given name failed, try using the current
- language to look up a symbol. This may augment the search. If a
- symbol is found this way, repeat the iteration, but using the
- discovered name. */
- if (info.result.nelts == 0 && current_language->la_language == language_ada)
- {
- struct symbol *sym;
-
- sym = lookup_symbol (lookup_name, get_selected_block (0), VAR_DOMAIN, 0);
- if (sym)
- {
- copy = SYMBOL_SEARCH_NAME (sym);
- add_matching_symbols_to_info (copy, &info, NULL);
- }
- }
-
if (info.result.nelts > 0)
{
if (self->canonical)
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index f83c622..52c592a 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -401,6 +401,7 @@ const struct language_defn m2_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ NULL,
LANG_MAGIC
};
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index dcf9459..b5024b6 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -541,6 +541,7 @@ const struct language_defn objc_language_defn = {
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ NULL,
LANG_MAGIC
};
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 05955b4..43791ea 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1024,6 +1024,7 @@ const struct language_defn opencl_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ NULL,
LANG_MAGIC
};
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 655279b..76ec4b9 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -459,6 +459,7 @@ const struct language_defn pascal_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ NULL,
LANG_MAGIC
};
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index cd3ca73..62384b0 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-22 Tom Tromey <tromey@redhat.com>
+
+ * gdb.ada/homonym.exp: Add two breakpoint tests.
+
2011-11-18 Tom Tromey <tromey@redhat.com>
* gdb.base/solib-weak.exp (do_test): Remove kfail.
diff --git a/gdb/testsuite/gdb.ada/homonym.exp b/gdb/testsuite/gdb.ada/homonym.exp
index b5dff1b..c58657a 100644
--- a/gdb/testsuite/gdb.ada/homonym.exp
+++ b/gdb/testsuite/gdb.ada/homonym.exp
@@ -31,6 +31,20 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" }
clean_restart ${testfile}
+
+# Do these tests before running, so we are operating in a known
+# environment.
+
+gdb_test "break Get_Value" \
+ "Breakpoint \[0-9\]+ at $hex: Get_Value. .2 locations." \
+ "set breakpoint at Get_Value"
+
+gdb_test "break <homonym__get_value>" \
+ "Breakpoint \[0-9\]+ at $hex: <homonym__get_value>. .2 locations." \
+ "set breakpoint at <homonym__get_value>"
+
+delete_breakpoints
+
set bp_location [gdb_get_line_number "BREAK_1" ${testdir}/homonym.adb]
runto "homonym.adb:$bp_location"
@@ -86,6 +100,3 @@ gdb_test "ptype lcl" \
gdb_test "print lcl" \
"= 17" \
"print lcl at BREAK_2"
-
-
-
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-28 21:29 ` Tom Tromey
@ 2011-11-29 2:28 ` Joel Brobecker
2011-11-29 2:49 ` iterate_over_symbols should be a wrapper? (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
` (7 subsequent siblings)
8 siblings, 0 replies; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 2:28 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
Hi Tom,
> Here are the latest patches.
Thanks again for sending the patch. Overally, with a few changes
here and there, I am noticing that we're getting very close to what
the AdaCore debugger is capable of in terms of pure-Ada functionality,
and I am very please by that result.
To avoid having one email thread discussing about everything, I think
I'll make one reply per topic. You've fixed a couple of the things
I wanted to talk about, so there might not be many.
We still have a couple of regressions, and I'll let you know which
ones I am planing on working on first, so that, should you decide
to look at some of them, our efforts do not collide.
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* iterate_over_symbols should be a wrapper? (was: "Re: GDB 7.4 branching status? (2011-11-23)")
2011-11-28 21:29 ` Tom Tromey
2011-11-29 2:28 ` Joel Brobecker
@ 2011-11-29 2:49 ` Joel Brobecker
2011-11-29 15:27 ` iterate_over_symbols should be a wrapper? Tom Tromey
2011-11-29 3:07 ` partial-symtab symbol sorting (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
` (6 subsequent siblings)
8 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 2:49 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1730 bytes --]
I noticed that the following linespec does not work for Ada anymore:
(gdb) break FILE:FUNCTION
And that got me into looking how we do symbol matching. When no filename
is provided in the linespec, we call iterate_over_all_matching_symtabs,
which calls iterate_over_symbols over all symtabs, immediately followed
by:
if (current_language->la_iterate_over_symbols)
(*current_language->la_iterate_over_symbols) (name, domain,
So, basically, we do a first pass collecting symbols that follow
a certain matching algorithm, and then we do a second pass for
language that might require a different matching algorithm...
It seems to me that there should be only one, language-specific
matching routine, and iterate_over_symbols should call it.
So, my proposal is to change the profile of la_iterate_over_symbols
to match the iterate_over_symbols routine, and then then set
the la_iterate_over_symbols field to iterate_over_symbols for
all languages except Ada. The changes in ada_iterate_over_symbols
should be straightforward, since ada_lookup_symbol_list accepts
a block as well.
That would solve the problem above as well: When the linespec contains
a filename in it, add_matching_symbols_to_info only calls
iterate_over_symbols:
else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt))
{
[...]
iterate_over_symbols (get_search_block (elt), name,
VAR_DOMAIN, collect_symbols,
info);
}
In the meantime, I applied a different type of patch which just
follows the current approach of doing the generic matching first,
followed by the language-specific one next. Attached is the
corresponding patch.
--
Joel
[-- Attachment #2: 0005-Call-current_language-la_iterate_over_symbols-for-FI.patch --]
[-- Type: text/x-diff, Size: 4304 bytes --]
From a86c5755b965bb1e060130319cb1e09ab2e2d92c Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Fri, 25 Nov 2011 15:21:19 -0800
Subject: [PATCH 5/5] Call current_language->la_iterate_over_symbols for FILE:FUNCTION linespecs
Without this, breakpoints using FILE:FUNCTION linespecs fail
for Ada units. For instance, consider for the following trivial program:
procedure Foo is
begin
null;
end Foo;
Trying to insert a breakpoint on foo.adb:foo fails:
(gdb) b foo.adb:foo
Function "foo" not defined in "foo.adb".
Make breakpoint pending on future shared library load? (y or [n])
This is because the default method of matching symbols does not work
in this case, because the linkage name for procedure "Foo" here is
_ada_foo. We need to apply Ada-specific symbol-name matching.
gdb/ChangeLog:
* linespec.c (add_matching_symbols_to_info): Add call
current_language->la_iterate_over_symbols after call to
iterate_over_symbols.
gdb/testsuite/ChangeLog:
* gdb.ada/file_fun_bp: New testcase.
---
gdb/linespec.c | 4 +++
gdb/testsuite/gdb.ada/file_fun_bp.exp | 32 +++++++++++++++++++++++++++++
gdb/testsuite/gdb.ada/file_fun_bp/foo.adb | 19 +++++++++++++++++
3 files changed, 55 insertions(+), 0 deletions(-)
create mode 100644 gdb/testsuite/gdb.ada/file_fun_bp.exp
create mode 100644 gdb/testsuite/gdb.ada/file_fun_bp/foo.adb
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 146163a..1e713ee 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -2806,6 +2806,10 @@ add_matching_symbols_to_info (const char *name,
iterate_over_symbols (get_search_block (elt), name,
VAR_DOMAIN, collect_symbols,
info);
+ if (current_language->la_iterate_over_symbols)
+ (*current_language->la_iterate_over_symbols) (name, VAR_DOMAIN,
+ collect_symbols,
+ info);
}
}
}
diff --git a/gdb/testsuite/gdb.ada/file_fun_bp.exp b/gdb/testsuite/gdb.ada/file_fun_bp.exp
new file mode 100644
index 0000000..06b757a
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/file_fun_bp.exp
@@ -0,0 +1,32 @@
+# Copyright 2011 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/>.
+
+load_lib "ada.exp"
+
+set testdir "file_fun_bp"
+set testfile "${testdir}/foo"
+set srcfile ${srcdir}/${subdir}/${testfile}.adb
+set binfile ${objdir}/${subdir}/${testfile}
+
+file mkdir ${objdir}/${subdir}/${testdir}
+if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" } {
+ return -1
+}
+
+clean_restart ${testfile}
+
+gdb_test "break foo.adb:foo" \
+ "Breakpoint \[0-9\]+ at 0x\[0-9a-f]+: file .*foo.adb, line \[0-9\]+."
+
diff --git a/gdb/testsuite/gdb.ada/file_fun_bp/foo.adb b/gdb/testsuite/gdb.ada/file_fun_bp/foo.adb
new file mode 100644
index 0000000..6d251fc
--- /dev/null
+++ b/gdb/testsuite/gdb.ada/file_fun_bp/foo.adb
@@ -0,0 +1,19 @@
+-- Copyright 2011 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/>.
+
+procedure Foo is
+begin
+ null;
+end Foo;
--
1.7.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* partial-symtab symbol sorting (was: "Re: GDB 7.4 branching status? (2011-11-23)")
2011-11-28 21:29 ` Tom Tromey
2011-11-29 2:28 ` Joel Brobecker
2011-11-29 2:49 ` iterate_over_symbols should be a wrapper? (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 3:07 ` Joel Brobecker
2011-11-29 8:41 ` Pierre Muller
` (2 more replies)
2011-11-29 3:11 ` multiple-location breakpoint output (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
` (5 subsequent siblings)
8 siblings, 3 replies; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 3:07 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
This is an issue that is only tangential to this patch, and should
not be considered part of the series.
I just realized that partial symbols are sorted using strcmp_iw_ordered.
This works great for C++, for instance, but only works OK for Ada.
I think that this is related to the fact that we might be using
the linkage name, rather than the natural name (we compute the natural
name only on-demand, due to memory pressure in large apps). As a result,
the strcmp_iw_ordered routine can return non-zero for two names that
ada-lang.c:compare_names would consider equal.
For instance: `pck__hello' and `pck__hello__2'.
So when doing a symbol lookup for pck__hello, for instance, we pass
our own comparison routine, which is "compatible" with
strcmp_iw_ordered to the psymtab map_matching_symbols routine.
This allows us to perform a binary search rather than linear one.
I am wondering if we shouldn't be sorting the partial symbols
using a language-specific sorting routine instead. As it turns
out, there was a bug in ada-lang.c:compare_names and that could
have caused the two search orders to diverge. The thing is, when
I looked at it, it's not easy just looking at the partial symtab
what language it is. The language seems to be embedded in the
symbols themselves. And then, we'd still have to specify whether
we'd want to perform a binary search or not anyways. That's because
we permit "wild" matches:
(gdb) break hello
In the case above, we must break on "pck__hello" and "pck__hello__2".
In that case, binary searches based on string comparison cannot work
because we're missing the start of the symbol linkage name.
As an aside: One of the ideas I had in the past was to store the natural
name inverted - for instance "hello.pck" instead of "pck.hello". That
way, searches for hello could be done using binary searches as well.
It might actually allow us to reconcile "wild" vs "non-wild" searches,
and even allow "semi-wild" lookups as in:
(gdb) break subpackage.hello
... would now manage to find matches such as package.subpackage.hello.
This is not the case today. You either fully qualify your symbol name,
or you don't qualify it at all.
But, without even thinking about performance issues at startup, this
approach suffers from the same problem as storing the natural name does:
For certain large applications, we would exceed the maximum amount of
memory a process can hold. This is not necessarily on GNU/Linux, but
the problem is there. I think we'll have better luck we are capable of
merging a bit the massive duplication in the debug info.
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* multiple-location breakpoint output (was: "Re: GDB 7.4 branching status? (2011-11-23)")
2011-11-28 21:29 ` Tom Tromey
` (2 preceding siblings ...)
2011-11-29 3:07 ` partial-symtab symbol sorting (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 3:11 ` Joel Brobecker
2011-11-29 15:06 ` multiple-location breakpoint output Tom Tromey
2011-11-29 3:14 ` decode_digits_line_mode (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
` (4 subsequent siblings)
8 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 3:11 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
Just for the record, I noticed that the output of the "break" command
has been slightly adjusted when inserting a multi-location breakpoint.
Now, instead of printing "file [...], line [...]", it just prints
the linespec itself. Eg:
(gdb) b pck.adb:6
Breakpoint 1 at 0x40213b: pck.adb:6. (3 locations)
Another example, when inserting a breakpoint on a function which
has homonyms:
(gdb) b get_value
Breakpoint 1 at 0x402160: get_value. (2 locations)
This is probably intentional, and I think that it's an improvement,
particularly in the second situation, where each breakpoint corresponds
to different line locations.
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* decode_digits_line_mode (was: "Re: GDB 7.4 branching status? (2011-11-23)")
2011-11-28 21:29 ` Tom Tromey
` (3 preceding siblings ...)
2011-11-29 3:11 ` multiple-location breakpoint output (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 3:14 ` Joel Brobecker
2011-11-29 14:56 ` decode_digits_line_mode Tom Tromey
2011-11-29 3:19 ` [RFA/commit/testcase] "info line" should not skip prologues (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
` (3 subsequent siblings)
8 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 3:14 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
One tiny suggestion:
s/decode_digits_line_mode/decode_digits_list_mode/
The function documentation talks about 'list_mode', and the call
to that function also checks self->list_mode:
if (self->list_mode)
decode_digits_line_mode (self, &values, val);
...
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* [RFA/commit/testcase] "info line" should not skip prologues (was: "Re: GDB 7.4 branching status? (2011-11-23)")
2011-11-28 21:29 ` Tom Tromey
` (4 preceding siblings ...)
2011-11-29 3:14 ` decode_digits_line_mode (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 3:19 ` Joel Brobecker
2011-11-29 15:03 ` [RFA/commit/testcase] "info line" should not skip prologues Tom Tromey
2011-11-29 3:22 ` GDB 7.4 branching status? (2011-11-23) Joel Brobecker
` (2 subsequent siblings)
8 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 3:19 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1186 bytes --]
This is an issue that I discovered in your previous set of patches, but
got fixed in this iteration :-). Nonetheless, I wrote a testcase,
so I'm sending it here. I think I should commit it independenly
of your series.
I had described the problem as follow:
> The "info line" command skips function prologues, but it shouldn't.
> Consider for instance the new testcase provided with this patch.
> The code looks like this:
>
> 17
> 18 int twice (int i) { /* THIS LINE */
> 19 /* We purposefully put the return type, function prototype and
> 20 opening curly brace on the same line, in an effort to make sure
> 21 that the function prologue would be associated to that line. */
> 22 return 2 * i;
> 23 }
>
> Without this patch, GDB would report the following address range
> for line 18:
>
> (gdb) info line 18
> Line 18 of "[...]/infoline.c" is at address 0x40049b <twice+7>
> but contains no code.
>
> The indicator that the prologue was skipped comes from the fact that
> the address chosen is at twice+7, not twice+0.
--
Joel
[-- Attachment #2: 0003-decode_all_digits-Skip-prologue-only-if-self-funfirs.patch --]
[-- Type: text/x-diff, Size: 3376 bytes --]
From c21988ba1e257d0f20f2bdaf9677b867bfa0aeb0 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Fri, 25 Nov 2011 11:42:26 -0800
Subject: info line should not skip function prologues.
gdb/testsuite/ChangeLog:
* gdb.base/infoline.c, gdb.base/infoline.exp: New files.
---
gdb/testsuite/gdb.base/infoline.c | 30 ++++++++++++++++++++++++++++++
gdb/testsuite/gdb.base/infoline.exp | 30 ++++++++++++++++++++++++++++++
2 files changed, 60 insertions(+), 0 deletions(-)
create mode 100644 gdb/testsuite/gdb.base/infoline.c
create mode 100644 gdb/testsuite/gdb.base/infoline.exp
diff --git a/gdb/testsuite/gdb.base/infoline.c b/gdb/testsuite/gdb.base/infoline.c
new file mode 100644
index 0000000..7b0da2b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/infoline.c
@@ -0,0 +1,30 @@
+/* Copyright 2011 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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/>. */
+
+int twice (int i) { /* THIS LINE */
+ /* We purposefully put the return type, function prototype and
+ opening curly brace on the same line, in an effort to make sure
+ that the function prologue would be associated to that line. */
+ return 2 * i;
+}
+
+int
+main (void)
+{
+ int t = twice (1);
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/infoline.exp b/gdb/testsuite/gdb.base/infoline.exp
new file mode 100644
index 0000000..41ff894
--- /dev/null
+++ b/gdb/testsuite/gdb.base/infoline.exp
@@ -0,0 +1,30 @@
+# Copyright (C) 2011 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/>.
+
+set testfile infoline
+set srcfile ${testfile}.c
+
+if { [prepare_for_testing ${testfile}.exp ${testfile}] } {
+ return -1
+}
+
+clean_restart ${testfile}
+
+# Verify that the "info line" command does not skip function prologues.
+# If it did, GDB would tell us that the line we're interested in starts
+# at <twice+N> where N is different from zero.
+set fun_decl_line [gdb_get_line_number "THIS LINE"]
+gdb_test "info line ${srcfile}:${fun_decl_line}" \
+ "Line ${fun_decl_line} of \".*${testfile}\.c\" starts at address 0x\[0-9a-f\]+ <twice> and ends at .*"
--
1.7.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-28 21:29 ` Tom Tromey
` (5 preceding siblings ...)
2011-11-29 3:19 ` [RFA/commit/testcase] "info line" should not skip prologues (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 3:22 ` Joel Brobecker
2011-11-29 15:38 ` Tom Tromey
2011-11-29 3:29 ` set multiple-symbol ask/cancel not working (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
2011-11-29 3:33 ` one-too-many location in breakpoint (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
8 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 3:22 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 437 bytes --]
This patch is optional, and related to the problem that got fixed
by your latest patch series, mentioned in my previous email:
http://www.sourceware.org/ml/gdb-patches/2011-11/msg00799.html
I still noticed a call to skip_prologue_sal without a check of
self->funfirstline.
Perhaps there is no situation where this might make a difference,
but I thought it might be good to add the check anyways, just
to be on the safe side.
--
Joel
[-- Attachment #2: 0004-call-skip_prologue_sal-only-if-self-funfirstline.patch --]
[-- Type: text/x-diff, Size: 1024 bytes --]
From abc12be76deaa5632094c1507f4dff284bd36c2b Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Mon, 28 Nov 2011 16:08:40 -0800
Subject: [PATCH 4/5] call skip_prologue_sal only if self->funfirstline
gdb/ChangeLog:
* linespec.c (decode_all_digits): Call skip_prologue_sal
only if self->funfirstline.
---
gdb/linespec.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 06b1dd2..146163a 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -2433,7 +2433,8 @@ decode_all_digits (struct linespec_state *self,
/* Make sure the line matches the request, not what was
found. */
- skip_prologue_sal (&intermediate_results.sals[i]);
+ if (self->funfirstline)
+ skip_prologue_sal (&intermediate_results.sals[i]);
intermediate_results.sals[i].line = val.line;
add_sal_to_sals (self, &values, &intermediate_results.sals[i],
sym ? SYMBOL_NATURAL_NAME (sym) : NULL);
--
1.7.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* set multiple-symbol ask/cancel not working (was: "Re: GDB 7.4 branching status? (2011-11-23)")
2011-11-28 21:29 ` Tom Tromey
` (6 preceding siblings ...)
2011-11-29 3:22 ` GDB 7.4 branching status? (2011-11-23) Joel Brobecker
@ 2011-11-29 3:29 ` Joel Brobecker
2011-11-29 16:14 ` set multiple-symbol ask/cancel not working Tom Tromey
2011-11-29 3:33 ` one-too-many location in breakpoint (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
8 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 3:29 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
Hi Tom,
It looks like "set multiple-symbols ask/cancel" regressed again :-(.
(gdb) set multiple-symbols ask
(gdb) b normal_menu
Breakpoint 1 at 0x402130: normal_menu. (2 locations)
(gdb) set multiple-symbols cancel
(gdb) b normal_menu
Note: breakpoint 1 also set at pc 0x402130.
Note: breakpoint 1 also set at pc 0x40213b.
Breakpoint 2 at 0x402130: normal_menu. (2 locations)
Here is a reproducer:
package Pck is
procedure Normal_Menu;
procedure Normal_Menu (I : Integer);
end Pck;
package body Pck is
procedure Normal_Menu is
begin
null;
end Normal_Menu;
procedure Normal_Menu (I : Integer) is
begin
null;
end Normal_Menu;
end Pck;
with Pck; use Pck;
procedure Foo is
begin
Normal_Menu;
Normal_Menu (1);
end Foo;
(put the code above in a file called sources.ada, and then call
"gnatchop sources.ada", and it should create pck.ads, pck.adb and
foo.adb for you).
To produce the executable:
% gnatmake -g foo
I'll probably work on that last, because you might know where the
problem is without even looking, since you've already fixed it before.
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* one-too-many location in breakpoint (was: "Re: GDB 7.4 branching status? (2011-11-23)")
2011-11-28 21:29 ` Tom Tromey
` (7 preceding siblings ...)
2011-11-29 3:29 ` set multiple-symbol ask/cancel not working (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 3:33 ` Joel Brobecker
2011-11-29 16:15 ` one-too-many location in breakpoint Tom Tromey
8 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 3:33 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
I have a testcase where inserting a breakpoint causes one too many location.
I haven't investigated why that is. That'll be next on my list.
And I have another testcase where we also have an unexpected second
location, but I think that this might be because I forgot to contribute
some changes. It has to do with broken debug information due to
linker bugs with -ffunction-sections. I haven't investigated either.
And I think that's all! So, as you see, I think we're really close.
I'll continue working on these two tomorrow...
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* RE: partial-symtab symbol sorting (was: "Re: GDB 7.4 branching status? (2011-11-23)")
2011-11-29 3:07 ` partial-symtab symbol sorting (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 8:41 ` Pierre Muller
2011-11-29 14:51 ` partial-symtab symbol sorting Tom Tromey
[not found] ` <47228.5772244961$1322556128@news.gmane.org>
2 siblings, 0 replies; 42+ messages in thread
From: Pierre Muller @ 2011-11-29 8:41 UTC (permalink / raw)
To: 'Joel Brobecker', 'Tom Tromey'; +Cc: gdb-patches
> -----Message d'origine-----
> De : gdb-patches-owner@sourceware.org [mailto:gdb-patches-
> owner@sourceware.org] De la part de Joel Brobecker
> Envoyé : mardi 29 novembre 2011 04:07
> À : Tom Tromey
> Cc : gdb-patches@sources.redhat.com
> Objet : partial-symtab symbol sorting (was: "Re: GDB 7.4 branching status?
> (2011-11-23)")
>
> This is an issue that is only tangential to this patch, and should
> not be considered part of the series.
>
> I just realized that partial symbols are sorted using strcmp_iw_ordered.
> This works great for C++, for instance, but only works OK for Ada.
> I think that this is related to the fact that we might be using
> the linkage name, rather than the natural name (we compute the natural
> name only on-demand, due to memory pressure in large apps). As a result,
> the strcmp_iw_ordered routine can return non-zero for two names that
> ada-lang.c:compare_names would consider equal.
>
> For instance: `pck__hello' and `pck__hello__2'.
>
> So when doing a symbol lookup for pck__hello, for instance, we pass
> our own comparison routine, which is "compatible" with
> strcmp_iw_ordered to the psymtab map_matching_symbols routine.
> This allows us to perform a binary search rather than linear one.
>
> I am wondering if we shouldn't be sorting the partial symbols
> using a language-specific sorting routine instead.
Did you think about what would happen to executables containing
objects compiled in different languages, each having a different sorting
routine?
I don't understand how this would work in such a case?
Pierre Muller
GDB pascal language support maintainer
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: partial-symtab symbol sorting
2011-11-29 3:07 ` partial-symtab symbol sorting (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
2011-11-29 8:41 ` Pierre Muller
@ 2011-11-29 14:51 ` Tom Tromey
[not found] ` <47228.5772244961$1322556128@news.gmane.org>
2 siblings, 0 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 14:51 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> I just realized that partial symbols are sorted using strcmp_iw_ordered.
Joel> This works great for C++, for instance, but only works OK for Ada.
Joel> I am wondering if we shouldn't be sorting the partial symbols
Joel> using a language-specific sorting routine instead.
FWIW, I think it would probably be fine. It is hard to know for certain
without actually trying it, though.
Joel> The thing is, when I looked at it, it's not easy just looking at
Joel> the partial symtab what language it is. The language seems to be
Joel> embedded in the symbols themselves.
This is easy to add, though.
We could also add more function pointers so that the behavior is
method-based instead of switch-based.
Joel> But, without even thinking about performance issues at startup, this
Joel> approach suffers from the same problem as storing the natural name does:
Joel> For certain large applications, we would exceed the maximum amount of
Joel> memory a process can hold. This is not necessarily on GNU/Linux, but
Joel> the problem is there. I think we'll have better luck we are capable of
Joel> merging a bit the massive duplication in the debug info.
I'm curious to know what massive duplication you mean.
In my local builds I'm using -gdwarf-4 and seeing big space wins.
These also translate to runtime space wins for gdb; the effect is
basically like a bcache for types.
This is for C, I don't know about Ada.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: partial-symtab symbol sorting
[not found] ` <47228.5772244961$1322556128@news.gmane.org>
@ 2011-11-29 14:55 ` Tom Tromey
0 siblings, 0 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 14:55 UTC (permalink / raw)
To: Pierre Muller; +Cc: 'Joel Brobecker', gdb-patches
>>>>> "Pierre" == Pierre Muller <pierre.muller@ics-cnrs.unistra.fr> writes:
Pierre> Did you think about what would happen to executables containing
Pierre> objects compiled in different languages, each having a different sorting
Pierre> routine?
Pierre> I don't understand how this would work in such a case?
The symbols in a psymtab are specific to that particular psymtab.
In DWARF terms this corresponds to a single CU, so it just has one
language (ignoring possible future confusion via LTO builds).
See, e.g., psympriv.h:struct partial_symtab:globals_offset.
I tend to think this is a weird design and that we should have a single
hash per objfile for looking up partial symbols. But I have never tried
to measure the slowdown, if any, and of course this sort of change has
its own possible flaws... just something for a future to-do list.
Speaking of weird design, anybody know why globals are sorted in a
psymtab and static symbols are not? The comment in psympriv.h doesn't
make sense to me, since it ignores the possibility of an unsuccessful
search.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: decode_digits_line_mode
2011-11-29 3:14 ` decode_digits_line_mode (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 14:56 ` Tom Tromey
0 siblings, 0 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 14:56 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> One tiny suggestion:
Joel> s/decode_digits_line_mode/decode_digits_list_mode/
Joel> The function documentation talks about 'list_mode', and the call
Joel> to that function also checks self->list_mode:
Yeah, thanks, I will fix that.
I have some mental block about line-vs-list here, and I had to correct
the code more than once since I typed the wrong thing.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [RFA/commit/testcase] "info line" should not skip prologues
2011-11-29 3:19 ` [RFA/commit/testcase] "info line" should not skip prologues (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 15:03 ` Tom Tromey
2011-11-29 17:00 ` Joel Brobecker
0 siblings, 1 reply; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 15:03 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> This is an issue that I discovered in your previous set of patches, but
Joel> got fixed in this iteration :-). Nonetheless, I wrote a testcase,
Joel> so I'm sending it here. I think I should commit it independenly
Joel> of your series.
I agree, thanks.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: multiple-location breakpoint output
2011-11-29 3:11 ` multiple-location breakpoint output (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 15:06 ` Tom Tromey
0 siblings, 0 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 15:06 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> Just for the record, I noticed that the output of the "break" command
Joel> has been slightly adjusted when inserting a multi-location breakpoint.
Joel> Now, instead of printing "file [...], line [...]", it just prints
Joel> the linespec itself. Eg:
Joel> (gdb) b pck.adb:6
Joel> Breakpoint 1 at 0x40213b: pck.adb:6. (3 locations)
Joel> Another example, when inserting a breakpoint on a function which
Joel> has homonyms:
Joel> (gdb) b get_value
Joel> Breakpoint 1 at 0x402160: get_value. (2 locations)
Joel> This is probably intentional, and I think that it's an improvement,
Joel> particularly in the second situation, where each breakpoint corresponds
Joel> to different line locations.
Yeah, that is exactly why I did it.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: iterate_over_symbols should be a wrapper?
2011-11-29 2:49 ` iterate_over_symbols should be a wrapper? (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 15:27 ` Tom Tromey
0 siblings, 0 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 15:27 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> So, my proposal is to change the profile of la_iterate_over_symbols
Joel> to match the iterate_over_symbols routine, and then then set
Joel> the la_iterate_over_symbols field to iterate_over_symbols for
Joel> all languages except Ada. The changes in ada_iterate_over_symbols
Joel> should be straightforward, since ada_lookup_symbol_list accepts
Joel> a block as well.
I'm working on this now.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-29 3:22 ` GDB 7.4 branching status? (2011-11-23) Joel Brobecker
@ 2011-11-29 15:38 ` Tom Tromey
0 siblings, 0 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 15:38 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> This patch is optional, and related to the problem that got fixed
Joel> by your latest patch series, mentioned in my previous email:
Joel> http://www.sourceware.org/ml/gdb-patches/2011-11/msg00799.html
Joel> I still noticed a call to skip_prologue_sal without a check of
Joel> self-> funfirstline.
Joel> Perhaps there is no situation where this might make a difference,
Joel> but I thought it might be good to add the check anyways, just
Joel> to be on the safe side.
I am going to roll this into my patch.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: set multiple-symbol ask/cancel not working
2011-11-29 3:29 ` set multiple-symbol ask/cancel not working (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 16:14 ` Tom Tromey
2011-11-29 16:57 ` Tom Tromey
0 siblings, 1 reply; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 16:14 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> It looks like "set multiple-symbols ask/cancel" regressed again :-(.
Joel> (gdb) set multiple-symbols ask
Joel> (gdb) b normal_menu
Joel> Breakpoint 1 at 0x402130: normal_menu. (2 locations)
Thanks for sending the reproducer and the instructions. This saved a
lot of time.
I looked into this. The bug is that the canonical form for each
location is the same: "pck.adb:normal_menu". (Unlike in C++, where the
arguments would be part of the symbol name...)
I am not sure of the best way to handle this. Personally I think the
C++ approach is pretty good (though not without its baggage). But, I
don't know how to implement that for Ada, and I assume that there is
probably some reason it isn't done.
Since the "canonical form" doesn't actually have to be valid input to
linespec (it is only used for filtering the results -- well, it is now
that I fixed a couple of bad uses), I went ahead and changed
linespec.c:add_sal_to_sals to use FILE:FUNCTION:LINE for the canonical
form in this case.
This gives:
(gdb) b pck.adb:normal_Menu
[0] cancel
[1] all
[2] pck.adb:pck.normal_menu:4
[3] pck.adb:pck.normal_menu:8
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: one-too-many location in breakpoint
2011-11-29 3:33 ` one-too-many location in breakpoint (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
@ 2011-11-29 16:15 ` Tom Tromey
2011-11-29 16:59 ` Tom Tromey
0 siblings, 1 reply; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 16:15 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> I have a testcase where inserting a breakpoint causes one too many
Joel> location. I haven't investigated why that is. That'll be next on
Joel> my list.
Joel> And I have another testcase where we also have an unexpected second
Joel> location, but I think that this might be because I forgot to contribute
Joel> some changes. It has to do with broken debug information due to
Joel> linker bugs with -ffunction-sections. I haven't investigated either.
Joel> And I think that's all! So, as you see, I think we're really close.
Joel> I'll continue working on these two tomorrow...
I fixed all the other problems. I'm running a regression test to make
sure I didn't make something else break while doing this. If all goes
well I will send out refreshed patches.
I'm happy to help look at the remaining problems, just send the info.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: set multiple-symbol ask/cancel not working
2011-11-29 16:14 ` set multiple-symbol ask/cancel not working Tom Tromey
@ 2011-11-29 16:57 ` Tom Tromey
2011-11-29 17:06 ` Joel Brobecker
0 siblings, 1 reply; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 16:57 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Tom" == Tom Tromey <tromey@redhat.com> writes:
Tom> Since the "canonical form" doesn't actually have to be valid input to
Tom> linespec (it is only used for filtering the results -- well, it is now
Tom> that I fixed a couple of bad uses), I went ahead and changed
Tom> linespec.c:add_sal_to_sals to use FILE:FUNCTION:LINE for the canonical
Tom> form in this case.
Tom> This gives:
Tom> (gdb) b pck.adb:normal_Menu
Tom> [0] cancel
Tom> [1] all
Tom> [2] pck.adb:pck.normal_menu:4
Tom> [3] pck.adb:pck.normal_menu:8
I am not at all sure about doing this. It means that the breakpoint
will stop working if the line number changes.
Maybe this is ok, since it is what the user asked for in
multiple-symbols=ask mode -- not the default, so he essentially asked
twice.
Another option would be to only apply this treatment to Ada.
I'll send the current patches, with this in place, regardless.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: one-too-many location in breakpoint
2011-11-29 16:15 ` one-too-many location in breakpoint Tom Tromey
@ 2011-11-29 16:59 ` Tom Tromey
2011-11-30 5:59 ` Joel Brobecker
` (2 more replies)
0 siblings, 3 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-29 16:59 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 431 bytes --]
Tom> I fixed all the other problems. I'm running a regression test to make
Tom> sure I didn't make something else break while doing this. If all goes
Tom> well I will send out refreshed patches.
I needed a couple of test suite changes to account for the different
output. Otherwise all is well.
This includes a test addition for the iterate_over_symbols change.
I didn't write a new test for the "normal_menu" problem.
Tom
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: main patch --]
[-- Type: text/x-patch, Size: 252694 bytes --]
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a35c692..ee67bb4 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,37 @@
+2011-11-28 Tom Tromey <tromey@redhat.com>
+ Joel Brobecker <brobecker@acacore.com>
+
+ * source.c (line_info): Use DECODE_LINE_LIST_MODE.
+ * breakpoint.c (clear_command): Use DECODE_LINE_LIST_MODE.
+ * linespec.c (decode_digits_list_mode): New function.
+ (decode_digits_ordinary): Likewise.
+ * symtab.c (append_expanded_sal): Remove.
+ (append_exact_match_to_sals): Remove.
+ (expand_line_sal): Remove.
+ * symtab.h (expand_line_sal): Remove.
+
+2011-11-22 Tom Tromey <tromey@redhat.com>
+
+ * linespec.c (iterate_over_all_matching_symtabs): Call
+ la_iterate_over_symbols.
+ (find_function_symbols, decode_variable): Remove Ada special
+ case.
+ * language.h (struct language_defn) <la_iterate_over_symbols>: New
+ field.
+ * language.c (unknown_language_defn, auto_language_defn)
+ (local_language_defn): Update.
+ * c-lang.c (c_language_defn, cplus_language_defn)
+ (asm_language_defn, minimal_language_defn): Update.
+ * d-lang.c (d_language_defn): Update.
+ * f-lang.c (f_language_defn): Update.
+ * jv-lang.c (java_language_defn): Update.
+ * m2-lang.c (m2_language_defn): Update.
+ * objc-lang.c (objc_language_defn): Update.
+ * opencl-lang.c (opencl_language_defn): Update.
+ * p-lang.c (pascal_language_defn): Update.
+ * ada-lang.c (ada_iterate_over_symbols): New function.
+ (ada_language_defn): Update.
+
2011-11-28 Phil Muldoon <pmuldoon@redhat.com>
PR python/13369
@@ -248,6 +282,158 @@
2011-11-18 Tom Tromey <tromey@redhat.com>
+ PR breakpoints/13105, PR objc/8341, PR objc/8343, PR objc/8366,
+ PR objc/8535, PR breakpoints/11657, PR breakpoints/11970,
+ PR breakpoints/12023, PR breakpoints/12334, PR breakpoints/12856,
+ PR shlibs/8929, PR shlibs/7393:
+ * python/py-type.c (compare_maybe_null_strings): Rename from
+ compare_strings.
+ (check_types_equal): Update.
+ * utils.c (compare_strings): New function.
+ * tui/tui-winsource.c (tui_update_breakpoint_info): Update for
+ location changes.
+ * tracepoint.c (scope_info): Update.
+ * symtab.h (iterate_over_minimal_symbols)
+ (iterate_over_some_symtabs, iterate_over_symtabs)
+ (find_pcs_for_symtab_line, iterate_over_symbols)
+ (demangle_for_lookup): Declare.
+ * symtab.c (iterate_over_some_symtabs, iterate_over_symtabs)
+ (lookup_symtab_callback): New functions.
+ (lookup_symtab): Rewrite.
+ (demangle_for_lookup): New function, extract from
+ lookup_symbol_in_language.
+ (lookup_symbol_in_language): Use it.
+ (iterate_over_symbols): New function.
+ (find_line_symtab): Update.
+ (find_pcs_for_symtab_line): New functions.
+ (find_line_common): Add 'start' argument.
+ (decode_line_spec): Update.
+ (validate_inexact_match): New function.
+ * symfile.h (struct quick_symbol_functions) <lookup_symtab>:
+ Remove.
+ <map_symtabs_matching_filename>: New field.
+ * stack.c (func_command): Only look in the current program space.
+ * source.c (line_info): Set pspace on sal. Check program space in
+ the loop.
+ * solib-target.c: Remove DEF_VEC_I(CORE_ADDR).
+ * python/python.c (gdbpy_decode_line): Update.
+ * psymtab.c (partial_map_expand_apply): New function.
+ (partial_map_symtabs_matching_filename): Rename from
+ lookup_partial_symbol. Update arguments.
+ (lookup_symtab_via_partial_symtab): Remove.
+ (psym_functions): Update.
+ * objc-lang.h (parse_selector, parse_method): Don't declare.
+ (find_imps): Update.
+ * objc-lang.c (parse_selector, parse_method): Now static.
+ (find_methods): Change arguments. Fill in a vector of symbol
+ names.
+ (uniquify_strings): New function.
+ (find_imps): Change arguments.
+ * minsyms.c (iterate_over_minimal_symbols): New function.
+ * linespec.h (struct linespec_sals): New type.
+ (struct linespec_result) <canonical>: Remove.
+ (enum decode_line_flags): New.
+ <pre_expanded, addr_string, sals>: New fields.
+ (destroy_linespec_result, make_cleanup_destroy_linespec_result)
+ (decode_line_full): Declare.
+ (decode_line_1): Update.
+ * linespec.c (struct address_entry, struct linespec_state, struct
+ collect_info): New types.
+ (add_sal_to_sals_basic, add_sal_to_sals, hash_address_entry)
+ (eq_address_entry, maybe_add_address): New functions.
+ (total_number_of_methods): Remove.
+ (iterate_name_matcher, iterate_over_all_matching_symtabs): New
+ functions.
+ (find_methods): Change arguments. Don't canonicalize input.
+ Simplify logic.
+ (add_matching_methods, add_constructors)
+ (build_canonical_line_spec): Remove.
+ (filter_results, convert_results_to_lsals): New functions.
+ (decode_line_2): Change arguments. Rewrite for new data
+ structures.
+ (decode_line_internal): Rename from decode_line_1. Change
+ arguments. Add cleanups. Update for new data structures.
+ (linespec_state_constructor, linespec_state_destructor)
+ (decode_line_full, decode_line_1): New functions.
+ (decode_indirect): Change arguments. Update.
+ (locate_first_half): Use skip_spaces.
+ (decode_objc): Change arguments. Update for new data structures.
+ Simplify logic.
+ (decode_compound): Change arguments. Add cleanups. Fall back on
+ decode_variable.
+ (struct decode_compound_collector): New type.
+ (collect_one_symbol): New function.
+ (lookup_prefix_sym): Change arguments. Update.
+ (compare_symbol_name, add_all_symbol_names_from_pspace)
+ (find_superclass_methods ): New functions.
+ (find_method): Rewrite.
+ (struct symtab_collector): New type.
+ (add_symtabs_to_list, collect_symtabs_from_filename): New
+ functions.
+ (symtabs_from_filename): Change API. Rename from
+ symtab_from_filename.
+ (collect_function_symbols): New function.
+ (find_function_symbols): Change API. Rename from
+ find_function_symbol. Rewrite.
+ (decode_all_digits): Change arguments. Rewrite.
+ (decode_dollar): Change arguments. Use decode_variable.
+ (decode_label): Change arguments. Rewrite.
+ (collect_symbols): New function.
+ (minsym_found): Change arguments. Rewrite.
+ (check_minsym, search_minsyms_for_name)
+ (add_matching_symbols_to_info): New function.
+ (decode_variable): Change arguments. Iterate over all symbols.
+ (symbol_found): Remove.
+ (symbol_to_sal): New function.
+ (init_linespec_result, destroy_linespec_result)
+ (cleanup_linespec_result, make_cleanup_destroy_linespec_result):
+ New functions.
+ * dwarf2read.c (dw2_map_expand_apply): New function.
+ (dw2_map_symtabs_matching_filename): Rename from
+ dw2_lookup_symtab. Change arguments.
+ (dwarf2_gdb_index_functions): Update.
+ * dwarf2loc.c: Remove DEF_VEC_I(CORE_ADDR).
+ * defs.h (compare_strings): Declare.
+ * cli/cli-cmds.c (compare_strings): Move to utils.c.
+ (edit_command, list_command): Use decode_line_list. Call
+ filter_sals.
+ (compare_symtabs, filter_sals): New functions.
+ * breakpoint.h (struct bp_location) <line_number, source_file>:
+ New fields.
+ (struct breakpoint) <line_number, source_file>: Remove.
+ <filter>: New field.
+ * breakpoint.c (print_breakpoint_location, init_raw_breakpoint)
+ (momentary_breakpoint_from_master, add_location_to_breakpoint):
+ Update for changes to locations.
+ (init_breakpoint_sal): Add 'filter' argument. Set 'filter' on
+ breakpoint.
+ (create_breakpoint_sal): Add 'filter' argument.
+ (remove_sal, expand_line_sal_maybe): Remove.
+ (create_breakpoints_sal): Remove 'sals' argument. Handle
+ pre-expanded sals and the filter.
+ (parse_breakpoint_sals): Use decode_line_full.
+ (check_fast_tracepoint_sals): Use get_sal_arch.
+ (create_breakpoint): Create a linespec_sals. Update.
+ (break_range_command): Use decode_line_full. Update.
+ (until_break_command): Update.
+ (clear_command): Update match conditions for linespec.c changes.
+ (say_where): Update for changes to locations.
+ (bp_location_dtor): Free 'source_file'.
+ (base_breakpoint_dtor): Free 'filter'. Don't free 'source_file'.
+ (update_static_tracepoint): Update for changes to locations.
+ (update_breakpoint_locations): Disable ranged breakpoint if too
+ many locations match. Update.
+ (addr_string_to_sals): Use decode_line_full. Resolve all sal
+ PCs.
+ (breakpoint_re_set_default): Don't call expand_line_sal_maybe.
+ (decode_line_spec_1): Update.
+ * block.h (block_containing_function): Declare.
+ * block.c (block_containing_function): New function.
+ * skip.c (skip_function_command): Update.
+ (skip_re_set): Update.
+
+2011-10-28 Tom Tromey <tromey@redhat.com>
+
* elfread.c (elf_gnu_ifunc_resolver_return_stop): Allow
breakpoint's pspace to be NULL.
* breakpoint.h (struct breakpoint) <pspace>: Update comment.
diff --git a/gdb/block.c b/gdb/block.c
index c165bc2..1fa3688 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -82,6 +82,20 @@ block_linkage_function (const struct block *bl)
return BLOCK_FUNCTION (bl);
}
+/* Return the symbol for the function which contains a specified
+ block, described by a struct block BL. The return value will be
+ the closest enclosing function, which might be an inline
+ function. */
+
+struct symbol *
+block_containing_function (const struct block *bl)
+{
+ while (BLOCK_FUNCTION (bl) == NULL && BLOCK_SUPERBLOCK (bl) != NULL)
+ bl = BLOCK_SUPERBLOCK (bl);
+
+ return BLOCK_FUNCTION (bl);
+}
+
/* Return one if BL represents an inlined function. */
int
diff --git a/gdb/block.h b/gdb/block.h
index 1742f24..63b18a6 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -131,6 +131,8 @@ struct blockvector
extern struct symbol *block_linkage_function (const struct block *);
+extern struct symbol *block_containing_function (const struct block *);
+
extern int block_inlined_p (const struct block *block);
extern int contained_in (const struct block *, const struct block *);
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 6eced70..c9ce4ed 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -4563,7 +4563,7 @@ print_breakpoint_location (struct breakpoint *b,
if (b->display_canonical)
ui_out_field_string (uiout, "what", b->addr_string);
- else if (b->source_file && loc)
+ else if (loc && loc->source_file)
{
struct symbol *sym
= find_pc_sect_function (loc->address, loc->section);
@@ -4576,7 +4576,7 @@ print_breakpoint_location (struct breakpoint *b,
ui_out_wrap_hint (uiout, wrap_indent_at_field (uiout, "what"));
ui_out_text (uiout, "at ");
}
- ui_out_field_string (uiout, "file", b->source_file);
+ ui_out_field_string (uiout, "file", loc->source_file);
ui_out_text (uiout, ":");
if (ui_out_is_mi_like_p (uiout))
@@ -4588,7 +4588,7 @@ print_breakpoint_location (struct breakpoint *b,
ui_out_field_string (uiout, "fullname", fullname);
}
- ui_out_field_int (uiout, "line", b->line_number);
+ ui_out_field_int (uiout, "line", loc->line_number);
}
else if (loc)
{
@@ -5825,12 +5825,6 @@ init_raw_breakpoint (struct breakpoint *b, struct gdbarch *gdbarch,
if (bptype != bp_breakpoint && bptype != bp_hardware_breakpoint)
b->pspace = sal.pspace;
- if (sal.symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file = xstrdup (sal.symtab->filename);
- b->line_number = sal.line;
-
breakpoints_changed ();
}
@@ -7076,12 +7070,10 @@ momentary_breakpoint_from_master (struct breakpoint *orig,
copy->loc->section = orig->loc->section;
copy->loc->pspace = orig->loc->pspace;
- if (orig->source_file == NULL)
- copy->source_file = NULL;
- else
- copy->source_file = xstrdup (orig->source_file);
+ if (orig->loc->source_file != NULL)
+ copy->loc->source_file = xstrdup (orig->loc->source_file);
- copy->line_number = orig->line_number;
+ copy->loc->line_number = orig->loc->line_number;
copy->frame_id = orig->frame_id;
copy->thread = orig->thread;
copy->pspace = orig->pspace;
@@ -7165,6 +7157,11 @@ add_location_to_breakpoint (struct breakpoint *b,
gdb_assert (loc->pspace != NULL);
loc->section = sal->section;
loc->gdbarch = loc_gdbarch;
+
+ if (sal->symtab != NULL)
+ loc->source_file = xstrdup (sal->symtab->filename);
+ loc->line_number = sal->line;
+
set_breakpoint_location_function (loc,
sal->explicit_pc || sal->explicit_line);
return loc;
@@ -7221,7 +7218,7 @@ bp_loc_is_permanent (struct bp_location *loc)
static void
init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
struct symtabs_and_lines sals, char *addr_string,
- char *cond_string,
+ char *filter, char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int task, int ignore_count,
const struct breakpoint_ops *ops, int from_tty,
@@ -7335,12 +7332,13 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
me. */
b->addr_string
= xstrprintf ("*%s", paddress (b->loc->gdbarch, b->loc->address));
+ b->filter = filter;
}
static void
create_breakpoint_sal (struct gdbarch *gdbarch,
struct symtabs_and_lines sals, char *addr_string,
- char *cond_string,
+ char *filter, char *cond_string,
enum bptype type, enum bpdisp disposition,
int thread, int task, int ignore_count,
const struct breakpoint_ops *ops, int from_tty,
@@ -7363,7 +7361,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
init_breakpoint_sal (b, gdbarch,
sals, addr_string,
- cond_string,
+ filter, cond_string,
type, disposition,
thread, task, ignore_count,
ops, from_tty,
@@ -7373,138 +7371,6 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
install_breakpoint (internal, b, 0);
}
-/* Remove element at INDEX_TO_REMOVE from SAL, shifting other
- elements to fill the void space. */
-static void
-remove_sal (struct symtabs_and_lines *sal, int index_to_remove)
-{
- int i = index_to_remove+1;
- int last_index = sal->nelts-1;
-
- for (;i <= last_index; ++i)
- sal->sals[i-1] = sal->sals[i];
-
- --(sal->nelts);
-}
-
-/* If appropriate, obtains all sals that correspond to the same file
- and line as SAL, in all program spaces. Users debugging with IDEs,
- will want to set a breakpoint at foo.c:line, and not really care
- about program spaces. This is done only if SAL does not have
- explicit PC and has line and file information. If we got just a
- single expanded sal, return the original.
-
- Otherwise, if SAL.explicit_line is not set, filter out all sals for
- which the name of enclosing function is different from SAL. This
- makes sure that if we have breakpoint originally set in template
- instantiation, say foo<int>(), we won't expand SAL to locations at
- the same line in all existing instantiations of 'foo'. */
-
-static struct symtabs_and_lines
-expand_line_sal_maybe (struct symtab_and_line sal)
-{
- struct symtabs_and_lines expanded;
- CORE_ADDR original_pc = sal.pc;
- char *original_function = NULL;
- int found;
- int i;
- struct cleanup *old_chain;
-
- /* If we have explicit pc, don't expand.
- If we have no line number, we can't expand. */
- if (sal.explicit_pc || sal.line == 0 || sal.symtab == NULL)
- {
- expanded.nelts = 1;
- expanded.sals = xmalloc (sizeof (struct symtab_and_line));
- expanded.sals[0] = sal;
- return expanded;
- }
-
- sal.pc = 0;
-
- old_chain = save_current_space_and_thread ();
-
- switch_to_program_space_and_thread (sal.pspace);
-
- find_pc_partial_function (original_pc, &original_function, NULL, NULL);
-
- /* Note that expand_line_sal visits *all* program spaces. */
- expanded = expand_line_sal (sal);
-
- if (expanded.nelts == 1)
- {
- /* We had one sal, we got one sal. Return that sal, adjusting it
- past the function prologue if necessary. */
- xfree (expanded.sals);
- expanded.nelts = 1;
- expanded.sals = xmalloc (sizeof (struct symtab_and_line));
- sal.pc = original_pc;
- expanded.sals[0] = sal;
- skip_prologue_sal (&expanded.sals[0]);
- do_cleanups (old_chain);
- return expanded;
- }
-
- if (!sal.explicit_line)
- {
- CORE_ADDR func_addr, func_end;
- for (i = 0; i < expanded.nelts; ++i)
- {
- CORE_ADDR pc = expanded.sals[i].pc;
- char *this_function;
-
- /* We need to switch threads as well since we're about to
- read memory. */
- switch_to_program_space_and_thread (expanded.sals[i].pspace);
-
- if (find_pc_partial_function (pc, &this_function,
- &func_addr, &func_end))
- {
- if (this_function
- && strcmp (this_function, original_function) != 0)
- {
- remove_sal (&expanded, i);
- --i;
- }
- }
- }
- }
-
- /* Skip the function prologue if necessary. */
- for (i = 0; i < expanded.nelts; ++i)
- skip_prologue_sal (&expanded.sals[i]);
-
- do_cleanups (old_chain);
-
- if (expanded.nelts <= 1)
- {
- /* This is an ugly workaround. If we get zero expanded sals
- then something is really wrong. Fix that by returning the
- original sal. */
-
- xfree (expanded.sals);
- expanded.nelts = 1;
- expanded.sals = xmalloc (sizeof (struct symtab_and_line));
- sal.pc = original_pc;
- expanded.sals[0] = sal;
- return expanded;
- }
-
- if (original_pc)
- {
- found = 0;
- for (i = 0; i < expanded.nelts; ++i)
- if (expanded.sals[i].pc == original_pc)
- {
- found = 1;
- break;
- }
- gdb_assert (found);
- }
-
- return expanded;
-}
-
/* Add SALS.nelts breakpoints to the breakpoint table. For each
SALS.sal[i] breakpoint, include the corresponding ADDR_STRING[i]
value. COND_STRING, if not NULL, specified the condition to be
@@ -7522,7 +7388,6 @@ expand_line_sal_maybe (struct symtab_and_line sal)
static void
create_breakpoints_sal (struct gdbarch *gdbarch,
- struct symtabs_and_lines sals,
struct linespec_result *canonical,
char *cond_string,
enum bptype type, enum bpdisp disposition,
@@ -7531,17 +7396,30 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
int enabled, int internal)
{
int i;
+ struct linespec_sals *lsal;
- for (i = 0; i < sals.nelts; ++i)
+ if (canonical->pre_expanded)
+ gdb_assert (VEC_length (linespec_sals, canonical->sals) == 1);
+
+ for (i = 0; VEC_iterate (linespec_sals, canonical->sals, i, lsal); ++i)
{
- struct symtabs_and_lines expanded =
- expand_line_sal_maybe (sals.sals[i]);
+ /* Note that 'addr_string' can be NULL in the case of a plain
+ 'break', without arguments. */
+ char *addr_string = (canonical->addr_string
+ ? xstrdup (canonical->addr_string)
+ : NULL);
+ char *filter_string = lsal->canonical ? xstrdup (lsal->canonical) : NULL;
+ struct cleanup *inner = make_cleanup (xfree, addr_string);
- create_breakpoint_sal (gdbarch, expanded, canonical->canonical[i],
+ make_cleanup (xfree, filter_string);
+ create_breakpoint_sal (gdbarch, lsal->sals,
+ addr_string,
+ filter_string,
cond_string, type, disposition,
thread, task, ignore_count, ops,
from_tty, enabled, internal,
canonical->special_display);
+ discard_cleanups (inner);
}
}
@@ -7555,7 +7433,6 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
static void
parse_breakpoint_sals (char **address,
- struct symtabs_and_lines *sals,
struct linespec_result *canonical)
{
char *addr_start = *address;
@@ -7569,10 +7446,11 @@ parse_breakpoint_sals (char **address,
address. */
if (last_displayed_sal_is_valid ())
{
+ struct linespec_sals lsal;
struct symtab_and_line sal;
init_sal (&sal); /* Initialize to zeroes. */
- sals->sals = (struct symtab_and_line *)
+ lsal.sals.sals = (struct symtab_and_line *)
xmalloc (sizeof (struct symtab_and_line));
/* Set sal's pspace, pc, symtab, and line to the values
@@ -7587,8 +7465,11 @@ parse_breakpoint_sals (char **address,
instances with the same symtab and line. */
sal.explicit_pc = 1;
- sals->sals[0] = sal;
- sals->nelts = 1;
+ lsal.sals.sals[0] = sal;
+ lsal.sals.nelts = 1;
+ lsal.canonical = NULL;
+
+ VEC_safe_push (linespec_sals, canonical->sals, &lsal);
}
else
error (_("No default breakpoint address now."));
@@ -7598,40 +7479,16 @@ parse_breakpoint_sals (char **address,
/* Force almost all breakpoints to be in terms of the
current_source_symtab (which is decode_line_1's default).
This should produce the results we want almost all of the
- time while leaving the last displayed codepoint pointers
- alone.
-
- ObjC: However, don't match an Objective-C method name which
- may have a '+' or '-' succeeded by a '[' */
-
- struct symtab_and_line cursal = get_current_source_symtab_and_line ();
-
- if (last_displayed_sal_is_valid ()
- && (!cursal.symtab
- || ((strchr ("+-", (*address)[0]) != NULL)
- && ((*address)[1] != '['))))
- *sals = decode_line_1 (address, 1,
- get_last_displayed_symtab (),
- get_last_displayed_line (),
- canonical);
+ time while leaving default_breakpoint_* alone. */
+ if (last_displayed_sal_is_valid ())
+ decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
+ get_last_displayed_symtab (),
+ get_last_displayed_line (),
+ canonical, NULL, NULL);
else
- *sals = decode_line_1 (address, 1, (struct symtab *) NULL, 0,
- canonical);
- }
- /* For any SAL that didn't have a canonical string, fill one in. */
- if (sals->nelts > 0 && canonical->canonical == NULL)
- canonical->canonical = xcalloc (sals->nelts, sizeof (char *));
- if (addr_start != (*address))
- {
- int i;
-
- for (i = 0; i < sals->nelts; i++)
- {
- /* Add the string if not present. */
- if (canonical->canonical[i] == NULL)
- canonical->canonical[i] = savestring (addr_start,
- (*address) - addr_start);
- }
+ decode_line_full (address, DECODE_LINE_FUNFIRSTLINE,
+ (struct symtab *) NULL, 0,
+ canonical, NULL, NULL);
}
}
@@ -7666,15 +7523,22 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch,
for (i = 0; i < sals->nelts; i++)
{
+ struct gdbarch *sarch;
+
sal = &sals->sals[i];
- rslt = gdbarch_fast_tracepoint_valid_at (gdbarch, sal->pc,
+ sarch = get_sal_arch (*sal);
+ /* We fall back to GDBARCH if there is no architecture
+ associated with SAL. */
+ if (sarch == NULL)
+ sarch = gdbarch;
+ rslt = gdbarch_fast_tracepoint_valid_at (sarch, sal->pc,
NULL, &msg);
old_chain = make_cleanup (xfree, msg);
if (!rslt)
error (_("May not have a fast tracepoint at 0x%s%s"),
- paddress (gdbarch, sal->pc), (msg ? msg : ""));
+ paddress (sarch, sal->pc), (msg ? msg : ""));
do_cleanups (old_chain);
}
@@ -7816,9 +7680,7 @@ create_breakpoint (struct gdbarch *gdbarch,
int from_tty, int enabled, int internal)
{
volatile struct gdb_exception e;
- struct symtabs_and_lines sals;
- struct symtab_and_line pending_sal;
- char *copy_arg;
+ char *copy_arg = NULL;
char *addr_start = arg;
struct linespec_result canonical;
struct cleanup *old_chain;
@@ -7830,26 +7692,26 @@ create_breakpoint (struct gdbarch *gdbarch,
gdb_assert (ops != NULL);
- sals.sals = NULL;
- sals.nelts = 0;
init_linespec_result (&canonical);
if (type_wanted == bp_static_tracepoint && is_marker_spec (arg))
{
int i;
+ struct linespec_sals lsal;
- sals = decode_static_tracepoint_spec (&arg);
+ lsal.sals = decode_static_tracepoint_spec (&arg);
copy_arg = savestring (addr_start, arg - addr_start);
- canonical.canonical = xcalloc (sals.nelts, sizeof (char *));
- for (i = 0; i < sals.nelts; i++)
- canonical.canonical[i] = xstrdup (copy_arg);
+
+ lsal.canonical = xstrdup (copy_arg);
+ VEC_safe_push (linespec_sals, canonical.sals, &lsal);
+
goto done;
}
TRY_CATCH (e, RETURN_MASK_ALL)
{
- parse_breakpoint_sals (&arg, &sals, &canonical);
+ parse_breakpoint_sals (&arg, &canonical);
}
/* If caller is interested in rc value from parse, set value. */
@@ -7881,35 +7743,31 @@ create_breakpoint (struct gdbarch *gdbarch,
a pending breakpoint and selected yes, or pending
breakpoint behavior is on and thus a pending breakpoint
is defaulted on behalf of the user. */
- copy_arg = xstrdup (addr_start);
- canonical.canonical = ©_arg;
- sals.nelts = 1;
- sals.sals = &pending_sal;
- pending_sal.pc = 0;
- pending = 1;
+ {
+ struct linespec_sals lsal;
+
+ copy_arg = xstrdup (addr_start);
+ lsal.canonical = xstrdup (copy_arg);
+ lsal.sals.nelts = 1;
+ lsal.sals.sals = XNEW (struct symtab_and_line);
+ init_sal (&lsal.sals.sals[0]);
+ pending = 1;
+ VEC_safe_push (linespec_sals, canonical.sals, &lsal);
+ }
break;
default:
throw_exception (e);
}
break;
default:
- if (!sals.nelts)
+ if (VEC_empty (linespec_sals, canonical.sals))
return 0;
}
done:
/* Create a chain of things that always need to be cleaned up. */
- old_chain = make_cleanup (null_cleanup, 0);
-
- if (!pending)
- {
- /* Make sure that all storage allocated to SALS gets freed. */
- make_cleanup (xfree, sals.sals);
-
- /* Cleanup the canonical array but not its contents. */
- make_cleanup (xfree, canonical.canonical);
- }
+ old_chain = make_cleanup_destroy_linespec_result (&canonical);
/* ----------------------------- SNIP -----------------------------
Anything added to the cleanup chain beyond this point is assumed
@@ -7917,28 +7775,36 @@ create_breakpoint (struct gdbarch *gdbarch,
then the memory is not reclaimed. */
bkpt_chain = make_cleanup (null_cleanup, 0);
- /* Mark the contents of the canonical for cleanup. These go on
- the bkpt_chain and only occur if the breakpoint create fails. */
- for (i = 0; i < sals.nelts; i++)
- {
- if (canonical.canonical[i] != NULL)
- make_cleanup (xfree, canonical.canonical[i]);
- }
-
/* Resolve all line numbers to PC's and verify that the addresses
are ok for the target. */
if (!pending)
- breakpoint_sals_to_pc (&sals);
+ {
+ int ix;
+ struct linespec_sals *iter;
+
+ for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix)
+ breakpoint_sals_to_pc (&iter->sals);
+ }
/* Fast tracepoints may have additional restrictions on location. */
if (!pending && type_wanted == bp_fast_tracepoint)
- check_fast_tracepoint_sals (gdbarch, &sals);
+ {
+ int ix;
+ struct linespec_sals *iter;
+
+ for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix)
+ check_fast_tracepoint_sals (gdbarch, &iter->sals);
+ }
/* Verify that condition can be parsed, before setting any
breakpoints. Allocate a separate condition expression for each
breakpoint. */
if (!pending)
{
+ struct linespec_sals *lsal;
+
+ lsal = VEC_index (linespec_sals, canonical.sals, 0);
+
if (parse_condition_and_thread)
{
/* Here we only parse 'arg' to separate condition
@@ -7947,7 +7813,7 @@ create_breakpoint (struct gdbarch *gdbarch,
re-parse it in context of each sal. */
cond_string = NULL;
thread = -1;
- find_condition_and_thread (arg, sals.sals[0].pc, &cond_string,
+ find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
&thread, &task);
if (cond_string)
make_cleanup (xfree, cond_string);
@@ -7969,24 +7835,26 @@ create_breakpoint (struct gdbarch *gdbarch,
expand multiple locations for each sal, given than SALS
already should contain all sals for MARKER_ID. */
if (type_wanted == bp_static_tracepoint
- && is_marker_spec (canonical.canonical[0]))
+ && is_marker_spec (copy_arg))
{
int i;
- for (i = 0; i < sals.nelts; ++i)
+ for (i = 0; i < lsal->sals.nelts; ++i)
{
struct symtabs_and_lines expanded;
struct tracepoint *tp;
struct cleanup *old_chain;
+ char *addr_string;
expanded.nelts = 1;
- expanded.sals = xmalloc (sizeof (struct symtab_and_line));
- expanded.sals[0] = sals.sals[i];
- old_chain = make_cleanup (xfree, expanded.sals);
+ expanded.sals = &lsal->sals.sals[i];
+
+ addr_string = xstrdup (canonical.addr_string);
+ old_chain = make_cleanup (xfree, addr_string);
tp = XCNEW (struct tracepoint);
init_breakpoint_sal (&tp->base, gdbarch, expanded,
- canonical.canonical[i],
+ addr_string, NULL,
cond_string, type_wanted,
tempflag ? disp_del : disp_donttouch,
thread, task, ignore_count, ops,
@@ -8002,11 +7870,11 @@ create_breakpoint (struct gdbarch *gdbarch,
install_breakpoint (internal, &tp->base, 0);
- do_cleanups (old_chain);
+ discard_cleanups (old_chain);
}
}
else
- create_breakpoints_sal (gdbarch, sals, &canonical, cond_string,
+ create_breakpoints_sal (gdbarch, &canonical, cond_string,
type_wanted,
tempflag ? disp_del : disp_donttouch,
thread, task, ignore_count, ops, from_tty,
@@ -8030,7 +7898,7 @@ create_breakpoint (struct gdbarch *gdbarch,
init_raw_breakpoint_without_location (b, gdbarch, type_wanted, ops);
- b->addr_string = canonical.canonical[0];
+ b->addr_string = copy_arg;
b->cond_string = NULL;
b->ignore_count = ignore_count;
b->disposition = tempflag ? disp_del : disp_donttouch;
@@ -8042,7 +7910,7 @@ create_breakpoint (struct gdbarch *gdbarch,
install_breakpoint (internal, b, 0);
}
- if (sals.nelts > 1)
+ if (VEC_length (linespec_sals, canonical.sals) > 1)
{
warning (_("Multiple breakpoints were set.\nUse the "
"\"delete\" command to delete unwanted breakpoints."));
@@ -8423,8 +8291,8 @@ break_range_command (char *arg, int from_tty)
CORE_ADDR end;
struct breakpoint *b;
struct symtab_and_line sal_start, sal_end;
- struct symtabs_and_lines sals_start, sals_end;
struct cleanup *cleanup_bkpt;
+ struct linespec_sals *lsal_start, *lsal_end;
/* We don't support software ranged breakpoints. */
if (target_ranged_break_num_registers () < 0)
@@ -8437,71 +8305,62 @@ break_range_command (char *arg, int from_tty)
if (can_use_bp < 0)
error (_("Hardware breakpoints used exceeds limit."));
+ arg = skip_spaces (arg);
if (arg == NULL || arg[0] == '\0')
error(_("No address range specified."));
- sals_start.sals = NULL;
- sals_start.nelts = 0;
init_linespec_result (&canonical_start);
- while (*arg == ' ' || *arg == '\t')
- arg++;
-
- parse_breakpoint_sals (&arg, &sals_start, &canonical_start);
+ arg_start = arg;
+ parse_breakpoint_sals (&arg, &canonical_start);
- sal_start = sals_start.sals[0];
- addr_string_start = canonical_start.canonical[0];
- cleanup_bkpt = make_cleanup (xfree, addr_string_start);
- xfree (sals_start.sals);
- xfree (canonical_start.canonical);
+ cleanup_bkpt = make_cleanup_destroy_linespec_result (&canonical_start);
if (arg[0] != ',')
error (_("Too few arguments."));
- else if (sals_start.nelts == 0)
+ else if (VEC_empty (linespec_sals, canonical_start.sals))
error (_("Could not find location of the beginning of the range."));
- else if (sals_start.nelts != 1)
+
+ lsal_start = VEC_index (linespec_sals, canonical_start.sals, 0);
+
+ if (VEC_length (linespec_sals, canonical_start.sals) > 1
+ || lsal_start->sals.nelts != 1)
error (_("Cannot create a ranged breakpoint with multiple locations."));
- resolve_sal_pc (&sal_start);
+ sal_start = lsal_start->sals.sals[0];
+ addr_string_start = savestring (arg_start, arg - arg_start);
+ make_cleanup (xfree, addr_string_start);
arg++; /* Skip the comma. */
- while (*arg == ' ' || *arg == '\t')
- arg++;
+ arg = skip_spaces (arg);
/* Parse the end location. */
- sals_end.sals = NULL;
- sals_end.nelts = 0;
init_linespec_result (&canonical_end);
arg_start = arg;
- /* We call decode_line_1 directly here instead of using
+ /* We call decode_line_full directly here instead of using
parse_breakpoint_sals because we need to specify the start location's
symtab and line as the default symtab and line for the end of the
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 can be NULL if it was of the form "*0xdeadbeef". */
- if (canonical_end.canonical == NULL)
- canonical_end.canonical = xcalloc (1, sizeof (char *));
- /* Add the string if not present. */
- if (arg_start != arg && canonical_end.canonical[0] == NULL)
- canonical_end.canonical[0] = savestring (arg_start, arg - arg_start);
-
- sal_end = sals_end.sals[0];
- addr_string_end = canonical_end.canonical[0];
- make_cleanup (xfree, addr_string_end);
- xfree (sals_end.sals);
- xfree (canonical_end.canonical);
+ decode_line_full (&arg, DECODE_LINE_FUNFIRSTLINE,
+ sal_start.symtab, sal_start.line,
+ &canonical_end, NULL, NULL);
+
+ make_cleanup_destroy_linespec_result (&canonical_end);
- if (sals_end.nelts == 0)
+ if (VEC_empty (linespec_sals, canonical_end.sals))
error (_("Could not find location of the end of the range."));
- else if (sals_end.nelts != 1)
+
+ lsal_end = VEC_index (linespec_sals, canonical_end.sals, 0);
+ if (VEC_length (linespec_sals, canonical_end.sals) > 1
+ || lsal_end->sals.nelts != 1)
error (_("Cannot create a ranged breakpoint with multiple locations."));
- resolve_sal_pc (&sal_end);
+ sal_end = lsal_end->sals.sals[0];
+ addr_string_end = savestring (arg_start, arg - arg_start);
+ make_cleanup (xfree, addr_string_end);
end = find_breakpoint_range_end (sal_end);
if (sal_start.pc > end)
@@ -8528,11 +8387,11 @@ break_range_command (char *arg, int from_tty)
set_breakpoint_count (breakpoint_count + 1);
b->number = breakpoint_count;
b->disposition = disp_donttouch;
- b->addr_string = addr_string_start;
- b->addr_string_range_end = addr_string_end;
+ b->addr_string = xstrdup (addr_string_start);
+ b->addr_string_range_end = xstrdup (addr_string_end);
b->loc->length = length;
- discard_cleanups (cleanup_bkpt);
+ do_cleanups (cleanup_bkpt);
mention (b);
observer_notify_breakpoint_created (b);
@@ -9639,12 +9498,12 @@ until_break_command (char *arg, int from_tty, int anywhere)
this function. */
if (last_displayed_sal_is_valid ())
- sals = decode_line_1 (&arg, 1,
+ sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
get_last_displayed_symtab (),
- get_last_displayed_line (),
- NULL);
+ get_last_displayed_line ());
else
- sals = decode_line_1 (&arg, 1, (struct symtab *) NULL, 0, NULL);
+ sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE,
+ (struct symtab *) NULL, 0);
if (sals.nelts != 1)
error (_("Couldn't get information on specified line."));
@@ -10155,7 +10014,8 @@ clear_command (char *arg, int from_tty)
if (arg)
{
- sals = decode_line_spec (arg, 1);
+ sals = decode_line_spec (arg, (DECODE_LINE_FUNFIRSTLINE
+ | DECODE_LINE_LIST_MODE));
default_match = 0;
}
else
@@ -10227,18 +10087,21 @@ clear_command (char *arg, int from_tty)
struct bp_location *loc = b->loc;
for (; loc; loc = loc->next)
{
- int pc_match = sal.pc
- && (loc->pspace == sal.pspace)
- && (loc->address == sal.pc)
- && (!section_is_overlay (loc->section)
- || loc->section == sal.section);
- int line_match = ((default_match || (0 == sal.pc))
- && b->source_file != NULL
+ /* If the user specified file:line, don't allow a PC
+ match. This matches historical gdb behavior. */
+ int pc_match = (!sal.explicit_line
+ && sal.pc
+ && (loc->pspace == sal.pspace)
+ && (loc->address == sal.pc)
+ && (!section_is_overlay (loc->section)
+ || loc->section == sal.section));
+ int line_match = ((default_match || sal.explicit_line)
+ && loc->source_file != NULL
&& sal.symtab != NULL
&& sal.pspace == loc->pspace
- && filename_cmp (b->source_file,
+ && filename_cmp (loc->source_file,
sal.symtab->filename) == 0
- && b->line_number == sal.line);
+ && loc->line_number == sal.line);
if (pc_match || line_match)
{
match = 1;
@@ -10830,15 +10693,25 @@ say_where (struct breakpoint *b)
}
else
{
- if (opts.addressprint || b->source_file == NULL)
+ if (opts.addressprint || b->loc->source_file == NULL)
{
printf_filtered (" at ");
fputs_filtered (paddress (b->loc->gdbarch, b->loc->address),
gdb_stdout);
}
- if (b->source_file)
- printf_filtered (": file %s, line %d.",
- b->source_file, b->line_number);
+ if (b->loc->source_file)
+ {
+ /* If there is a single location, we can print the location
+ more nicely. */
+ if (b->loc->next == NULL)
+ printf_filtered (": file %s, line %d.",
+ b->loc->source_file, b->loc->line_number);
+ else
+ /* This is not ideal, but each location may have a
+ different file name, and this at least reflects the
+ real situation somewhat. */
+ printf_filtered (": %s.", b->addr_string);
+ }
if (b->loc->next)
{
@@ -10858,6 +10731,7 @@ bp_location_dtor (struct bp_location *self)
{
xfree (self->cond);
xfree (self->function_name);
+ xfree (self->source_file);
}
static const struct bp_location_ops bp_location_ops =
@@ -10874,8 +10748,8 @@ base_breakpoint_dtor (struct breakpoint *self)
decref_counted_command_line (&self->commands);
xfree (self->cond_string);
xfree (self->addr_string);
+ xfree (self->filter);
xfree (self->addr_string_range_end);
- xfree (self->source_file);
}
static struct bp_location *
@@ -11710,17 +11584,18 @@ update_static_tracepoint (struct breakpoint *b, struct symtab_and_line sal)
ui_out_field_int (uiout, "line", sal.line);
ui_out_text (uiout, "\n");
- b->line_number = sal.line;
+ b->loc->line_number = sal.line;
- xfree (b->source_file);
+ xfree (b->loc->source_file);
if (sym)
- b->source_file = xstrdup (sal.symtab->filename);
+ b->loc->source_file = xstrdup (sal.symtab->filename);
else
- b->source_file = NULL;
+ b->loc->source_file = NULL;
xfree (b->addr_string);
b->addr_string = xstrprintf ("%s:%d",
- sal.symtab->filename, b->line_number);
+ sal.symtab->filename,
+ b->loc->line_number);
/* Might be nice to check if function changed, and warn if
so. */
@@ -11770,8 +11645,17 @@ update_breakpoint_locations (struct breakpoint *b,
int i;
struct bp_location *existing_locations = b->loc;
- /* Ranged breakpoints have only one start location and one end location. */
- gdb_assert (sals_end.nelts == 0 || (sals.nelts == 1 && sals_end.nelts == 1));
+ if (sals_end.nelts != 0 && (sals.nelts != 1 || sals_end.nelts != 1))
+ {
+ /* Ranged breakpoints have only one start location and one end
+ location. */
+ b->enable_state = bp_disabled;
+ update_global_location_list (1);
+ printf_unfiltered (_("Could not reset ranged breakpoint %d: "
+ "multiple locations found\n"),
+ b->number);
+ return;
+ }
/* If there's no new locations, and all existing locations are
pending, don't do anything. This optimizes the common case where
@@ -11786,8 +11670,11 @@ update_breakpoint_locations (struct breakpoint *b,
for (i = 0; i < sals.nelts; ++i)
{
- struct bp_location *new_loc =
- add_location_to_breakpoint (b, &(sals.sals[i]));
+ struct bp_location *new_loc;
+
+ switch_to_program_space_and_thread (sals.sals[i].pspace);
+
+ new_loc = add_location_to_breakpoint (b, &(sals.sals[i]));
/* Reparse conditions, they might contain references to the
old symtab. */
@@ -11811,16 +11698,6 @@ update_breakpoint_locations (struct breakpoint *b,
}
}
- if (b->source_file != NULL)
- xfree (b->source_file);
- if (sals.sals[i].symtab == NULL)
- b->source_file = NULL;
- else
- b->source_file = xstrdup (sals.sals[i].symtab->filename);
-
- if (b->line_number == 0)
- b->line_number = sals.sals[i].line;
-
if (sals_end.nelts)
{
CORE_ADDR end = find_breakpoint_range_end (sals_end.sals[0]);
@@ -11887,7 +11764,7 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
char *s;
int marker_spec;
struct symtabs_and_lines sals = {0};
- struct gdb_exception e;
+ volatile struct gdb_exception e;
s = addr_string;
marker_spec = b->type == bp_static_tracepoint && is_marker_spec (s);
@@ -11908,7 +11785,31 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
error (_("marker %s not found"), tp->static_trace_marker_id);
}
else
- sals = decode_line_1 (&s, 1, (struct symtab *) NULL, 0, NULL);
+ {
+ struct linespec_result canonical;
+
+ init_linespec_result (&canonical);
+ decode_line_full (&s, DECODE_LINE_FUNFIRSTLINE,
+ (struct symtab *) NULL, 0,
+ &canonical, multiple_symbols_all,
+ b->filter);
+
+ /* We should get 0 or 1 resulting SALs. */
+ gdb_assert (VEC_length (linespec_sals, canonical.sals) < 2);
+
+ if (VEC_length (linespec_sals, canonical.sals) > 0)
+ {
+ struct linespec_sals *lsal;
+
+ lsal = VEC_index (linespec_sals, canonical.sals, 0);
+ sals = lsal->sals;
+ /* Arrange it so the destructor does not free the
+ contents. */
+ lsal->sals.sals = NULL;
+ }
+
+ destroy_linespec_result (&canonical);
+ }
}
if (e.reason < 0)
{
@@ -11942,9 +11843,10 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
if (e.reason == 0 || e.error != NOT_FOUND_ERROR)
{
- gdb_assert (sals.nelts == 1);
+ int i;
- resolve_sal_pc (&sals.sals[0]);
+ for (i = 0; i < sals.nelts; ++i)
+ resolve_sal_pc (&sals.sals[i]);
if (b->condition_not_parsed && s && s[0])
{
char *cond_string = 0;
@@ -11987,7 +11889,7 @@ breakpoint_re_set_default (struct breakpoint *b)
if (found)
{
make_cleanup (xfree, sals.sals);
- expanded = expand_line_sal_maybe (sals.sals[0]);
+ expanded = sals;
}
if (b->addr_string_range_end)
@@ -11996,7 +11898,7 @@ breakpoint_re_set_default (struct breakpoint *b)
if (found)
{
make_cleanup (xfree, sals_end.sals);
- expanded_end = expand_line_sal_maybe (sals_end.sals[0]);
+ expanded_end = sals_end;
}
}
@@ -12525,20 +12427,18 @@ invalidate_bp_value_on_memory_change (CORE_ADDR addr, int len,
if they aren't valid. */
struct symtabs_and_lines
-decode_line_spec_1 (char *string, int funfirstline)
+decode_line_spec_1 (char *string, int flags)
{
struct symtabs_and_lines sals;
if (string == 0)
error (_("Empty line specification."));
if (last_displayed_sal_is_valid ())
- sals = decode_line_1 (&string, funfirstline,
+ sals = decode_line_1 (&string, flags,
get_last_displayed_symtab (),
- get_last_displayed_line (),
- NULL);
+ get_last_displayed_line ());
else
- sals = decode_line_1 (&string, funfirstline,
- (struct symtab *) NULL, 0, NULL);
+ sals = decode_line_1 (&string, flags, (struct symtab *) NULL, 0);
if (*string)
error (_("Junk at end of line specification: %s"), string);
return sals;
diff --git a/gdb/breakpoint.h b/gdb/breakpoint.h
index de1491e..ead3930 100644
--- a/gdb/breakpoint.h
+++ b/gdb/breakpoint.h
@@ -397,6 +397,14 @@ struct bp_location
This variable keeps a number of events still to go, when
it becomes 0 this location is retired. */
int events_till_retirement;
+
+ /* Line number of this address. */
+
+ int line_number;
+
+ /* Source file name of this address. */
+
+ char *source_file;
};
/* This structure is a collection of function pointers that, if available,
@@ -544,14 +552,6 @@ struct breakpoint
/* Location(s) associated with this high-level breakpoint. */
struct bp_location *loc;
- /* Line number of this address. */
-
- int line_number;
-
- /* Source file name of this address. */
-
- char *source_file;
-
/* Non-zero means a silent breakpoint (don't print frame info
if we stop here). */
unsigned char silent;
@@ -575,6 +575,11 @@ struct breakpoint
/* String we used to set the breakpoint (malloc'd). */
char *addr_string;
+ /* The filter that should be passed to decode_line_full when
+ re-setting this breakpoint. This may be NULL, but otherwise is
+ allocated with xmalloc. */
+ char *filter;
+
/* For a ranged breakpoint, the string we used to find
the end of the range (malloc'd). */
char *addr_string_range_end;
diff --git a/gdb/cli/cli-cmds.c b/gdb/cli/cli-cmds.c
index d75a6c0..8832e0c 100644
--- a/gdb/cli/cli-cmds.c
+++ b/gdb/cli/cli-cmds.c
@@ -92,6 +92,9 @@ void apropos_command (char *, int);
/* Prototypes for local utility functions */
static void ambiguous_line_spec (struct symtabs_and_lines *);
+
+static void filter_sals (struct symtabs_and_lines *);
+
\f
/* Limit the call depth of user-defined commands */
int max_user_call_depth;
@@ -246,16 +249,6 @@ help_command (char *command, int from_tty)
help_cmd (command, gdb_stdout);
}
\f
-/* String compare function for qsort. */
-static int
-compare_strings (const void *arg1, const void *arg2)
-{
- const char **s1 = (const char **) arg1;
- const char **s2 = (const char **) arg2;
-
- return strcmp (*s1, *s2);
-}
-
/* The "complete" command is used by Emacs to implement completion. */
static void
@@ -796,8 +789,9 @@ 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, DECODE_LINE_LIST_MODE, 0, 0);
+ filter_sals (&sals);
if (! sals.nelts)
{
/* C++ */
@@ -926,8 +920,9 @@ 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, DECODE_LINE_LIST_MODE, 0, 0);
+ filter_sals (&sals);
if (!sals.nelts)
return; /* C++ */
if (sals.nelts > 1)
@@ -959,9 +954,11 @@ 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, DECODE_LINE_LIST_MODE, 0, 0);
else
- sals_end = decode_line_1 (&arg1, 0, sal.symtab, sal.line, 0);
+ sals_end = decode_line_1 (&arg1, DECODE_LINE_LIST_MODE,
+ sal.symtab, sal.line);
+ filter_sals (&sals);
if (sals_end.nelts == 0)
return;
if (sals_end.nelts > 1)
@@ -1472,6 +1469,85 @@ ambiguous_line_spec (struct symtabs_and_lines *sals)
sals->sals[i].symtab->filename, sals->sals[i].line);
}
+/* Sort function for filter_sals. */
+
+static int
+compare_symtabs (const void *a, const void *b)
+{
+ const struct symtab_and_line *sala = a;
+ const struct symtab_and_line *salb = b;
+ int r;
+
+ if (!sala->symtab->dirname)
+ {
+ if (salb->symtab->dirname)
+ return -1;
+ }
+ else if (!salb->symtab->dirname)
+ {
+ if (sala->symtab->dirname)
+ return 1;
+ }
+ else
+ {
+ r = filename_cmp (sala->symtab->dirname, salb->symtab->dirname);
+ if (r)
+ return r;
+ }
+
+ r = filename_cmp (sala->symtab->filename, salb->symtab->filename);
+ if (r)
+ return r;
+
+ if (sala->line < salb->line)
+ return -1;
+ return sala->line == salb->line ? 0 : 1;
+}
+
+/* Remove any SALs that do not match the current program space, or
+ which appear to be "file:line" duplicates. */
+
+static void
+filter_sals (struct symtabs_and_lines *sals)
+{
+ int i, out, prev;
+
+ out = 0;
+ for (i = 0; i < sals->nelts; ++i)
+ {
+ if (sals->sals[i].pspace == current_program_space
+ || sals->sals[i].symtab == NULL)
+ {
+ sals->sals[out] = sals->sals[i];
+ ++out;
+ }
+ }
+ sals->nelts = out;
+
+ qsort (sals->sals, sals->nelts, sizeof (struct symtab_and_line),
+ compare_symtabs);
+
+ out = 1;
+ prev = 0;
+ for (i = 1; i < sals->nelts; ++i)
+ {
+ if (compare_symtabs (&sals->sals[prev], &sals->sals[i]))
+ {
+ /* Symtabs differ. */
+ sals->sals[out] = sals->sals[i];
+ prev = out;
+ ++out;
+ }
+ }
+ sals->nelts = out;
+
+ if (sals->nelts == 0)
+ {
+ xfree (sals->sals);
+ sals->sals = NULL;
+ }
+}
+
static void
set_debug (char *arg, int from_tty)
{
diff --git a/gdb/defs.h b/gdb/defs.h
index b5bc6c5..040d9c9 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -425,6 +425,7 @@ char *ldirname (const char *filename);
char **gdb_buildargv (const char *);
int compare_positive_ints (const void *ap, const void *bp);
+int compare_strings (const void *ap, const void *bp);
/* A wrapper for bfd_errmsg to produce a more helpful error message
in the case of bfd_error_file_ambiguously recognized.
diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c
index 8a7d7e9..7547a40 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -443,9 +443,6 @@ func_addr_to_tail_call_list (struct gdbarch *gdbarch, CORE_ADDR addr)
return sym;
}
-/* Define VEC (CORE_ADDR) functions. */
-DEF_VEC_I (CORE_ADDR);
-
/* Verify function with entry point exact address ADDR can never call itself
via its tail calls (incl. transitively). Throw NO_ENTRY_VALUE_ERROR if it
can call itself via tail calls.
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 3f66c67..ba56065 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2439,10 +2439,38 @@ dw2_forget_cached_source_info (struct objfile *objfile)
dw2_free_cached_file_names, NULL);
}
+/* Helper function for dw2_map_symtabs_matching_filename that expands
+ the symtabs and calls the iterator. */
+
+static int
+dw2_map_expand_apply (struct objfile *objfile,
+ struct dwarf2_per_cu_data *per_cu,
+ const char *name,
+ const char *full_path, const char *real_path,
+ int (*callback) (struct symtab *, void *),
+ void *data)
+{
+ struct symtab *last_made = objfile->symtabs;
+
+ /* Don't visit already-expanded CUs. */
+ if (per_cu->v.quick->symtab)
+ return 0;
+
+ /* This may expand more than one symtab, and we want to iterate over
+ all of them. */
+ dw2_instantiate_symtab (objfile, per_cu);
+
+ return iterate_over_some_symtabs (name, full_path, real_path, callback, data,
+ objfile->symtabs, last_made);
+}
+
+/* Implementation of the map_symtabs_matching_filename method. */
+
static int
-dw2_lookup_symtab (struct objfile *objfile, const char *name,
- const char *full_path, const char *real_path,
- struct symtab **result)
+dw2_map_symtabs_matching_filename (struct objfile *objfile, const char *name,
+ const char *full_path, const char *real_path,
+ int (*callback) (struct symtab *, void *),
+ void *data)
{
int i;
const char *name_basename = lbasename (name);
@@ -2472,8 +2500,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (FILENAME_CMP (name, this_name) == 0)
{
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, per_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
if (check_basename && ! base_cu
@@ -2494,8 +2524,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (this_real_name != NULL
&& FILENAME_CMP (full_path, this_real_name) == 0)
{
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, per_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
}
@@ -2507,8 +2539,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (this_real_name != NULL
&& FILENAME_CMP (real_path, this_real_name) == 0)
{
- *result = dw2_instantiate_symtab (objfile, per_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, per_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
}
}
@@ -2516,8 +2550,10 @@ dw2_lookup_symtab (struct objfile *objfile, const char *name,
if (base_cu)
{
- *result = dw2_instantiate_symtab (objfile, base_cu);
- return 1;
+ if (dw2_map_expand_apply (objfile, base_cu,
+ name, full_path, real_path,
+ callback, data))
+ return 1;
}
return 0;
@@ -2867,7 +2903,7 @@ const struct quick_symbol_functions dwarf2_gdb_index_functions =
dw2_has_symbols,
dw2_find_last_source_symtab,
dw2_forget_cached_source_info,
- dw2_lookup_symtab,
+ dw2_map_symtabs_matching_filename,
dw2_lookup_symbol,
dw2_pre_expand_symtabs_matching,
dw2_print_stats,
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 7b935fe..5d94cd4 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -57,6 +57,7 @@
#include "tracepoint.h"
#include "inf-loop.h"
#include "continuations.h"
+#include "linespec.h"
/* Functions exported for general use, in inferior.h: */
@@ -1116,7 +1117,7 @@ jump_command (char *arg, int from_tty)
if (!arg)
error_no_arg (_("starting address"));
- sals = decode_line_spec_1 (arg, 1);
+ sals = decode_line_spec_1 (arg, DECODE_LINE_FUNFIRSTLINE);
if (sals.nelts != 1)
{
error (_("Unreasonable jump request"));
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 64ba837..6b391bc 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -45,108 +45,248 @@
#include "cli/cli-utils.h"
#include "filenames.h"
+typedef struct symtab *symtab_p;
+DEF_VEC_P (symtab_p);
+
+typedef struct symbol *symbolp;
+DEF_VEC_P (symbolp);
+
+typedef struct type *typep;
+DEF_VEC_P (typep);
+
+/* An address entry is used to ensure that any given location is only
+ added to the result a single time. It holds an address and the
+ program space from which the address came. */
+
+struct address_entry
+{
+ struct program_space *pspace;
+ CORE_ADDR addr;
+};
+
+/* 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. */
+
+struct linespec_state
+{
+ /* The program space as seen when the module was entered. */
+ struct program_space *program_space;
+
+ /* The default symtab to use, if no other symtab is specified. */
+ struct symtab *default_symtab;
+
+ /* The default line to use. */
+ int default_line;
+
+ /* If the linespec started with "FILE:", this holds all the matching
+ symtabs. Otherwise, it will hold a single NULL entry, meaning
+ that the default symtab should be used. */
+ VEC (symtab_p) *file_symtabs;
+
+ /* If the linespec started with "FILE:", this holds an xmalloc'd
+ copy of "FILE". */
+ char *user_filename;
+
+ /* If the linespec is "FUNCTION:LABEL", this holds an xmalloc'd copy
+ of "FUNCTION". */
+ char *user_function;
+
+ /* The 'funfirstline' value that was passed in to decode_line_1 or
+ decode_line_full. */
+ int funfirstline;
+
+ /* Nonzero if we are running in 'list' mode; see decode_line_list. */
+ int list_mode;
+
+ /* The 'canonical' value passed to decode_line_full, or NULL. */
+ struct linespec_result *canonical;
+
+ /* Canonical strings that mirror the symtabs_and_lines result. */
+ char **canonical_names;
+
+ /* This is a set of address_entry objects which is used to prevent
+ duplicate symbols from being entered into the result. */
+ htab_t addr_set;
+};
+
+/* This is a helper object that is used when collecting symbols into a
+ result. */
+
+struct collect_info
+{
+ /* The linespec object in use. */
+ struct linespec_state *state;
+
+ /* The result being accumulated. */
+ struct symtabs_and_lines result;
+
+ /* The current objfile; used only by the minimal symbol code. */
+ struct objfile *objfile;
+};
+
/* Prototypes for local functions. */
static void initialize_defaults (struct symtab **default_symtab,
int *default_line);
-static struct symtabs_and_lines decode_indirect (char **argptr);
+static struct symtabs_and_lines decode_indirect (struct linespec_state *self,
+ char **argptr);
static char *locate_first_half (char **argptr, int *is_quote_enclosed);
-static struct symtabs_and_lines decode_objc (char **argptr,
- int funfirstline,
- struct symtab *file_symtab,
- struct linespec_result *canonical,
- char *saved_arg);
+static struct symtabs_and_lines decode_objc (struct linespec_state *self,
+ char **argptr);
-static struct symtabs_and_lines decode_compound (char **argptr,
- int funfirstline,
- struct linespec_result *canonical,
- struct symtab *file_symtab,
+static struct symtabs_and_lines decode_compound (struct linespec_state *self,
+ char **argptr,
char *saved_arg,
char *p);
-static struct symbol *lookup_prefix_sym (char **argptr, char *p,
- struct symtab *);
+static VEC (symbolp) *lookup_prefix_sym (char **argptr, char *p,
+ VEC (symtab_p) *,
+ char **);
-static struct symtabs_and_lines find_method (int funfirstline,
- struct linespec_result *canonical,
+static struct symtabs_and_lines find_method (struct linespec_state *self,
char *saved_arg,
char *copy,
- struct type *t,
- struct symbol *sym_class,
- struct symtab *);
+ const char *class_name,
+ VEC (symbolp) *sym_classes);
static void cplusplus_error (const char *name, const char *fmt, ...)
ATTRIBUTE_NORETURN ATTRIBUTE_PRINTF (2, 3);
-static int total_number_of_methods (struct type *type);
+static char *find_toplevel_char (char *s, char c);
-static int find_methods (struct type *, char *,
- enum language, struct symbol **, struct symtab *);
+static int is_objc_method_format (const char *s);
-static int add_matching_methods (int method_counter, struct type *t,
- enum language language,
- struct symbol **sym_arr);
+static VEC (symtab_p) *symtabs_from_filename (char **argptr,
+ char *p, int is_quote_enclosed,
+ char **user_filename);
-static int add_constructors (int method_counter, struct type *t,
- enum language language,
- struct symbol **sym_arr);
+static VEC (symbolp) *find_function_symbols (char **argptr, char *p,
+ int is_quote_enclosed,
+ char **user_function);
-static void build_canonical_line_spec (struct symtab_and_line *,
- char *, struct linespec_result *);
+static struct symtabs_and_lines decode_all_digits (struct linespec_state *self,
+ char **argptr,
+ char *q);
-static char *find_toplevel_char (char *s, char c);
+static struct symtabs_and_lines decode_dollar (struct linespec_state *self,
+ char *copy);
-static int is_objc_method_format (const char *s);
+static int decode_label (struct linespec_state *self,
+ VEC (symbolp) *function_symbols,
+ char *copy,
+ struct symtabs_and_lines *result);
+
+static struct symtabs_and_lines decode_variable (struct linespec_state *self,
+ char *copy);
-static struct symtabs_and_lines decode_line_2 (struct symbol *[],
- int, int,
- struct linespec_result *);
+static int symbol_to_sal (struct symtab_and_line *result,
+ int funfirstline, struct symbol *sym);
-static struct symtab *symtab_from_filename (char **argptr,
- char *p, int is_quote_enclosed);
+static void add_matching_symbols_to_info (const char *name,
+ struct collect_info *info,
+ struct program_space *pspace);
-static struct symbol *find_function_symbol (char **argptr, char *p,
- int is_quote_enclosed);
+static void add_all_symbol_names_from_pspace (struct collect_info *info,
+ struct program_space *pspace,
+ VEC (const_char_ptr) *names);
-static struct
-symtabs_and_lines decode_all_digits (char **argptr,
- struct symtab *default_symtab,
- int default_line,
- struct linespec_result *canonical,
- struct symtab *file_symtab,
- char *q);
+/* Helper functions. */
-static struct symtabs_and_lines decode_dollar (char *copy,
- int funfirstline,
- struct symtab *default_symtab,
- struct linespec_result *canonical,
- struct symtab *file_symtab);
+/* Add SAL to SALS. */
-static int decode_label (struct symbol *function_symbol,
- char *copy, struct linespec_result *canonical,
- struct symtabs_and_lines *result);
+static void
+add_sal_to_sals_basic (struct symtabs_and_lines *sals,
+ struct symtab_and_line *sal)
+{
+ ++sals->nelts;
+ sals->sals = xrealloc (sals->sals, sals->nelts * sizeof (sals->sals[0]));
+ sals->sals[sals->nelts - 1] = *sal;
+}
-static struct symtabs_and_lines decode_variable (char *copy,
- int funfirstline,
- struct linespec_result *canonical,
- struct symtab *file_symtab);
+/* Add SAL to SALS, and also update SELF->CANONICAL_NAMES to reflect
+ the new sal, if needed. If not NULL, SYMNAME is the name of the
+ symbol to use when constructing the new canonical name. */
-static struct
-symtabs_and_lines symbol_found (int funfirstline,
- struct linespec_result *canonical,
- char *copy,
- struct symbol *sym,
- struct symtab *file_symtab,
- struct symbol *function_symbol);
+static void
+add_sal_to_sals (struct linespec_state *self,
+ struct symtabs_and_lines *sals,
+ struct symtab_and_line *sal,
+ const char *symname)
+{
+ add_sal_to_sals_basic (sals, sal);
-static struct
-symtabs_and_lines minsym_found (int funfirstline,
- struct minimal_symbol *msymbol);
+ if (self->canonical)
+ {
+ char *canonical_name = NULL;
-/* Helper functions. */
+ self->canonical_names = xrealloc (self->canonical_names,
+ sals->nelts * sizeof (char *));
+ if (sal->symtab && sal->symtab->filename)
+ {
+ char *filename = sal->symtab->filename;
+
+ /* Note that the filter doesn't have to be a valid linespec
+ input. */
+ if (symname != NULL && sal->line != 0)
+ canonical_name = xstrprintf ("%s:%s:%d", filename, symname,
+ sal->line);
+ else if (symname != NULL)
+ canonical_name = xstrprintf ("%s:%s", filename, symname);
+ else
+ canonical_name = xstrprintf ("%s:%d", filename, sal->line);
+ }
+
+ self->canonical_names[sals->nelts - 1] = canonical_name;
+ }
+}
+
+/* A hash function for address_entry. */
+
+static hashval_t
+hash_address_entry (const void *p)
+{
+ const struct address_entry *aep = p;
+
+ return iterative_hash_object (*aep, 0);
+}
+
+/* An equality function for address_entry. */
+
+static int
+eq_address_entry (const void *a, const void *b)
+{
+ const struct address_entry *aea = a;
+ const struct address_entry *aeb = b;
+
+ return aea->pspace == aeb->pspace && aea->addr == aeb->addr;
+}
+
+/* Check whether the address, represented by PSPACE and ADDR, is
+ already in the set. If so, return 0. Otherwise, add it and return
+ 1. */
+
+static int
+maybe_add_address (htab_t set, struct program_space *pspace, CORE_ADDR addr)
+{
+ struct address_entry e, *p;
+ void **slot;
+
+ e.pspace = pspace;
+ e.addr = addr;
+ slot = htab_find_slot (set, &e, INSERT);
+ if (*slot)
+ return 0;
+
+ p = XNEW (struct address_entry);
+ memcpy (p, &e, sizeof (struct address_entry));
+ *slot = p;
+
+ return 1;
+}
/* Issue a helpful hint on using the command completion feature on
single quoted demangled C++ symbols as part of the completion
@@ -181,26 +321,64 @@ cplusplus_error (const char *name, const char *fmt, ...)
throw_error (NOT_FOUND_ERROR, "%s", message);
}
-/* Return the number of methods described for TYPE, including the
- methods from types it derives from. This can't be done in the symbol
- reader because the type of the baseclass might still be stubbed
- when the definition of the derived class is parsed. */
+/* A helper for iterate_over_all_matching_symtabs that is passed as a
+ callback to the expand_symtabs_matching method. */
static int
-total_number_of_methods (struct type *type)
+iterate_name_matcher (const char *name, void *d)
{
- int n;
- int count;
+ const char **dname = d;
- CHECK_TYPEDEF (type);
- if (! HAVE_CPLUS_STRUCT (type))
- return 0;
- count = TYPE_NFN_FIELDS_TOTAL (type);
+ if (strcmp_iw (name, *dname) == 0)
+ return 1;
+ return 0;
+}
+
+/* A helper that walks over all matching symtabs in all objfiles and
+ calls CALLBACK for each symbol matching NAME. If SEARCH_PSPACE is
+ not NULL, then the search is restricted to just that program
+ space. */
+
+static void
+iterate_over_all_matching_symtabs (const char *name,
+ const domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data,
+ struct program_space *search_pspace)
+{
+ struct objfile *objfile;
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ {
+ if (search_pspace != NULL && search_pspace != pspace)
+ continue;
+ if (pspace->executing_startup)
+ continue;
+
+ set_current_program_space (pspace);
- for (n = 0; n < TYPE_N_BASECLASSES (type); n++)
- count += total_number_of_methods (TYPE_BASECLASS (type, n));
+ ALL_OBJFILES (objfile)
+ {
+ struct symtab *symtab;
+
+ if (objfile->sf)
+ objfile->sf->qf->expand_symtabs_matching (objfile, NULL,
+ iterate_name_matcher,
+ ALL_DOMAIN,
+ &name);
- return count;
+ ALL_OBJFILE_SYMTABS (objfile, symtab)
+ {
+ if (symtab->primary)
+ {
+ struct block *block;
+ block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+ iterate_over_symbols (block, name, domain, callback, data);
+ }
+ }
+ }
+ }
}
/* Returns the block to be used for symbol searches for the given SYMTAB,
@@ -227,40 +405,24 @@ get_search_block (struct symtab *symtab)
return block;
}
-/* Recursive helper function for decode_line_1.
- Look for methods named NAME in type T.
- Return number of matches.
- Put matches in SYM_ARR, which should have been allocated with
- a size of total_number_of_methods (T) * sizeof (struct symbol *).
- Note that this function is g++ specific. */
+/* A helper for find_method. This finds all methods in type T which
+ match NAME. It adds resulting symbol names to RESULT_NAMES, and
+ adds T's direct superclasses to SUPERCLASSES. */
-static int
-find_methods (struct type *t, char *name, enum language language,
- struct symbol **sym_arr, struct symtab *file_symtab)
+static void
+find_methods (struct type *t, const char *name,
+ VEC (const_char_ptr) **result_names,
+ VEC (typep) **superclasses)
{
int i1 = 0;
int ibase;
char *class_name = type_name_no_tag (t);
- struct cleanup *cleanup;
char *canon;
- /* NAME is typed by the user: it needs to be canonicalized before
- passing to lookup_symbol. */
- canon = cp_canonicalize_string_no_typedefs (name);
- if (canon != NULL)
- {
- name = canon;
- cleanup = make_cleanup (xfree, name);
- }
- else
- cleanup = make_cleanup (null_cleanup, NULL);
-
/* Ignore this class if it doesn't have a name. This is ugly, but
unless we figure out how to get the physname without the name of
the class, then the loop can't do any good. */
- if (class_name
- && (lookup_symbol_in_language (class_name, get_search_block (file_symtab),
- STRUCT_DOMAIN, language, (int *) NULL)))
+ if (class_name)
{
int method_counter;
int name_len = strlen (name);
@@ -288,181 +450,32 @@ find_methods (struct type *t, char *name, enum language language,
method_name = dem_opname;
}
- if (strcmp_iw (name, method_name) == 0)
- /* Find all the overloaded methods with that name. */
- i1 += add_matching_methods (method_counter, t, language,
- sym_arr + i1);
- else if (strncmp (class_name, name, name_len) == 0
- && (class_name[name_len] == '\0'
- || class_name[name_len] == '<'))
- i1 += add_constructors (method_counter, t, language,
- sym_arr + i1);
- }
- }
-
- /* Only search baseclasses if there is no match yet, since names in
- derived classes override those in baseclasses.
-
- FIXME: The above is not true; it is only true of member functions
- if they have the same number of arguments (??? - section 13.1 of the
- ARM says the function members are not in the same scope but doesn't
- really spell out the rules in a way I understand. In any case, if
- the number of arguments differ this is a case in which we can overload
- rather than hiding without any problem, and gcc 2.4.5 does overload
- rather than hiding in this case). */
-
- if (i1 == 0)
- for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
- i1 += find_methods (TYPE_BASECLASS (t, ibase), name,
- language, sym_arr + i1, file_symtab);
-
- do_cleanups (cleanup);
- return i1;
-}
-
-/* Add the symbols associated to methods of the class whose type is T
- and whose name matches the method indexed by METHOD_COUNTER in the
- array SYM_ARR. Return the number of methods added. */
-
-static int
-add_matching_methods (int method_counter, struct type *t,
- enum language language, struct symbol **sym_arr)
-{
- int field_counter;
- int i1 = 0;
-
- for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
- field_counter >= 0;
- --field_counter)
- {
- struct fn_field *f;
- const char *phys_name;
-
- f = TYPE_FN_FIELDLIST1 (t, method_counter);
+ if (strcmp_iw (method_name, name) == 0)
+ {
+ int field_counter;
- if (TYPE_FN_FIELD_STUB (f, field_counter))
- {
- char *tmp_name, *tmp2;
-
- tmp_name = gdb_mangle_name (t,
- method_counter,
- field_counter);
- tmp2 = alloca (strlen (tmp_name) + 1);
- strcpy (tmp2, tmp_name);
- xfree (tmp_name);
- phys_name = tmp2;
- }
- else
- phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
-
- sym_arr[i1] = lookup_symbol_in_language (phys_name,
- NULL, VAR_DOMAIN,
- language,
- (int *) NULL);
- if (sym_arr[i1])
- i1++;
- else
- {
- /* This error message gets printed, but the method
- still seems to be found.
- fputs_filtered("(Cannot find method ", gdb_stdout);
- fprintf_symbol_filtered (gdb_stdout, phys_name,
- language_cplus,
- DMGL_PARAMS | DMGL_ANSI);
- fputs_filtered(" - possibly inlined.)\n", gdb_stdout);
- */
+ for (field_counter = (TYPE_FN_FIELDLIST_LENGTH (t, method_counter)
+ - 1);
+ field_counter >= 0;
+ --field_counter)
+ {
+ struct fn_field *f;
+ const char *phys_name;
+
+ f = TYPE_FN_FIELDLIST1 (t, method_counter);
+ if (TYPE_FN_FIELD_STUB (f, field_counter))
+ continue;
+ phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+ VEC_safe_push (const_char_ptr, *result_names, phys_name);
+ }
+ }
}
}
- return i1;
-}
-
-/* Add the symbols associated to constructors of the class whose type
- is CLASS_TYPE and which are indexed by by METHOD_COUNTER to the
- array SYM_ARR. Return the number of methods added. */
-
-static int
-add_constructors (int method_counter, struct type *t,
- enum language language, struct symbol **sym_arr)
-{
- int field_counter;
- int i1 = 0;
-
- /* For GCC 3.x and stabs, constructors and destructors
- have names like __base_ctor and __complete_dtor.
- Check the physname for now if we're looking for a
- constructor. */
- for (field_counter
- = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
- field_counter >= 0;
- --field_counter)
- {
- struct fn_field *f;
- const char *phys_name;
-
- f = TYPE_FN_FIELDLIST1 (t, method_counter);
-
- /* GCC 3.x will never produce stabs stub methods, so
- we don't need to handle this case. */
- if (TYPE_FN_FIELD_STUB (f, field_counter))
- continue;
- phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
- if (! is_constructor_name (phys_name))
- continue;
-
- /* If this method is actually defined, include it in the
- list. */
- sym_arr[i1] = lookup_symbol_in_language (phys_name,
- NULL, VAR_DOMAIN,
- language,
- (int *) NULL);
- if (sym_arr[i1])
- i1++;
- }
-
- return i1;
-}
-
-/* Helper function for decode_line_1.
- Build a canonical line spec in CANONICAL if it is non-NULL and if
- the SAL has a symtab.
- If SYMNAME is non-NULL the canonical line spec is `filename:symname'.
- If SYMNAME is NULL the line number from SAL is used and the canonical
- line spec is `filename:linenum'. */
-
-static void
-build_canonical_line_spec (struct symtab_and_line *sal, char *symname,
- struct linespec_result *canonical)
-{
- char **canonical_arr;
- char *canonical_name;
- char *filename;
- struct symtab *s = sal->symtab;
-
- if (s == (struct symtab *) NULL
- || s->filename == (char *) NULL
- || canonical == NULL)
- return;
-
- canonical_arr = (char **) xmalloc (sizeof (char *));
- canonical->canonical = canonical_arr;
-
- filename = s->filename;
- if (symname != NULL)
- {
- canonical_name = xmalloc (strlen (filename) + strlen (symname) + 2);
- sprintf (canonical_name, "%s:%s", filename, symname);
- }
- else
- {
- canonical_name = xmalloc (strlen (filename) + 30);
- sprintf (canonical_name, "%s:%d", filename, sal->line);
- }
- canonical_arr[0] = canonical_name;
+ for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
+ VEC_safe_push (typep, *superclasses, TYPE_BASECLASS (t, ibase));
}
-
-
/* Find an instance of the character C in the string S that is outside
of all parenthesis pairs, single-quoted strings, and double-quoted
strings. Also, ignore the char within a template name, like a ','
@@ -518,147 +531,154 @@ is_objc_method_format (const char *s)
return 0;
}
-/* Given a list of NELTS symbols in SYM_ARR, return a list of lines to
- operate on (ask user if necessary).
- If CANONICAL is non-NULL return a corresponding array of mangled names
- as canonical line specs there. */
+/* Given FILTERS, a list of canonical names, filter the sals in RESULT
+ and store the result in SELF->CANONICAL. */
-static struct symtabs_and_lines
-decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
- struct linespec_result *canonical)
+static void
+filter_results (struct linespec_state *self,
+ struct symtabs_and_lines *result,
+ VEC (const_char_ptr) *filters)
+{
+ int i;
+ const char *name;
+
+ for (i = 0; VEC_iterate (const_char_ptr, filters, i, name); ++i)
+ {
+ struct linespec_sals lsal;
+ int j;
+
+ memset (&lsal, 0, sizeof (lsal));
+
+ for (j = 0; j < result->nelts; ++j)
+ {
+ if (strcmp (name, self->canonical_names[j]) == 0)
+ add_sal_to_sals_basic (&lsal.sals, &result->sals[j]);
+ }
+
+ if (lsal.sals.nelts > 0)
+ {
+ lsal.canonical = xstrdup (name);
+ VEC_safe_push (linespec_sals, self->canonical->sals, &lsal);
+ }
+ }
+
+ self->canonical->pre_expanded = 0;
+}
+
+/* Store RESULT into SELF->CANONICAL. */
+
+static void
+convert_results_to_lsals (struct linespec_state *self,
+ struct symtabs_and_lines *result)
{
- struct symtabs_and_lines values, return_values;
- char *args, *arg1;
+ struct linespec_sals lsal;
+
+ lsal.canonical = NULL;
+ lsal.sals = *result;
+ VEC_safe_push (linespec_sals, self->canonical->sals, &lsal);
+}
+
+/* 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
+ in SELF->CANONICAL is set up properly. */
+
+static void
+decode_line_2 (struct linespec_state *self,
+ struct symtabs_and_lines *result,
+ const char *select_mode)
+{
+ const char *iter;
+ char *args, *prompt;
int i;
- char *prompt;
- char *symname;
struct cleanup *old_chain;
- char **canonical_arr = (char **) NULL;
- const char *select_mode = multiple_symbols_select_mode ();
+ VEC (const_char_ptr) *item_names = NULL, *filters = NULL;
+ struct get_number_or_range_state state;
- if (select_mode == multiple_symbols_cancel)
- error (_("canceled because the command is ambiguous\n"
- "See set/show multiple-symbol."));
-
- values.sals = (struct symtab_and_line *)
- alloca (nelts * sizeof (struct symtab_and_line));
- return_values.sals = (struct symtab_and_line *)
- xmalloc (nelts * sizeof (struct symtab_and_line));
- old_chain = make_cleanup (xfree, return_values.sals);
+ gdb_assert (select_mode != multiple_symbols_all);
+ gdb_assert (self->canonical != NULL);
- if (canonical)
+ 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)
{
- canonical_arr = (char **) xmalloc (nelts * sizeof (char *));
- make_cleanup (xfree, canonical_arr);
- memset (canonical_arr, 0, nelts * sizeof (char *));
- canonical->canonical = canonical_arr;
+ int j, found = 0;
+ const char *iter;
+
+ gdb_assert (self->canonical_names[i] != NULL);
+ for (j = 0; VEC_iterate (const_char_ptr, item_names, j, iter); ++j)
+ {
+ if (strcmp (iter, self->canonical_names[i]) == 0)
+ {
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ VEC_safe_push (const_char_ptr, item_names, self->canonical_names[i]);
}
- i = 0;
- while (i < nelts)
+ if (select_mode == multiple_symbols_cancel
+ && VEC_length (const_char_ptr, item_names) > 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)
{
- init_sal (&return_values.sals[i]); /* Initialize to zeroes. */
- init_sal (&values.sals[i]);
- if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
- values.sals[i] = find_function_start_sal (sym_arr[i], funfirstline);
- i++;
+ do_cleanups (old_chain);
+ convert_results_to_lsals (self, result);
+ return;
}
- /* If select_mode is "all", then do not print the multiple-choice
- menu and act as if the user had chosen choice "1" (all). */
- if (select_mode == multiple_symbols_all
- || ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
- args = "1";
- else
+ 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);
+
+ prompt = getenv ("PS2");
+ if (prompt == NULL)
{
- i = 0;
- printf_unfiltered (_("[0] cancel\n[1] all\n"));
- while (i < nelts)
- {
- if (sym_arr[i] && SYMBOL_CLASS (sym_arr[i]) == LOC_BLOCK)
- {
- if (values.sals[i].symtab)
- printf_unfiltered ("[%d] %s at %s:%d\n",
- (i + 2),
- SYMBOL_PRINT_NAME (sym_arr[i]),
- values.sals[i].symtab->filename,
- values.sals[i].line);
- else
- printf_unfiltered (_("[%d] %s at ?FILE:%d [No symtab? "
- "Probably broken debug info...]\n"),
- (i + 2),
- SYMBOL_PRINT_NAME (sym_arr[i]),
- values.sals[i].line);
-
- }
- else
- printf_unfiltered (_("?HERE\n"));
- i++;
- }
-
- prompt = getenv ("PS2");
- if (prompt == NULL)
- {
- prompt = "> ";
- }
- args = command_line_input (prompt, 0, "overload-choice");
+ prompt = "> ";
}
+ args = command_line_input (prompt, 0, "overload-choice");
if (args == 0 || *args == 0)
error_no_arg (_("one or more choice numbers"));
- i = 0;
- while (*args)
+ init_number_or_range (&state, args);
+ while (!state.finished)
{
int num;
- arg1 = args;
- while (*arg1 >= '0' && *arg1 <= '9')
- arg1++;
- if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
- error (_("Arguments must be choice numbers."));
-
- num = atoi (args);
+ num = get_number_or_range (&state);
if (num == 0)
error (_("canceled"));
else if (num == 1)
{
- if (canonical_arr)
- {
- for (i = 0; i < nelts; i++)
- {
- if (canonical_arr[i] == NULL)
- {
- symname = SYMBOL_LINKAGE_NAME (sym_arr[i]);
- canonical_arr[i] = xstrdup (symname);
- }
- }
- }
- memcpy (return_values.sals, values.sals,
- (nelts * sizeof (struct symtab_and_line)));
- return_values.nelts = nelts;
- discard_cleanups (old_chain);
- return return_values;
+ /* We intentionally make this result in a single breakpoint,
+ contrary to what older versions of gdb did. The
+ rationale is that this lets a user get the
+ multiple_symbols_all behavior even with the 'ask'
+ setting; and he can get separate breakpoints by entering
+ "2-57" at the query. */
+ do_cleanups (old_chain);
+ convert_results_to_lsals (self, result);
+ return;
}
- if (num >= nelts + 2)
- {
- printf_unfiltered (_("No choice number %d.\n"), num);
- }
+ num -= 2;
+ if (num >= VEC_length (const_char_ptr, item_names))
+ printf_unfiltered (_("No choice number %d.\n"), num);
else
{
- num -= 2;
- if (values.sals[num].pc)
+ const char *elt = VEC_index (const_char_ptr, item_names, num);
+
+ if (elt != NULL)
{
- if (canonical_arr)
- {
- symname = SYMBOL_LINKAGE_NAME (sym_arr[num]);
- make_cleanup (xfree, symname);
- canonical_arr[i] = xstrdup (symname);
- }
- return_values.sals[i++] = values.sals[num];
- values.sals[num].pc = 0;
+ VEC_safe_push (const_char_ptr, filters, elt);
+ VEC_replace (const_char_ptr, item_names, num, NULL);
}
else
{
@@ -666,14 +686,10 @@ decode_line_2 (struct symbol *sym_arr[], int nelts, int funfirstline,
num);
}
}
-
- args = arg1;
- while (*args == ' ' || *args == '\t')
- args++;
}
- return_values.nelts = i;
- discard_cleanups (old_chain);
- return return_values;
+
+ filter_results (self, result, filters);
+ do_cleanups (old_chain);
}
/* Valid delimiters for linespec keywords "if", "thread" or "task". */
@@ -813,13 +829,10 @@ keep_name_info (char *p, int on_boundary)
can use as appropriate instead of make_symbol_completion_list. */
struct symtabs_and_lines
-decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
- int default_line, struct linespec_result *canonical)
+decode_line_internal (struct linespec_state *self, char **argptr)
{
char *p;
char *q;
- /* If a file name is specified, this is its symtab. */
- struct symtab *file_symtab = NULL;
char *copy;
/* This says whether or not something in *ARGPTR is quoted with
@@ -836,21 +849,26 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
/* The "first half" of the linespec. */
char *first_half;
- /* If we are parsing `function:label', this holds the symbol for the
- function. */
- struct symbol *function_symbol = NULL;
- /* If FUNCTION_SYMBOL is not NULL, then this is the exception that
+ /* If we are parsing `function:label', this holds the symbols
+ matching the function name. */
+ VEC (symbolp) *function_symbols = NULL;
+ /* If FUNCTION_SYMBOLS is not NULL, then this is the exception that
was thrown when trying to parse a filename. */
volatile struct gdb_exception file_exception;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+
/* Defaults have defaults. */
- initialize_defaults (&default_symtab, &default_line);
+ initialize_defaults (&self->default_symtab, &self->default_line);
/* See if arg is *PC. */
if (**argptr == '*')
- return decode_indirect (argptr);
+ {
+ do_cleanups (cleanup);
+ return decode_indirect (self, argptr);
+ }
is_quoted = (strchr (get_gdb_completer_quote_characters (),
**argptr) != NULL);
@@ -877,7 +895,14 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
symtab and strip the filename from ARGPTR. */
TRY_CATCH (file_exception, RETURN_MASK_ERROR)
{
- file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed);
+ self->file_symtabs = symtabs_from_filename (argptr, p, is_quote_enclosed,
+ &self->user_filename);
+ }
+
+ if (VEC_empty (symtab_p, self->file_symtabs))
+ {
+ /* A NULL entry means to use GLOBAL_DEFAULT_SYMTAB. */
+ VEC_safe_push (symtab_p, self->file_symtabs, NULL);
}
if (file_exception.reason >= 0)
@@ -903,10 +928,12 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
{
struct symtabs_and_lines values;
- values = decode_objc (argptr, funfirstline, file_symtab,
- canonical, saved_arg);
+ values = decode_objc (self, argptr);
if (values.sals != NULL)
- return values;
+ {
+ do_cleanups (cleanup);
+ return values;
+ }
}
/* Does it look like there actually were two parts? */
@@ -934,14 +961,16 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
TRY_CATCH (ex, RETURN_MASK_ERROR)
{
- values = decode_compound (argptr, funfirstline, canonical,
- file_symtab, saved_arg, p);
+ values = decode_compound (self, argptr, saved_arg, p);
}
if ((is_quoted || is_squote_enclosed) && **argptr == '\'')
*argptr = *argptr + 1;
if (ex.reason >= 0)
- return values;
+ {
+ do_cleanups (cleanup);
+ return values;
+ }
if (ex.error != NOT_FOUND_ERROR)
throw_exception (ex);
@@ -954,12 +983,16 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
then check whether we were really given `function:label'. */
if (file_exception.reason < 0)
{
- function_symbol = find_function_symbol (argptr, p,
- is_quote_enclosed);
+ function_symbols = find_function_symbols (argptr, p,
+ is_quote_enclosed,
+ &self->user_function);
+
/* If we did not find a function, re-throw the original
exception. */
- if (!function_symbol)
+ if (!function_symbols)
throw_exception (file_exception);
+
+ make_cleanup (VEC_cleanup (symbolp), &function_symbols);
}
/* Check for single quotes on the non-filename part. */
@@ -974,9 +1007,10 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
}
}
- /* file_symtab is specified file's symtab, or 0 if no file specified.
- If we are parsing `function:symbol', then FUNCTION_SYMBOL is the
- function before the `:'.
+ /* self->file_symtabs holds the specified file symtabs, or 0 if no file
+ specified.
+ If we are parsing `function:symbol', then FUNCTION_SYMBOLS holds the
+ functions before the `:'.
arg no longer contains the file name. */
/* If the filename was quoted, we must re-check the quotation. */
@@ -999,10 +1033,15 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
q++;
if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ',')
- && function_symbol == NULL)
- /* We found a token consisting of all digits -- at least one digit. */
- return decode_all_digits (argptr, default_symtab, default_line,
- canonical, file_symtab, q);
+ && function_symbols == NULL)
+ {
+ struct symtabs_and_lines values;
+
+ /* We found a token consisting of all digits -- at least one digit. */
+ values = decode_all_digits (self, argptr, q);
+ do_cleanups (cleanup);
+ return values;
+ }
/* Arg token is not digits => try it as a variable name
Find the next token (everything up to end or next whitespace). */
@@ -1042,91 +1081,218 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
}
else if (is_quoted || is_squote_enclosed)
copy[p - *argptr - 1] = '\0';
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
+
+ *argptr = skip_spaces (p);
/* If it starts with $: may be a legitimate variable or routine name
(e.g. HP-UX millicode routines such as $$dyncall), or it may
be history value, or it may be a convenience variable. */
- if (*copy == '$' && function_symbol == NULL)
- return decode_dollar (copy, funfirstline, default_symtab,
- canonical, file_symtab);
+ if (*copy == '$' && function_symbols == NULL)
+ {
+ struct symtabs_and_lines values;
+
+ values = decode_dollar (self, copy);
+ do_cleanups (cleanup);
+ return values;
+ }
/* Try the token as a label, but only if no file was specified,
because we can only really find labels in the current scope. */
- if (!file_symtab)
+ if (VEC_length (symtab_p, self->file_symtabs) == 1
+ && VEC_index (symtab_p, self->file_symtabs, 0) == NULL)
{
struct symtabs_and_lines label_result;
- if (decode_label (function_symbol, copy, canonical, &label_result))
- return label_result;
+ if (decode_label (self, function_symbols, copy, &label_result))
+ {
+ do_cleanups (cleanup);
+ return label_result;
+ }
}
- if (function_symbol)
+ if (function_symbols)
throw_exception (file_exception);
/* Look up that token as a variable.
If file specified, use that file's per-file block to start with. */
- return decode_variable (copy, funfirstline, canonical, file_symtab);
+ {
+ struct symtabs_and_lines values;
+
+ values = decode_variable (self, copy);
+ do_cleanups (cleanup);
+ return values;
+ }
}
-\f
+/* A constructor for linespec_state. */
-/* Now, more helper functions for decode_line_1. Some conventions
- that these functions follow:
-
- Decode_line_1 typically passes along some of its arguments or local
- variables to the subfunctions. It passes the variables by
- reference if they are modified by the subfunction, and by value
- otherwise.
-
- Some of the functions have side effects that don't arise from
- variables that are passed by reference. In particular, if a
- function is passed ARGPTR as an argument, it modifies what ARGPTR
- points to; typically, it advances *ARGPTR past whatever substring
- it has just looked at. (If it doesn't modify *ARGPTR, then the
- function gets passed *ARGPTR instead, which is then called ARG.)
- Also, functions that return a struct symtabs_and_lines may modify
- CANONICAL, as in the description of decode_line_1.
-
- If a function returns a struct symtabs_and_lines, then that struct
- will immediately make its way up the call chain to be returned by
- decode_line_1. In particular, all of the functions decode_XXX
- calculate the appropriate struct symtabs_and_lines, under the
- assumption that their argument is of the form XXX. */
+static void
+linespec_state_constructor (struct linespec_state *self,
+ int flags,
+ struct symtab *default_symtab,
+ int default_line,
+ struct linespec_result *canonical)
+{
+ memset (self, 0, sizeof (*self));
+ self->funfirstline = (flags & DECODE_LINE_FUNFIRSTLINE) ? 1 : 0;
+ self->list_mode = (flags & DECODE_LINE_LIST_MODE) ? 1 : 0;
+ self->default_symtab = default_symtab;
+ self->default_line = default_line;
+ self->canonical = canonical;
+ self->program_space = current_program_space;
+ self->addr_set = htab_create_alloc (10, hash_address_entry, eq_address_entry,
+ xfree, xcalloc, xfree);
+}
-/* First, some functions to initialize stuff at the beggining of the
- function. */
+/* A destructor for linespec_state. */
static void
-initialize_defaults (struct symtab **default_symtab, int *default_line)
+linespec_state_destructor (void *arg)
{
- if (*default_symtab == 0)
- {
- /* Use whatever we have for the default source line. We don't use
- get_current_or_default_symtab_and_line as it can recurse and call
- us back! */
- struct symtab_and_line cursal =
- get_current_source_symtab_and_line ();
-
- *default_symtab = cursal.symtab;
- *default_line = cursal.line;
- }
-}
+ struct linespec_state *self = arg;
-\f
+ xfree (self->user_filename);
+ xfree (self->user_function);
+ VEC_free (symtab_p, self->file_symtabs);
+ htab_delete (self->addr_set);
+}
-/* Decode arg of the form *PC. */
+/* See linespec.h. */
-static struct symtabs_and_lines
-decode_indirect (char **argptr)
+void
+decode_line_full (char **argptr, int flags,
+ struct symtab *default_symtab,
+ int default_line, struct linespec_result *canonical,
+ const char *select_mode,
+ const char *filter)
{
- struct symtabs_and_lines values;
- CORE_ADDR pc;
-
+ struct symtabs_and_lines result;
+ struct linespec_state state;
+ struct cleanup *cleanups;
+ char *arg_start = *argptr;
+ VEC (const_char_ptr) *filters = NULL;
+
+ gdb_assert (canonical != NULL);
+ /* The filter only makes sense for 'all'. */
+ gdb_assert (filter == NULL || select_mode == multiple_symbols_all);
+ gdb_assert (select_mode == NULL
+ || select_mode == multiple_symbols_all
+ || select_mode == multiple_symbols_ask
+ || select_mode == multiple_symbols_cancel);
+ gdb_assert ((flags & DECODE_LINE_LIST_MODE) == 0);
+
+ linespec_state_constructor (&state, flags,
+ default_symtab, default_line, canonical);
+ cleanups = make_cleanup (linespec_state_destructor, &state);
+ save_current_program_space ();
+
+ result = decode_line_internal (&state, argptr);
+
+ gdb_assert (result.nelts == 1 || canonical->pre_expanded);
+ gdb_assert (canonical->addr_string != NULL);
+ canonical->pre_expanded = 1;
+
+ /* Fill in the missing canonical names. */
+ if (result.nelts > 0)
+ {
+ int i;
+
+ if (state.canonical_names == NULL)
+ state.canonical_names = xcalloc (result.nelts, sizeof (char *));
+ make_cleanup (xfree, state.canonical_names);
+ for (i = 0; i < result.nelts; ++i)
+ {
+ if (state.canonical_names[i] == NULL)
+ state.canonical_names[i] = savestring (arg_start,
+ *argptr - arg_start);
+ make_cleanup (xfree, state.canonical_names[i]);
+ }
+ }
+
+ if (select_mode == NULL)
+ {
+ if (ui_out_is_mi_like_p (interp_ui_out (top_level_interpreter ())))
+ select_mode = multiple_symbols_all;
+ else
+ select_mode = multiple_symbols_select_mode ();
+ }
+
+ if (select_mode == multiple_symbols_all)
+ {
+ if (filter != NULL)
+ {
+ make_cleanup (VEC_cleanup (const_char_ptr), &filters);
+ VEC_safe_push (const_char_ptr, filters, filter);
+ filter_results (&state, &result, filters);
+ }
+ else
+ convert_results_to_lsals (&state, &result);
+ }
+ else
+ decode_line_2 (&state, &result, select_mode);
+
+ do_cleanups (cleanups);
+}
+
+struct symtabs_and_lines
+decode_line_1 (char **argptr, int flags,
+ struct symtab *default_symtab,
+ int default_line)
+{
+ struct symtabs_and_lines result;
+ struct linespec_state state;
+ struct cleanup *cleanups;
+
+ linespec_state_constructor (&state, flags,
+ default_symtab, default_line, NULL);
+ cleanups = make_cleanup (linespec_state_destructor, &state);
+ save_current_program_space ();
+
+ result = decode_line_internal (&state, argptr);
+ do_cleanups (cleanups);
+ return result;
+}
+
+\f
+
+/* First, some functions to initialize stuff at the beggining of the
+ function. */
+
+static void
+initialize_defaults (struct symtab **default_symtab, int *default_line)
+{
+ if (*default_symtab == 0)
+ {
+ /* Use whatever we have for the default source line. We don't use
+ get_current_or_default_symtab_and_line as it can recurse and call
+ us back! */
+ struct symtab_and_line cursal =
+ get_current_source_symtab_and_line ();
+
+ *default_symtab = cursal.symtab;
+ *default_line = cursal.line;
+ }
+}
+
+\f
+
+/* Decode arg of the form *PC. */
+
+static struct symtabs_and_lines
+decode_indirect (struct linespec_state *self, char **argptr)
+{
+ struct symtabs_and_lines values;
+ CORE_ADDR pc;
+ char *initial = *argptr;
+
+ if (current_program_space->executing_startup)
+ /* The error message doesn't really matter, because this case
+ should only hit during breakpoint reset. */
+ throw_error (NOT_FOUND_ERROR, _("cannot evaluate expressions while "
+ "program space is in startup"));
+
(*argptr)++;
pc = value_as_address (parse_to_comma_and_eval (argptr));
@@ -1139,6 +1305,9 @@ decode_indirect (char **argptr)
values.sals[0].section = find_pc_overlay (pc);
values.sals[0].explicit_pc = 1;
+ if (self->canonical)
+ self->canonical->addr_string = savestring (initial, *argptr - initial);
+
return values;
}
@@ -1246,8 +1415,7 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
break;
}
}
- while (p[0] == ' ' || p[0] == '\t')
- p++;
+ p = skip_spaces (p);
/* If the closing double quote was left at the end, remove it. */
if (*is_quote_enclosed)
@@ -1275,94 +1443,52 @@ locate_first_half (char **argptr, int *is_quote_enclosed)
than one method that could represent the selector, then use some of
the existing C++ code to let the user choose one. */
-struct symtabs_and_lines
-decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab,
- struct linespec_result *canonical, char *saved_arg)
+static struct symtabs_and_lines
+decode_objc (struct linespec_state *self, char **argptr)
{
- struct symtabs_and_lines values;
- struct symbol **sym_arr = NULL;
- struct symbol *sym = NULL;
- struct block *block = NULL;
- unsigned i1 = 0;
- unsigned i2 = 0;
+ struct collect_info info;
+ VEC (const_char_ptr) *symbol_names = NULL;
+ char *new_argptr;
+ struct cleanup *cleanup = make_cleanup (VEC_cleanup (const_char_ptr),
+ &symbol_names);
+
+ info.state = self;
+ info.result.sals = NULL;
+ info.result.nelts = 0;
+ info.objfile = NULL;
+
+ new_argptr = find_imps (*argptr, &symbol_names);
+ if (VEC_empty (const_char_ptr, symbol_names))
+ {
+ do_cleanups (cleanup);
+ return info.result;
+ }
- values.sals = NULL;
- values.nelts = 0;
+ add_all_symbol_names_from_pspace (&info, NULL, symbol_names);
- find_imps (file_symtab, get_search_block (file_symtab), *argptr,
- NULL, &i1, &i2);
-
- if (i1 > 0)
+ if (info.result.nelts > 0)
{
- sym_arr = (struct symbol **)
- alloca ((i1 + 1) * sizeof (struct symbol *));
- sym_arr[i1] = NULL;
+ char *saved_arg;
- *argptr = find_imps (file_symtab, block, *argptr, sym_arr, &i1, &i2);
- }
+ saved_arg = alloca (new_argptr - *argptr + 1);
+ memcpy (saved_arg, *argptr, new_argptr - *argptr);
+ saved_arg[new_argptr - *argptr] = '\0';
- /* i1 now represents the TOTAL number of matches found.
- i2 represents how many HIGH-LEVEL (struct symbol) matches,
- which will come first in the sym_arr array. Any low-level
- (minimal_symbol) matches will follow those. */
-
- if (i1 == 1)
- {
- if (i2 > 0)
- {
- /* Already a struct symbol. */
- sym = sym_arr[0];
- }
- else
+ if (self->canonical)
{
- sym = find_pc_function (SYMBOL_VALUE_ADDRESS (sym_arr[0]));
- if ((sym != NULL) && strcmp (SYMBOL_LINKAGE_NAME (sym_arr[0]),
- SYMBOL_LINKAGE_NAME (sym)) != 0)
- {
- warning (_("debugging symbol \"%s\" does "
- "not match selector; ignoring"),
- SYMBOL_LINKAGE_NAME (sym));
- sym = NULL;
- }
- }
-
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
-
- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- /* Canonicalize this, so it remains resolved for dylib loads. */
- values.sals[0] = find_function_start_sal (sym, funfirstline);
- build_canonical_line_spec (values.sals,
- SYMBOL_NATURAL_NAME (sym), canonical);
- }
- else
- {
- /* The only match was a non-debuggable symbol, which might point
- to a function descriptor; resolve it to the actual code address
- instead. */
- struct minimal_symbol *msymbol = (struct minimal_symbol *)sym_arr[0];
- struct objfile *objfile = msymbol_objfile (msymbol);
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
- CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol);
-
- pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
- ¤t_target);
-
- init_sal (&values.sals[0]);
- values.sals[0].pc = pc;
+ self->canonical->pre_expanded = 1;
+ if (self->user_filename)
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", self->user_filename, saved_arg);
+ else
+ self->canonical->addr_string = xstrdup (saved_arg);
}
- return values;
}
- if (i1 > 1)
- {
- /* More than one match. The user must choose one or more. */
- return decode_line_2 (sym_arr, i2, funfirstline, canonical);
- }
+ *argptr = new_argptr;
- return values;
+ do_cleanups (cleanup);
+ return info.result;
}
/* This handles C++ and Java compound data structures. P should point
@@ -1371,9 +1497,8 @@ decode_objc (char **argptr, int funfirstline, struct symtab *file_symtab,
pointing to "AAA::inA::fun" and P pointing to "::inA::fun". */
static struct symtabs_and_lines
-decode_compound (char **argptr, int funfirstline,
- struct linespec_result *canonical, struct symtab *file_symtab,
- char *the_real_saved_arg, char *p)
+decode_compound (struct linespec_state *self,
+ char **argptr, char *the_real_saved_arg, char *p)
{
struct symtabs_and_lines values;
char *p2, *name, *canon;
@@ -1381,10 +1506,9 @@ decode_compound (char **argptr, int funfirstline,
char *temp_end;
struct symbol *sym;
char *copy;
- struct symbol *sym_class;
- struct type *t;
- char *saved_arg;
- struct cleanup *cleanup;
+ VEC (symbolp) *sym_classes;
+ char *saved_arg, *class_name;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
/* If the user specified any completer quote characters in the input,
strip them. They are superfluous. */
@@ -1419,8 +1543,7 @@ decode_compound (char **argptr, int funfirstline,
2) AAA::inA isn't the name of a class. In that case, either the
user made a typo, AAA::inA is the name of a namespace, or it is
the name of a minimal symbol.
- We just look up AAA::inA::fun with lookup_symbol. If that fails,
- try lookup_minimal_symbol.
+ In this case we just delegate to decode_variable.
Thus, our first task is to find everything before the last set of
double-colons and figure out if it's the name of a class. So we
@@ -1520,15 +1643,14 @@ decode_compound (char **argptr, int funfirstline,
/* Before the call, argptr->"AAA::inA::fun",
p->"", p2->"::fun". After the call: argptr->"fun", p, p2
unchanged. */
- sym_class = lookup_prefix_sym (argptr, p2, file_symtab);
-
- /* If sym_class has been found, and if "AAA::inA" is a class, then
- we're in case 1 above. So we look up "fun" as a method of that
- class. */
- if (sym_class &&
- (t = check_typedef (SYMBOL_TYPE (sym_class)),
- (TYPE_CODE (t) == TYPE_CODE_STRUCT
- || TYPE_CODE (t) == TYPE_CODE_UNION)))
+ sym_classes = lookup_prefix_sym (argptr, p2, self->file_symtabs,
+ &class_name);
+ make_cleanup (VEC_cleanup (symbolp), &sym_classes);
+ make_cleanup (xfree, class_name);
+
+ /* If a class has been found, then we're in case 1 above. So we
+ look up "fun" as a method of those classes. */
+ if (!VEC_empty (symbolp, sym_classes))
{
/* Arg token is not digits => try it as a function name.
Find the next token (everything up to end or next
@@ -1578,9 +1700,7 @@ decode_compound (char **argptr, int funfirstline,
/* At this point copy->"fun", p->"". */
/* No line number may be specified. */
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
+ *argptr = skip_spaces (p);
/* At this point arptr->"". */
/* Look for copy as a method of sym_class. */
@@ -1590,8 +1710,10 @@ decode_compound (char **argptr, int funfirstline,
here, we return. If not, and we are at the and of the string,
we'll lookup the whole string in the symbol tables. */
- return find_method (funfirstline, canonical, saved_arg, copy, t,
- sym_class, file_symtab);
+ values = find_method (self, saved_arg, copy, class_name, sym_classes);
+
+ do_cleanups (cleanup);
+ return values;
} /* End if symbol found. */
@@ -1611,7 +1733,6 @@ decode_compound (char **argptr, int funfirstline,
/* Look up entire name. */
name = copy;
- cleanup = make_cleanup (null_cleanup, NULL);
canon = cp_canonicalize_string_no_typedefs (copy);
if (canon != NULL)
{
@@ -1619,213 +1740,400 @@ decode_compound (char **argptr, int funfirstline,
make_cleanup (xfree, name);
}
- sym = lookup_symbol (name, get_selected_block (0), VAR_DOMAIN, 0);
- do_cleanups (cleanup);
- if (sym)
- return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL);
- else
- {
- struct minimal_symbol *msym;
+ return decode_variable (self, copy);
+}
- /* Couldn't find any interpretation as classes/namespaces. As a last
- resort, try the minimal symbol tables. */
- msym = lookup_minimal_symbol (copy, NULL, NULL);
- if (msym != NULL)
- return minsym_found (funfirstline, msym);
- }
+/* An instance of this type is used when collecting prefix symbols for
+ decode_compound. */
- /* Couldn't find a minimal symbol, either, so give up. */
- cplusplus_error (the_real_saved_arg,
- "Can't find member of namespace, "
- "class, struct, or union named \"%s\"\n",
- copy);
-}
+struct decode_compound_collector
+{
+ /* The result vector. */
+ VEC (symbolp) *symbols;
+
+ /* A hash table of all symbols we found. We use this to avoid
+ adding any symbol more than once. */
+ htab_t unique_syms;
+};
+
+/* A callback for iterate_over_symbols that is used by
+ lookup_prefix_sym to collect type symbols. */
+
+static int
+collect_one_symbol (struct symbol *sym, void *d)
+{
+ struct decode_compound_collector *collector = d;
+ void **slot;
+ struct type *t;
-/* Next come some helper functions for decode_compound. */
+ if (SYMBOL_CLASS (sym) != LOC_TYPEDEF)
+ return 1;
+
+ t = SYMBOL_TYPE (sym);
+ CHECK_TYPEDEF (t);
+ if (TYPE_CODE (t) != TYPE_CODE_STRUCT
+ && TYPE_CODE (t) != TYPE_CODE_UNION
+ && TYPE_CODE (t) != TYPE_CODE_NAMESPACE)
+ return 1;
+
+ slot = htab_find_slot (collector->unique_syms, sym, INSERT);
+ if (!*slot)
+ {
+ *slot = sym;
+ VEC_safe_push (symbolp, collector->symbols, sym);
+ }
+
+ return 1;
+}
/* Return the symbol corresponding to the substring of *ARGPTR ending
at P, allowing whitespace. Also, advance *ARGPTR past the symbol
name in question, the compound object separator ("::" or "."), and
whitespace. Note that *ARGPTR is changed whether or not the
- lookup_symbol call finds anything (i.e we return NULL). As an
+ this call finds anything (i.e we return NULL). As an
example, say ARGPTR is "AAA::inA::fun" and P is "::inA::fun". */
-static struct symbol *
-lookup_prefix_sym (char **argptr, char *p, struct symtab *file_symtab)
+static VEC (symbolp) *
+lookup_prefix_sym (char **argptr, char *p, VEC (symtab_p) *file_symtabs,
+ char **class_name)
{
char *p1;
char *copy;
- struct symbol *sym;
+ int ix;
+ struct symtab *elt;
+ struct decode_compound_collector collector;
+ struct cleanup *outer;
+ struct cleanup *cleanup;
+ struct block *search_block;
/* Extract the class name. */
p1 = p;
while (p != *argptr && p[-1] == ' ')
--p;
- copy = (char *) alloca (p - *argptr + 1);
+ copy = (char *) xmalloc (p - *argptr + 1);
memcpy (copy, *argptr, p - *argptr);
copy[p - *argptr] = 0;
+ *class_name = copy;
+ outer = make_cleanup (xfree, copy);
/* Discard the class name from the argptr. */
p = p1 + (p1[0] == ':' ? 2 : 1);
- while (*p == ' ' || *p == '\t')
- p++;
+ p = skip_spaces (p);
*argptr = p;
/* At this point p1->"::inA::fun", p->"inA::fun" copy->"AAA",
argptr->"inA::fun". */
- sym = lookup_symbol (copy, get_search_block (file_symtab), STRUCT_DOMAIN, 0);
- if (sym == NULL)
- {
- /* Typedefs are in VAR_DOMAIN so the above symbol lookup will
- fail when the user attempts to lookup a method of a class
- via a typedef'd name (NOT via the class's name, which is already
- handled in symbol_matches_domain). So try the lookup again
- using VAR_DOMAIN (where typedefs live) and double-check that we
- found a struct/class type. */
- struct symbol *s = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
+ collector.symbols = NULL;
+ make_cleanup (VEC_cleanup (symbolp), &collector.symbols);
- if (s != NULL)
- {
- struct type *t = SYMBOL_TYPE (s);
+ collector.unique_syms = htab_create_alloc (1, htab_hash_pointer,
+ htab_eq_pointer, NULL,
+ xcalloc, xfree);
+ cleanup = make_cleanup_htab_delete (collector.unique_syms);
- CHECK_TYPEDEF (t);
- if (TYPE_CODE (t) == TYPE_CODE_STRUCT)
- return s;
+ for (ix = 0; VEC_iterate (symtab_p, file_symtabs, ix, elt); ++ix)
+ {
+ if (elt == NULL)
+ {
+ iterate_over_all_matching_symtabs (copy, STRUCT_DOMAIN,
+ collect_one_symbol, &collector,
+ NULL);
+ iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
+ collect_one_symbol, &collector,
+ NULL);
+ }
+ else
+ {
+ struct block *search_block;
+
+ /* Program spaces that are executing startup should have
+ been filtered out earlier. */
+ gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
+ set_current_program_space (SYMTAB_PSPACE (elt));
+ search_block = get_search_block (elt);
+ iterate_over_symbols (search_block, copy, STRUCT_DOMAIN,
+ collect_one_symbol, &collector);
+ iterate_over_symbols (search_block, copy, VAR_DOMAIN,
+ collect_one_symbol, &collector);
}
}
- return sym;
+ do_cleanups (cleanup);
+ discard_cleanups (outer);
+ return collector.symbols;
}
-/* This finds the method COPY in the class whose type is T and whose
- symbol is SYM_CLASS. */
+/* A qsort comparison function for symbols. The resulting order does
+ not actually matter; we just need to be able to sort them so that
+ symbols with the same program space end up next to each other. */
-static struct symtabs_and_lines
-find_method (int funfirstline, struct linespec_result *canonical,
- char *saved_arg,
- char *copy, struct type *t, struct symbol *sym_class,
- struct symtab *file_symtab)
+static int
+compare_symbols (const void *a, const void *b)
{
- struct symtabs_and_lines values;
- struct symbol *sym = NULL;
- int i1; /* Counter for the symbol array. */
- struct symbol **sym_arr = alloca (total_number_of_methods (t)
- * sizeof (struct symbol *));
+ struct symbol * const *sa = a;
+ struct symbol * const *sb = b;
+ uintptr_t uia, uib;
+
+ uia = (uintptr_t) SYMTAB_PSPACE (SYMBOL_SYMTAB (*sa));
+ uib = (uintptr_t) SYMTAB_PSPACE (SYMBOL_SYMTAB (*sb));
- /* Find all methods with a matching name, and put them in
- sym_arr. */
+ if (uia < uib)
+ return -1;
+ if (uia > uib)
+ return 1;
- i1 = find_methods (t, copy, SYMBOL_LANGUAGE (sym_class), sym_arr,
- file_symtab);
+ uia = (uintptr_t) *sa;
+ uib = (uintptr_t) *sb;
- /* If we were given a specific overload instance in COPY, defer the field
- acceptance till the strcmp_iw verification below, even if we found just
- a single field with that name. */
- if (i1 == 1 && strchr (copy, '(') == NULL)
+ if (uia < uib)
+ return -1;
+ if (uia > uib)
+ return 1;
+
+ return 0;
+}
+
+/* Look for all the matching instances of each symbol in NAMES. Only
+ instances from PSPACE are considered; other program spaces are
+ handled by our caller. If PSPACE is NULL, then all program spaces
+ are considered. Results are stored into INFO. */
+
+static void
+add_all_symbol_names_from_pspace (struct collect_info *info,
+ struct program_space *pspace,
+ VEC (const_char_ptr) *names)
+{
+ int ix;
+ const char *iter;
+
+ for (ix = 0; VEC_iterate (const_char_ptr, names, ix, iter); ++ix)
+ add_matching_symbols_to_info (iter, info, pspace);
+}
+
+static void
+find_superclass_methods (VEC (typep) *superclasses,
+ const char *name,
+ VEC (const_char_ptr) **result_names)
+{
+ int old_len = VEC_length (const_char_ptr, *result_names);
+ VEC (typep) *iter_classes;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+
+ iter_classes = superclasses;
+ while (1)
{
- /* There is exactly one field with that name. */
- sym = sym_arr[0];
+ VEC (typep) *new_supers = NULL;
+ int ix;
+ struct type *t;
- if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
- {
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- values.sals[0] = find_function_start_sal (sym,
- funfirstline);
- }
- else
+ make_cleanup (VEC_cleanup (typep), &new_supers);
+ for (ix = 0; VEC_iterate (typep, iter_classes, ix, t); ++ix)
+ find_methods (t, name, result_names, &new_supers);
+
+ if (VEC_length (const_char_ptr, *result_names) != old_len
+ || VEC_empty (typep, new_supers))
+ break;
+
+ iter_classes = new_supers;
+ }
+
+ do_cleanups (cleanup);
+}
+
+/* This finds the method COPY in the class whose type is given by one
+ of the symbols in SYM_CLASSES. */
+
+static struct symtabs_and_lines
+find_method (struct linespec_state *self, char *saved_arg,
+ char *copy, const char *class_name, VEC (symbolp) *sym_classes)
+{
+ char *canon;
+ struct symbol *sym;
+ struct cleanup *cleanup = make_cleanup (null_cleanup, NULL);
+ int ix;
+ int last_result_len;
+ VEC (typep) *superclass_vec;
+ VEC (const_char_ptr) *result_names;
+ struct collect_info info;
+ char *name_iter;
+
+ /* NAME is typed by the user: it needs to be canonicalized before
+ searching the symbol tables. */
+ canon = cp_canonicalize_string_no_typedefs (copy);
+ if (canon != NULL)
+ {
+ copy = canon;
+ make_cleanup (xfree, copy);
+ }
+
+ /* Sort symbols so that symbols with the same program space are next
+ to each other. */
+ qsort (VEC_address (symbolp, sym_classes),
+ VEC_length (symbolp, sym_classes),
+ sizeof (symbolp),
+ compare_symbols);
+
+ info.state = self;
+ info.result.sals = NULL;
+ info.result.nelts = 0;
+ info.objfile = NULL;
+
+ /* Iterate over all the types, looking for the names of existing
+ methods matching COPY. If we cannot find a direct method in a
+ given program space, then we consider inherited methods; this is
+ not ideal (ideal would be to respect C++ hiding rules), but it
+ seems good enough and is what GDB has historically done. We only
+ need to collect the names because later we find all symbols with
+ those names. This loop is written in a somewhat funny way
+ because we collect data across the program space before deciding
+ what to do. */
+ superclass_vec = NULL;
+ make_cleanup (VEC_cleanup (typep), &superclass_vec);
+ result_names = NULL;
+ make_cleanup (VEC_cleanup (const_char_ptr), &result_names);
+ last_result_len = 0;
+ for (ix = 0; VEC_iterate (symbolp, sym_classes, ix, sym); ++ix)
+ {
+ struct type *t;
+ struct program_space *pspace;
+
+ /* Program spaces that are executing startup should have
+ been filtered out earlier. */
+ gdb_assert (!SYMTAB_PSPACE (SYMBOL_SYMTAB (sym))->executing_startup);
+ pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ set_current_program_space (pspace);
+ t = check_typedef (SYMBOL_TYPE (sym));
+ find_methods (t, copy, &result_names, &superclass_vec);
+
+ /* Handle all items from a single program space at once; and be
+ sure not to miss the last batch. */
+ if (ix == VEC_length (symbolp, sym_classes) - 1
+ || (pspace
+ != SYMTAB_PSPACE (SYMBOL_SYMTAB (VEC_index (symbolp, sym_classes,
+ ix + 1)))))
{
- values.sals = NULL;
- values.nelts = 0;
+ /* If we did not find a direct implementation anywhere in
+ this program space, consider superclasses. */
+ if (VEC_length (const_char_ptr, result_names) == last_result_len)
+ find_superclass_methods (superclass_vec, copy, &result_names);
+
+ /* We have a list of candidate symbol names, so now we
+ iterate over the symbol tables looking for all
+ matches in this pspace. */
+ add_all_symbol_names_from_pspace (&info, pspace, result_names);
+
+ VEC_truncate (typep, superclass_vec, 0);
+ last_result_len = VEC_length (const_char_ptr, result_names);
}
- return values;
}
- if (i1 > 0)
+
+ if (info.result.nelts > 0)
{
- /* If we were given a specific overload instance, use that
- (or error if no matches were found). Otherwise ask the user
- which one to use. */
- if (strchr (copy, '('))
+ if (self->canonical)
{
- int i;
- char *name;
- char *canon;
- struct cleanup *cleanup;
-
- /* Construct the proper search name based on SYM_CLASS and COPY.
- SAVED_ARG may contain a valid name, but that name might not be
- what is actually stored in the symbol table. For example,
- if SAVED_ARG (and SYM_CLASS) were found via an import
- ("using namespace" in C++), then the physname of
- SYM_CLASS ("A::myclass") may not be the same as SAVED_ARG
- ("myclass"). */
- name = xmalloc (strlen (SYMBOL_NATURAL_NAME (sym_class))
- + 2 /* "::" */ + strlen (copy) + 1);
- strcpy (name, SYMBOL_NATURAL_NAME (sym_class));
- strcat (name, "::");
- strcat (name, copy);
- canon = cp_canonicalize_string_no_typedefs (name);
- if (canon != NULL)
- {
- xfree (name);
- name = canon;
- }
- cleanup = make_cleanup (xfree, name);
-
- for (i = 0; i < i1; ++i)
- {
- if (strcmp_iw (name, SYMBOL_LINKAGE_NAME (sym_arr[i])) == 0)
- {
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- values.sals[0] = find_function_start_sal (sym_arr[i],
- funfirstline);
- do_cleanups (cleanup);
- return values;
- }
- }
-
- cplusplus_error (saved_arg, _("the class `%s' does not have "
- "any method instance named %s"),
- SYMBOL_PRINT_NAME (sym_class), copy);
+ self->canonical->pre_expanded = 1;
+ if (self->user_filename)
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", self->user_filename, saved_arg);
+ else
+ self->canonical->addr_string = xstrdup (saved_arg);
}
- return decode_line_2 (sym_arr, i1, funfirstline, canonical);
+ do_cleanups (cleanup);
+
+ return info.result;
}
+
+ if (copy[0] == '~')
+ cplusplus_error (saved_arg,
+ "the class `%s' does not have destructor defined\n",
+ class_name);
else
+ cplusplus_error (saved_arg,
+ "the class %s does not have any method named %s\n",
+ class_name, copy);
+}
+
+\f
+
+/* This object is used when collecting all matching symtabs. */
+
+struct symtab_collector
+{
+ /* The result vector of symtabs. */
+ VEC (symtab_p) *symtabs;
+
+ /* This is used to ensure the symtabs are unique. */
+ htab_t symtab_table;
+};
+
+/* Callback for iterate_over_symtabs. */
+
+static int
+add_symtabs_to_list (struct symtab *symtab, void *d)
+{
+ struct symtab_collector *data = d;
+ void **slot;
+
+ slot = htab_find_slot (data->symtab_table, symtab, INSERT);
+ if (!*slot)
{
- if (copy[0] == '~')
- cplusplus_error (saved_arg,
- "the class `%s' does not have destructor defined\n",
- SYMBOL_PRINT_NAME (sym_class));
- else
- cplusplus_error (saved_arg,
- "the class %s does not have any method named %s\n",
- SYMBOL_PRINT_NAME (sym_class), copy);
+ *slot = symtab;
+ VEC_safe_push (symtab_p, data->symtabs, symtab);
}
+
+ return 0;
}
-\f
+/* Given a file name, return a VEC of all matching symtabs. */
-/* Return the symtab associated to the filename given by the substring
- of *ARGPTR ending at P, and advance ARGPTR past that filename. */
+static VEC (symtab_p) *
+collect_symtabs_from_filename (const char *file)
+{
+ struct symtab_collector collector;
+ struct cleanup *cleanups;
+ struct program_space *pspace;
+
+ collector.symtabs = NULL;
+ collector.symtab_table = htab_create (1, htab_hash_pointer, htab_eq_pointer,
+ NULL);
+ cleanups = make_cleanup_htab_delete (collector.symtab_table);
+
+ /* Find that file's data. */
+ ALL_PSPACES (pspace)
+ {
+ if (pspace->executing_startup)
+ continue;
+
+ set_current_program_space (pspace);
+ iterate_over_symtabs (file, add_symtabs_to_list, &collector);
+ }
-static struct symtab *
-symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
+ do_cleanups (cleanups);
+ return collector.symtabs;
+}
+
+/* Return all the symtabs associated to the filename given by the
+ substring of *ARGPTR ending at P, and advance ARGPTR past that
+ filename. */
+
+static VEC (symtab_p) *
+symtabs_from_filename (char **argptr, char *p, int is_quote_enclosed,
+ char **user_filename)
{
char *p1;
char *copy;
- struct symtab *file_symtab;
+ struct cleanup *outer;
+ VEC (symtab_p) *result;
p1 = p;
while (p != *argptr && p[-1] == ' ')
--p;
if ((*p == '"') && is_quote_enclosed)
--p;
- copy = (char *) alloca (p - *argptr + 1);
+ copy = xmalloc (p - *argptr + 1);
+ outer = make_cleanup (xfree, copy);
memcpy (copy, *argptr, p - *argptr);
/* It may have the ending quote right after the file name. */
if ((is_quote_enclosed && copy[p - *argptr - 1] == '"')
@@ -1834,9 +2142,9 @@ symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
else
copy[p - *argptr] = 0;
- /* Find that file's data. */
- file_symtab = lookup_symtab (copy);
- if (file_symtab == 0)
+ result = collect_symtabs_from_filename (copy);
+
+ if (VEC_empty (symtab_p, result))
{
if (!have_full_symbols () && !have_partial_symbols ())
throw_error (NOT_FOUND_ERROR,
@@ -1847,31 +2155,47 @@ symtab_from_filename (char **argptr, char *p, int is_quote_enclosed)
/* Discard the file name from the arg. */
if (*p1 == '\0')
- return file_symtab;
- p = p1 + 1;
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
+ *argptr = p1;
+ else
+ *argptr = skip_spaces (p1 + 1);
+
+ discard_cleanups (outer);
+ *user_filename = copy;
+ return result;
+}
+
+/* A callback used by iterate_over_all_matching_symtabs that collects
+ symbols for find_function_symbols. */
+
+static int
+collect_function_symbols (struct symbol *sym, void *arg)
+{
+ VEC (symbolp) **syms = arg;
+
+ if (SYMBOL_CLASS (sym) == LOC_BLOCK)
+ VEC_safe_push (symbolp, *syms, sym);
- return file_symtab;
+ return 1;
}
/* Look up a function symbol in *ARGPTR. If found, advance *ARGPTR
and return the symbol. If not found, return NULL. */
-static struct symbol *
-find_function_symbol (char **argptr, char *p, int is_quote_enclosed)
+static VEC (symbolp) *
+find_function_symbols (char **argptr, char *p, int is_quote_enclosed,
+ char **user_function)
{
char *p1;
char *copy;
- struct symbol *function_symbol;
+ VEC (symbolp) *result = NULL;
p1 = p;
while (p != *argptr && p[-1] == ' ')
--p;
if ((*p == '"') && is_quote_enclosed)
--p;
- copy = (char *) alloca (p - *argptr + 1);
+ copy = (char *) xmalloc (p - *argptr + 1);
+ *user_function = copy;
memcpy (copy, *argptr, p - *argptr);
/* It may have the ending quote right after the file name. */
if ((is_quote_enclosed && copy[p - *argptr - 1] == '"')
@@ -1880,34 +2204,128 @@ find_function_symbol (char **argptr, char *p, int is_quote_enclosed)
else
copy[p - *argptr] = 0;
- function_symbol = lookup_symbol (copy, get_selected_block (0),
- VAR_DOMAIN, 0);
- if (!function_symbol || SYMBOL_CLASS (function_symbol) != LOC_BLOCK)
- return NULL;
+ iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
+ collect_function_symbols, &result, NULL);
- /* Discard the file name from the arg. */
- p = p1 + 1;
- while (*p == ' ' || *p == '\t')
- p++;
- *argptr = p;
+ /* If looking up the given name failed, try using the current
+ language to look up a symbol. This may augment the search. If a
+ symbol is found this way, repeat the iteration, but using the
+ discovered name. */
+ if (VEC_empty (symbolp, result)
+ && current_language->la_language == language_ada)
+ {
+ struct symbol *function_symbol;
+
+ function_symbol = lookup_symbol (copy, get_selected_block (0),
+ VAR_DOMAIN, 0);
+ if (function_symbol && SYMBOL_CLASS (function_symbol) == LOC_BLOCK)
+ {
+ xfree (copy);
+ copy = xstrdup (SYMBOL_SEARCH_NAME (function_symbol));
+ *user_function = copy;
+ iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
+ collect_function_symbols,
+ &result, NULL);
+ }
+ }
+
+ if (VEC_empty (symbolp, result))
+ VEC_free (symbolp, result);
+ else
+ {
+ /* Discard the file name from the arg. */
+ *argptr = skip_spaces (p1 + 1);
+ }
- return function_symbol;
+ return result;
}
\f
+/* A helper for decode_all_digits that handles the 'list_mode' case. */
+
+static void
+decode_digits_list_mode (struct linespec_state *self,
+ struct symtabs_and_lines *values,
+ struct symtab_and_line val)
+{
+ int ix;
+ struct symtab *elt;
+
+ gdb_assert (self->list_mode);
+
+ for (ix = 0; VEC_iterate (symtab_p, self->file_symtabs, ix, elt); ++ix)
+ {
+ /* The logic above should ensure this. */
+ gdb_assert (elt != NULL);
+
+ set_current_program_space (SYMTAB_PSPACE (elt));
+
+ /* Simplistic search just for the list command. */
+ val.symtab = find_line_symtab (elt, val.line, NULL, NULL);
+ if (val.symtab == NULL)
+ val.symtab = elt;
+ val.pspace = SYMTAB_PSPACE (elt);
+ val.pc = 0;
+ val.explicit_line = 1;
+
+ add_sal_to_sals (self, values, &val, NULL);
+ }
+}
+
+/* A helper for decode_all_digits that iterates over the symtabs,
+ adding lines to the VEC. */
+
+static void
+decode_digits_ordinary (struct linespec_state *self,
+ int line,
+ struct symtabs_and_lines *sals,
+ struct linetable_entry **best_entry)
+{
+ int ix;
+ struct symtab *elt;
+
+ for (ix = 0; VEC_iterate (symtab_p, self->file_symtabs, ix, elt); ++ix)
+ {
+ int i;
+ VEC (CORE_ADDR) *pcs;
+ CORE_ADDR pc;
+
+ /* The logic above should ensure this. */
+ gdb_assert (elt != NULL);
+
+ set_current_program_space (SYMTAB_PSPACE (elt));
+
+ pcs = find_pcs_for_symtab_line (elt, line, best_entry);
+ for (i = 0; VEC_iterate (CORE_ADDR, pcs, i, pc); ++i)
+ {
+ struct symtab_and_line sal;
+
+ init_sal (&sal);
+ sal.pspace = SYMTAB_PSPACE (elt);
+ sal.symtab = elt;
+ sal.line = line;
+ sal.pc = pc;
+ add_sal_to_sals_basic (sals, &sal);
+ }
+
+ VEC_free (CORE_ADDR, pcs);
+ }
+}
+
/* This decodes a line where the argument is all digits (possibly
preceded by a sign). Q should point to the end of those digits;
the other arguments are as usual. */
static struct symtabs_and_lines
-decode_all_digits (char **argptr, struct symtab *default_symtab,
- int default_line, struct linespec_result *canonical,
- struct symtab *file_symtab, char *q)
-
+decode_all_digits (struct linespec_state *self,
+ char **argptr,
+ char *q)
{
struct symtabs_and_lines values;
struct symtab_and_line val;
+ int use_default = 0;
+ char *saved_arg = *argptr;
enum sign
{
@@ -1915,12 +2333,9 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
}
sign = none;
- /* We might need a canonical line spec if no file was specified. */
- int need_canonical = (file_symtab == NULL) ? 1 : 0;
-
init_sal (&val);
-
- val.pspace = current_program_space;
+ values.sals = NULL;
+ values.nelts = 0;
/* This is where we need to make sure that we have good defaults.
We must guarantee that this section of code is never executed
@@ -1928,11 +2343,19 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
set_default_source_symtab_and_line uses
select_source_symtab that calls us with such an argument. */
- if (file_symtab == 0 && default_symtab == 0)
+ if (VEC_length (symtab_p, self->file_symtabs) == 1
+ && VEC_index (symtab_p, self->file_symtabs, 0) == NULL)
{
+ set_current_program_space (self->program_space);
+
/* Make sure we have at least a default source file. */
set_default_source_symtab_and_line ();
- initialize_defaults (&default_symtab, &default_line);
+ initialize_defaults (&self->default_symtab, &self->default_line);
+ VEC_pop (symtab_p, self->file_symtabs);
+ VEC_free (symtab_p, self->file_symtabs);
+ self->file_symtabs
+ = collect_symtabs_from_filename (self->default_symtab->filename);
+ use_default = 1;
}
if (**argptr == '+')
@@ -1945,14 +2368,14 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
case plus:
if (q == *argptr)
val.line = 5;
- if (file_symtab == 0)
- val.line = default_line + val.line;
+ if (use_default)
+ val.line = self->default_line + val.line;
break;
case minus:
if (q == *argptr)
val.line = 15;
- if (file_symtab == 0)
- val.line = default_line - val.line;
+ if (use_default)
+ val.line = self->default_line - val.line;
else
val.line = 1;
break;
@@ -1960,28 +2383,110 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
break; /* No need to adjust val.line. */
}
- while (*q == ' ' || *q == '\t')
- q++;
- *argptr = q;
- if (file_symtab == 0)
- file_symtab = default_symtab;
-
- /* It is possible that this source file has more than one symtab,
- and that the new line number specification has moved us from the
- default (in file_symtab) to a new one. */
- val.symtab = find_line_symtab (file_symtab, val.line, NULL, NULL);
- if (val.symtab == 0)
- val.symtab = file_symtab;
-
- val.pspace = SYMTAB_PSPACE (val.symtab);
- val.pc = 0;
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = val;
- values.nelts = 1;
- if (need_canonical)
- build_canonical_line_spec (values.sals, NULL, canonical);
- values.sals[0].explicit_line = 1;
+ *argptr = skip_spaces (q);
+
+ if (self->list_mode)
+ decode_digits_list_mode (self, &values, val);
+ else
+ {
+ struct linetable_entry *best_entry = NULL;
+ int *filter;
+ struct block **blocks;
+ struct cleanup *cleanup;
+ struct symtabs_and_lines intermediate_results;
+ int i, j;
+
+ intermediate_results.sals = NULL;
+ intermediate_results.nelts = 0;
+
+ decode_digits_ordinary (self, val.line, &intermediate_results,
+ &best_entry);
+ if (intermediate_results.nelts == 0 && best_entry != NULL)
+ decode_digits_ordinary (self, best_entry->line, &intermediate_results,
+ &best_entry);
+
+ cleanup = make_cleanup (xfree, intermediate_results.sals);
+
+ /* For optimized code, compiler can scatter one source line
+ accross disjoint ranges of PC values, even when no duplicate
+ functions or inline functions are involved. For example,
+ 'for (;;)' inside non-template non-inline non-ctor-or-dtor
+ function can result in two PC ranges. In this case, we don't
+ want to set breakpoint on first PC of each range. To filter
+ such cases, we use containing blocks -- for each PC found
+ above we see if there are other PCs that are in the same
+ block. If yes, the other PCs are filtered out. */
+
+ filter = xmalloc (intermediate_results.nelts * sizeof (int));
+ make_cleanup (xfree, filter);
+ blocks = xmalloc (intermediate_results.nelts * sizeof (struct block *));
+ make_cleanup (xfree, blocks);
+
+ for (i = 0; i < intermediate_results.nelts; ++i)
+ {
+ set_current_program_space (intermediate_results.sals[i].pspace);
+
+ filter[i] = 1;
+ blocks[i] = block_for_pc_sect (intermediate_results.sals[i].pc,
+ intermediate_results.sals[i].section);
+ }
+
+ for (i = 0; i < intermediate_results.nelts; ++i)
+ {
+ if (blocks[i] != NULL)
+ for (j = i + 1; j < intermediate_results.nelts; ++j)
+ {
+ if (blocks[j] == blocks[i])
+ {
+ filter[j] = 0;
+ break;
+ }
+ }
+ }
+
+ for (i = 0; i < intermediate_results.nelts; ++i)
+ if (filter[i])
+ {
+ struct symbol *sym = (blocks[i]
+ ? block_containing_function (blocks[i])
+ : NULL);
+
+ if (self->funfirstline)
+ skip_prologue_sal (&intermediate_results.sals[i]);
+ /* Make sure the line matches the request, not what was
+ found. */
+ intermediate_results.sals[i].line = val.line;
+ add_sal_to_sals (self, &values, &intermediate_results.sals[i],
+ sym ? SYMBOL_NATURAL_NAME (sym) : NULL);
+ }
+
+ do_cleanups (cleanup);
+ }
+
+ if (values.nelts == 0)
+ {
+ if (self->user_filename)
+ throw_error (NOT_FOUND_ERROR, _("No line %d in file \"%s\"."),
+ val.line, self->user_filename);
+ else
+ throw_error (NOT_FOUND_ERROR, _("No line %d in the current file."),
+ val.line);
+ }
+
+ if (self->canonical)
+ {
+ char *copy = savestring (saved_arg, q - saved_arg);
+
+ self->canonical->pre_expanded = 1;
+ gdb_assert (self->user_filename || use_default);
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", (self->user_filename
+ ? self->user_filename
+ : self->default_symtab->filename),
+ copy);
+ xfree (copy);
+ }
+
return values;
}
@@ -1990,17 +2495,17 @@ decode_all_digits (char **argptr, struct symtab *default_symtab,
/* Decode a linespec starting with a dollar sign. */
static struct symtabs_and_lines
-decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
- struct linespec_result *canonical, struct symtab *file_symtab)
+decode_dollar (struct linespec_state *self, char *copy)
{
LONGEST valx;
int index = 0;
- int need_canonical = 0;
struct symtabs_and_lines values;
struct symtab_and_line val;
char *p;
struct symbol *sym;
struct minimal_symbol *msymbol;
+ int ix;
+ struct symtab *elt;
p = (copy[1] == '$') ? copy + 2 : copy + 1;
while (*p >= '0' && *p <= '9')
@@ -2022,19 +2527,18 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
/* Not all digits -- may be user variable/function or a
convenience variable. */
- /* Look up entire name as a symbol first. */
- sym = lookup_symbol (copy, 0, VAR_DOMAIN, 0);
- file_symtab = (struct symtab *) NULL;
- need_canonical = 1;
- /* Symbol was found --> jump to normal symbol processing. */
- if (sym)
- return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL);
+ volatile struct gdb_exception exc;
+
+ TRY_CATCH (exc, RETURN_MASK_ERROR)
+ {
+ values = decode_variable (self, copy);
+ }
- /* If symbol was not found, look in minimal symbol tables. */
- msymbol = lookup_minimal_symbol (copy, NULL, NULL);
- /* Min symbol was found --> jump to minsym processing. */
- if (msymbol)
- return minsym_found (funfirstline, msymbol);
+ if (exc.reason == 0)
+ return values;
+
+ if (exc.error != NOT_FOUND_ERROR)
+ throw_exception (exc);
/* Not a user variable or function -- must be convenience variable. */
if (!get_internalvar_integer (lookup_internalvar (copy + 1), &valx))
@@ -2044,18 +2548,37 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
init_sal (&val);
- /* Either history value or convenience value from above, in valx. */
- val.symtab = file_symtab ? file_symtab : default_symtab;
- val.line = valx;
- val.pc = 0;
- val.pspace = current_program_space;
+ values.sals = NULL;
+ values.nelts = 0;
- values.sals = (struct symtab_and_line *) xmalloc (sizeof val);
- values.sals[0] = val;
- values.nelts = 1;
+ for (ix = 0; VEC_iterate (symtab_p, self->file_symtabs, ix, elt); ++ix)
+ {
+ if (elt == NULL)
+ {
+ elt = self->default_symtab;
+ set_current_program_space (self->program_space);
+ }
+ else
+ set_current_program_space (SYMTAB_PSPACE (elt));
- if (need_canonical)
- build_canonical_line_spec (values.sals, NULL, canonical);
+ /* Either history value or convenience value from above, in valx. */
+ val.symtab = elt;
+ val.line = valx;
+ val.pc = 0;
+ val.pspace = elt ? SYMTAB_PSPACE (elt) : current_program_space;
+
+ add_sal_to_sals (self, &values, &val, NULL);
+ }
+
+ if (self->canonical)
+ {
+ self->canonical->pre_expanded = 1;
+ if (self->user_filename)
+ self->canonical->addr_string = xstrprintf ("%s:%s",
+ self->user_filename, copy);
+ else
+ self->canonical->addr_string = xstrdup (copy);
+ }
return values;
}
@@ -2064,7 +2587,7 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
/* A helper for decode_line_1 that tries to find a label. The label
is searched for in the current block.
- FUNCTION_SYMBOL is the enclosing function; or NULL if none
+ FUNCTION_SYMBOLS is a list of the enclosing functions; or NULL if none
specified.
COPY is the name of the label to find.
CANONICAL is the same as the "canonical" argument to decode_line_1.
@@ -2073,78 +2596,308 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
This function returns 1 if a label was found, 0 otherwise. */
static int
-decode_label (struct symbol *function_symbol, char *copy,
- struct linespec_result *canonical,
+decode_label (struct linespec_state *self,
+ VEC (symbolp) *function_symbols, char *copy,
struct symtabs_and_lines *result)
{
- struct symbol *sym;
- struct block *block;
+ struct symbol *fn_sym;
+ int ix;
- if (function_symbol)
- block = SYMBOL_BLOCK_VALUE (function_symbol);
- else
+ if (function_symbols == NULL)
{
- block = get_selected_block (0);
+ struct block *block;
+ struct symbol *sym;
+ struct symtab_and_line sal;
+ struct symtabs_and_lines values;
+
+ values.nelts = 0;
+ values.sals = NULL;
+
+ set_current_program_space (self->program_space);
+ block = get_search_block (NULL);
+
for (;
block && !BLOCK_FUNCTION (block);
block = BLOCK_SUPERBLOCK (block))
;
if (!block)
return 0;
- function_symbol = BLOCK_FUNCTION (block);
+ fn_sym = BLOCK_FUNCTION (block);
+
+ sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0);
+
+ if (sym == NULL)
+ return 0;
+
+ symbol_to_sal (&sal, self->funfirstline, sym);
+ add_sal_to_sals (self, &values, &sal,
+ SYMBOL_NATURAL_NAME (fn_sym));
+
+ if (self->canonical)
+ {
+ self->canonical->special_display = 1;
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", SYMBOL_NATURAL_NAME (fn_sym),
+ copy);
+ }
+
+ *result = values;
+
+ return 1;
+ }
+
+ result->sals = NULL;
+ result->nelts = 0;
+
+ for (ix = 0; VEC_iterate (symbolp, function_symbols, ix, fn_sym); ++ix)
+ {
+ struct block *block;
+ struct symbol *sym;
+
+ set_current_program_space (SYMTAB_PSPACE (SYMBOL_SYMTAB (fn_sym)));
+ block = SYMBOL_BLOCK_VALUE (fn_sym);
+ sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0);
+
+ if (sym != NULL)
+ {
+ struct symtab_and_line sal;
+ char *symname;
+
+ symbol_to_sal (&sal, self->funfirstline, sym);
+ symname = xstrprintf ("%s:%s",
+ SYMBOL_NATURAL_NAME (fn_sym),
+ SYMBOL_NATURAL_NAME (sym));
+ add_sal_to_sals (self, result, &sal, symname);
+ xfree (symname);
+ }
+ }
+
+ if (self->canonical && result->nelts > 0)
+ {
+ self->canonical->pre_expanded = 1;
+ self->canonical->special_display = 1;
+
+ gdb_assert (self->user_function);
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", self->user_function, copy);
+ }
+
+ return result->nelts > 0;
+}
+
+/* A callback used to possibly add a symbol to the results. */
+
+static int
+collect_symbols (struct symbol *sym, void *data)
+{
+ struct collect_info *info = data;
+ struct symtab_and_line sal;
+
+ if ((SYMBOL_CLASS (sym) == LOC_STATIC
+ && !info->state->funfirstline
+ && !maybe_add_address (info->state->addr_set,
+ SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)),
+ SYMBOL_VALUE_ADDRESS (sym)))
+ || (SYMBOL_CLASS (sym) == LOC_BLOCK
+ && !maybe_add_address (info->state->addr_set,
+ SYMTAB_PSPACE (SYMBOL_SYMTAB (sym)),
+ BLOCK_START (SYMBOL_BLOCK_VALUE (sym)))))
+ {
+ /* Nothing. */
+ }
+ else if (symbol_to_sal (&sal, info->state->funfirstline, sym))
+ add_sal_to_sals (info->state, &info->result, &sal,
+ SYMBOL_NATURAL_NAME (sym));
+
+ return 1;
+}
+
+/* We've found a minimal symbol MSYMBOL to associate with our
+ linespec; add it to the result symtabs_and_lines. */
+
+static void
+minsym_found (struct linespec_state *self, struct objfile *objfile,
+ struct minimal_symbol *msymbol,
+ struct symtabs_and_lines *result)
+{
+ struct gdbarch *gdbarch = get_objfile_arch (objfile);
+ CORE_ADDR pc;
+ struct symtab_and_line sal;
+
+ sal = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
+ (struct obj_section *) 0, 0);
+ sal.section = SYMBOL_OBJ_SECTION (msymbol);
+
+ /* The minimal symbol might point to a function descriptor;
+ resolve it to the actual code address instead. */
+ pc = gdbarch_convert_from_func_ptr_addr (gdbarch, sal.pc, ¤t_target);
+ if (pc != sal.pc)
+ sal = find_pc_sect_line (pc, NULL, 0);
+
+ if (self->funfirstline)
+ skip_prologue_sal (&sal);
+
+ add_sal_to_sals (self, result, &sal, SYMBOL_NATURAL_NAME (msymbol));
+}
+
+/* Callback for iterate_over_minimal_symbols that may add the symbol
+ to the result. */
+
+static void
+check_minsym (struct minimal_symbol *minsym, void *d)
+{
+ struct collect_info *info = d;
+
+ if (MSYMBOL_TYPE (minsym) == mst_unknown
+ || MSYMBOL_TYPE (minsym) == mst_slot_got_plt
+ || MSYMBOL_TYPE (minsym) == mst_solib_trampoline)
+ {
+ /* Reject some odd ones. */
+ }
+ else if (info->state->funfirstline
+ && MSYMBOL_TYPE (minsym) != mst_text
+ && MSYMBOL_TYPE (minsym) != mst_text_gnu_ifunc
+ && MSYMBOL_TYPE (minsym) != mst_file_text)
+ {
+ /* When FUNFIRSTLINE, only allow text symbols. */
+ }
+ else if (maybe_add_address (info->state->addr_set, info->objfile->pspace,
+ SYMBOL_VALUE_ADDRESS (minsym)))
+ minsym_found (info->state, info->objfile, minsym, &info->result);
+}
+
+/* Search minimal symbols in all objfiles for NAME. If SEARCH_PSPACE
+ is not NULL, the search is restricted to just that program
+ space. */
+
+static void
+search_minsyms_for_name (struct collect_info *info, const char *name,
+ struct program_space *search_pspace)
+{
+ struct objfile *objfile;
+ struct program_space *pspace;
+
+ ALL_PSPACES (pspace)
+ {
+ if (search_pspace != NULL && search_pspace != pspace)
+ continue;
+ if (pspace->executing_startup)
+ continue;
+
+ set_current_program_space (pspace);
+
+ ALL_OBJFILES (objfile)
+ {
+ info->objfile = objfile;
+ iterate_over_minimal_symbols (objfile, name, check_minsym, info);
}
+ }
+}
- sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0);
+/* A helper function to add all symbols matching NAME to INFO. If
+ PSPACE is not NULL, the search is restricted to just that program
+ space. */
- if (sym != NULL)
- *result = symbol_found (0, canonical, copy, sym, NULL, function_symbol);
+static void
+add_matching_symbols_to_info (const char *name,
+ struct collect_info *info,
+ struct program_space *pspace)
+{
+ int ix;
+ struct symtab *elt;
- return sym != NULL;
+ for (ix = 0; VEC_iterate (symtab_p, info->state->file_symtabs, ix, elt); ++ix)
+ {
+ struct symbol *sym;
+
+ if (elt == NULL)
+ {
+ iterate_over_all_matching_symtabs (name, VAR_DOMAIN,
+ collect_symbols, info,
+ pspace);
+ search_minsyms_for_name (info, name, pspace);
+ }
+ else if (pspace == NULL || pspace == SYMTAB_PSPACE (elt))
+ {
+ /* Program spaces that are executing startup should have
+ been filtered out earlier. */
+ gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
+ set_current_program_space (SYMTAB_PSPACE (elt));
+ iterate_over_symbols (get_search_block (elt), name,
+ VAR_DOMAIN, collect_symbols,
+ info);
+ }
+ }
}
/* Decode a linespec that's a variable. If FILE_SYMTAB is non-NULL,
look in that symtab's static variables first. */
static struct symtabs_and_lines
-decode_variable (char *copy, int funfirstline,
- struct linespec_result *canonical,
- struct symtab *file_symtab)
+decode_variable (struct linespec_state *self, char *copy)
{
- char *name, *canon;
- struct symbol *sym;
+ struct collect_info info;
+ const char *lookup_name;
+ char *canon;
struct cleanup *cleanup;
- struct minimal_symbol *msymbol;
- name = copy;
- cleanup = make_cleanup (null_cleanup, NULL);
+ info.state = self;
+ info.result.sals = NULL;
+ info.result.nelts = 0;
+ info.objfile = NULL;
+
+ cleanup = demangle_for_lookup (copy, current_language->la_language,
+ &lookup_name);
+
canon = cp_canonicalize_string_no_typedefs (copy);
if (canon != NULL)
{
- name = canon;
- make_cleanup (xfree, name);
+ make_cleanup (xfree, canon);
+ lookup_name = canon;
}
- sym = lookup_symbol (name, get_search_block (file_symtab), VAR_DOMAIN, 0);
+ add_matching_symbols_to_info (lookup_name, &info, NULL);
- if (sym != NULL)
+ /* If looking up the given name failed, try using the current
+ language to look up a symbol. This may augment the search. If a
+ symbol is found this way, repeat the iteration, but using the
+ discovered name. */
+ if (info.result.nelts == 0 && current_language->la_language == language_ada)
{
- do_cleanups (cleanup);
- return symbol_found (funfirstline, canonical, copy, sym,
- file_symtab, NULL);
- }
+ struct symbol *sym;
- msymbol = lookup_minimal_symbol (name, NULL, NULL);
- do_cleanups (cleanup);
+ sym = lookup_symbol (lookup_name, get_selected_block (0), VAR_DOMAIN, 0);
+ if (sym)
+ {
+ copy = SYMBOL_SEARCH_NAME (sym);
+ add_matching_symbols_to_info (copy, &info, NULL);
+ }
+ }
- if (msymbol != NULL)
- return minsym_found (funfirstline, msymbol);
+ if (info.result.nelts > 0)
+ {
+ if (self->canonical)
+ {
+ self->canonical->pre_expanded = 1;
+ if (self->user_filename)
+ self->canonical->addr_string
+ = xstrprintf ("%s:%s", self->user_filename, copy);
+ else
+ self->canonical->addr_string = xstrdup (copy);
+ }
+ return info.result;
+ }
if (!have_full_symbols ()
&& !have_partial_symbols ()
&& !have_minimal_symbols ())
throw_error (NOT_FOUND_ERROR,
_("No symbol table is loaded. Use the \"file\" command."));
- throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy);
+ if (self->user_filename)
+ throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined in \"%s\"."),
+ copy, self->user_filename);
+ else
+ throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy);
}
@@ -2153,130 +2906,82 @@ decode_variable (char *copy, int funfirstline,
/* Now come some functions that are called from multiple places within
decode_line_1. */
-/* We've found a symbol SYM to associate with our linespec; build a
- corresponding struct symtabs_and_lines. */
-
-static struct symtabs_and_lines
-symbol_found (int funfirstline, struct linespec_result *canonical, char *copy,
- struct symbol *sym, struct symtab *file_symtab,
- struct symbol *function_symbol)
+static int
+symbol_to_sal (struct symtab_and_line *result,
+ int funfirstline, struct symbol *sym)
{
- struct symtabs_and_lines values;
-
if (SYMBOL_CLASS (sym) == LOC_BLOCK)
{
- /* Arg is the name of a function. */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = find_function_start_sal (sym, funfirstline);
- values.nelts = 1;
-
- /* Don't use the SYMBOL_LINE; if used at all it points to
- the line containing the parameters or thereabouts, not
- the first line of code. */
-
- /* We might need a canonical line spec if it is a static
- function. */
- if (file_symtab == 0)
- {
- struct blockvector *bv = BLOCKVECTOR (SYMBOL_SYMTAB (sym));
- struct block *b = BLOCKVECTOR_BLOCK (bv, STATIC_BLOCK);
-
- if (lookup_block_symbol (b, copy, VAR_DOMAIN) != NULL)
- build_canonical_line_spec (values.sals, copy, canonical);
- }
- return values;
+ *result = find_function_start_sal (sym, funfirstline);
+ return 1;
}
else
{
if (SYMBOL_CLASS (sym) == LOC_LABEL && SYMBOL_VALUE_ADDRESS (sym) != 0)
{
- /* We know its line number. */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- init_sal (&values.sals[0]);
- values.sals[0].symtab = SYMBOL_SYMTAB (sym);
- values.sals[0].line = SYMBOL_LINE (sym);
- values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym);
- values.sals[0].pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
- values.sals[0].explicit_pc = 1;
-
- if (canonical)
- {
- canonical->special_display = 1;
- canonical->canonical = xmalloc (sizeof (char *));
- canonical->canonical[0]
- = xstrprintf ("%s:%s",
- SYMBOL_NATURAL_NAME (function_symbol),
- SYMBOL_NATURAL_NAME (sym));
- }
-
- return values;
+ init_sal (result);
+ result->symtab = SYMBOL_SYMTAB (sym);
+ result->line = SYMBOL_LINE (sym);
+ result->pc = SYMBOL_VALUE_ADDRESS (sym);
+ result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ result->explicit_pc = 1;
+ return 1;
}
else if (funfirstline)
{
- /* NOT_FOUND_ERROR is not correct but it ensures COPY will be
- searched also as a minimal symbol. */
-
- throw_error (NOT_FOUND_ERROR, _("\"%s\" is not a function"), copy);
+ /* Nothing. */
}
else if (SYMBOL_LINE (sym) != 0)
{
/* We know its line number. */
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.nelts = 1;
- memset (&values.sals[0], 0, sizeof (values.sals[0]));
- values.sals[0].symtab = SYMBOL_SYMTAB (sym);
- values.sals[0].line = SYMBOL_LINE (sym);
- values.sals[0].pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
- return values;
+ init_sal (result);
+ result->symtab = SYMBOL_SYMTAB (sym);
+ result->line = SYMBOL_LINE (sym);
+ result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+ return 1;
}
- else
- /* This can happen if it is compiled with a compiler which doesn't
- put out line numbers for variables. */
- /* FIXME: Shouldn't we just set .line and .symtab to zero
- and return? For example, "info line foo" could print
- the address. */
- error (_("Line number not known for symbol \"%s\""), copy);
}
+
+ return 0;
}
-/* We've found a minimal symbol MSYMBOL to associate with our
- linespec; build a corresponding struct symtabs_and_lines. */
+/* See the comment in linespec.h. */
-static struct symtabs_and_lines
-minsym_found (int funfirstline, struct minimal_symbol *msymbol)
+void
+init_linespec_result (struct linespec_result *lr)
{
- struct objfile *objfile = msymbol_objfile (msymbol);
- struct gdbarch *gdbarch = get_objfile_arch (objfile);
- struct symtabs_and_lines values;
- CORE_ADDR pc;
+ memset (lr, 0, sizeof (*lr));
+}
- values.sals = (struct symtab_and_line *)
- xmalloc (sizeof (struct symtab_and_line));
- values.sals[0] = find_pc_sect_line (SYMBOL_VALUE_ADDRESS (msymbol),
- (struct obj_section *) 0, 0);
- values.sals[0].section = SYMBOL_OBJ_SECTION (msymbol);
+/* See the comment in linespec.h. */
- /* The minimal symbol might point to a function descriptor;
- resolve it to the actual code address instead. */
- pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
- values.sals[0].pc,
- ¤t_target);
- if (pc != values.sals[0].pc)
- values.sals[0] = find_pc_sect_line (pc, NULL, 0);
+void
+destroy_linespec_result (struct linespec_result *ls)
+{
+ int i;
+ struct linespec_sals *lsal;
- if (funfirstline)
- skip_prologue_sal (&values.sals[0]);
+ xfree (ls->addr_string);
+ for (i = 0; VEC_iterate (linespec_sals, ls->sals, i, lsal); ++i)
+ {
+ xfree (lsal->canonical);
+ xfree (lsal->sals.sals);
+ }
+ VEC_free (linespec_sals, ls->sals);
+}
- values.nelts = 1;
- return values;
+/* Cleanup function for a linespec_result. */
+
+static void
+cleanup_linespec_result (void *a)
+{
+ destroy_linespec_result (a);
}
-void
-init_linespec_result (struct linespec_result *lr)
+/* See the comment in linespec.h. */
+
+struct cleanup *
+make_cleanup_destroy_linespec_result (struct linespec_result *ls)
{
- memset (lr, 0, sizeof (*lr));
+ return make_cleanup (cleanup_linespec_result, ls);
}
diff --git a/gdb/linespec.h b/gdb/linespec.h
index 3c86af3..401158c 100644
--- a/gdb/linespec.h
+++ b/gdb/linespec.h
@@ -20,8 +20,44 @@
struct symtab;
+#include "vec.h"
+
+/* Flags to pass to decode_line_1 and decode_line_full. */
+
+enum decode_line_flags
+ {
+ /* Set this flag if you want the resulting SALs to describe the
+ first line of indicated functions. */
+ DECODE_LINE_FUNFIRSTLINE = 1,
+
+ /* Set this flag if you want "list mode". In this mode, a
+ FILE:LINE linespec will always return a result, and such
+ linespecs will not be expanded to all matches. */
+ DECODE_LINE_LIST_MODE = 2
+ };
+
+/* decode_line_full returns a vector of these. */
+
+struct linespec_sals
+{
+ /* This is the linespec corresponding to the sals contained in this
+ object. It can be passed as the FILTER argument to future calls
+ to decode_line_full. This is freed by
+ destroy_linespec_result. */
+ char *canonical;
+
+ /* Sals. The 'sals' field is destroyed by
+ destroy_linespec_result. */
+ struct symtabs_and_lines sals;
+};
+
+typedef struct linespec_sals linespec_sals;
+DEF_VEC_O (linespec_sals);
+
/* An instance of this may be filled in by decode_line_1. The caller
- must call init_linespec_result to initialize it. */
+ must call init_linespec_result to initialize it and
+ destroy_linespec_result to destroy it. The caller must make copies
+ of any data that it needs to keep. */
struct linespec_result
{
@@ -30,22 +66,78 @@ struct linespec_result
display mechanism would do the wrong thing. */
int special_display;
- /* If non-NULL, an array of canonical names for returned
- symtab_and_line objects. The array has as many elements as the
- `nelts' field in the symtabs_and_line returned by decode_line_1.
- An element in the array may be NULL. The array and each non-NULL
- element in it are allocated with xmalloc and must be freed by the
- caller. */
- char **canonical;
+ /* If non-zero, the linespec result should be considered to be a
+ "pre-expanded" multi-location linespec. A pre-expanded linespec
+ holds all matching locations in a single linespec_sals
+ object. */
+ int pre_expanded;
+
+ /* If PRE_EXPANDED is non-zero, this is set to the linespec entered
+ by the user. This will be freed by destroy_linespec_result. */
+ char *addr_string;
+
+ /* The sals. The vector will be freed by
+ destroy_linespec_result. */
+ VEC (linespec_sals) *sals;
};
/* Initialize a linespec_result. */
extern void init_linespec_result (struct linespec_result *);
+/* Destroy a linespec_result. */
+
+extern void destroy_linespec_result (struct linespec_result *);
+
+/* Return a cleanup that destroys a linespec_result. */
+
+extern struct cleanup *
+ make_cleanup_destroy_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);
+ decode_line_1 (char **argptr, int flags,
+ struct symtab *default_symtab, int default_line);
+
+/* Parse *ARGPTR as a linespec and return results. This is the "full"
+ interface to this module, which handles multiple results
+ properly.
+
+ For FLAGS, see decode_line_flags. DECODE_LINE_LIST_MODE is not
+ valid for this function.
+
+ DEFAULT_SYMTAB and DEFAULT_LINE describe the default location.
+ DEFAULT_SYMTAB can be NULL, in which case the current symtab and
+ line are used.
+
+ CANONICAL is where the results are stored. It must not be NULL.
+
+ SELECT_MODE must be one of the multiple_symbols_* constants, or
+ NULL. It determines how multiple results will be handled. If
+ NULL, the appropriate CLI value will be used.
+
+ FILTER can either be NULL or a string holding a canonical name.
+ This is only valid when SELECT_MODE is multiple_symbols_all.
+
+ Multiple results are handled differently depending on the
+ arguments:
+
+ . With multiple_symbols_cancel, an exception is thrown.
+
+ . With multiple_symbols_ask, a menu is presented to the user. The
+ user may select none, in which case an exception is thrown; or all,
+ which is handled like multiple_symbols_all, below. Otherwise,
+ CANONICAL->SALS will have one entry for each name the user chose.
+
+ . With multiple_symbols_all, CANONICAL->SALS will have a single
+ entry describing all the matching locations. If FILTER is
+ non-NULL, then only locations whose canonical name is equal (in the
+ strcmp sense) to FILTER will be returned; all others will be
+ filtered out. */
+
+extern void decode_line_full (char **argptr, int flags,
+ struct symtab *default_symtab, int default_line,
+ struct linespec_result *canonical,
+ const char *select_mode,
+ const char *filter);
#endif /* defined (LINESPEC_H) */
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index 5270fe4..eefe9ec 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -53,6 +53,7 @@
#include "splay-tree.h"
#include "tracepoint.h"
#include "ada-lang.h"
+#include "linespec.h"
#include <ctype.h>
#include <sys/time.h>
@@ -2437,7 +2438,7 @@ mi_cmd_trace_find (char *command, char **argv, int argc)
if (argc != 2)
error (_("Line is required"));
- sals = decode_line_spec (argv[1], 1);
+ sals = decode_line_spec (argv[1], DECODE_LINE_FUNFIRSTLINE);
back_to = make_cleanup (xfree, sals.sals);
sal = sals.sals[0];
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 70871cd..f90f036 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -310,6 +310,46 @@ lookup_minimal_symbol (const char *name, const char *sfile,
return NULL;
}
+/* Iterate over all the minimal symbols in the objfile OBJF which
+ match NAME. Both the ordinary and demangled names of each symbol
+ are considered. The caller is responsible for canonicalizing NAME,
+ should that need to be done.
+
+ For each matching symbol, CALLBACK is called with the symbol and
+ USER_DATA as arguments. */
+
+void
+iterate_over_minimal_symbols (struct objfile *objf, const char *name,
+ void (*callback) (struct minimal_symbol *,
+ void *),
+ void *user_data)
+{
+ unsigned int hash;
+ struct minimal_symbol *iter;
+ int (*cmp) (const char *, const char *);
+
+ /* The first pass is over the ordinary hash table. */
+ hash = msymbol_hash (name) % MINIMAL_SYMBOL_HASH_SIZE;
+ iter = objf->msymbol_hash[hash];
+ cmp = (case_sensitivity == case_sensitive_on ? strcmp : strcasecmp);
+ while (iter)
+ {
+ if (cmp (SYMBOL_LINKAGE_NAME (iter), name) == 0)
+ (*callback) (iter, user_data);
+ iter = iter->hash_next;
+ }
+
+ /* The second pass is over the demangled table. */
+ hash = msymbol_hash_iw (name) % MINIMAL_SYMBOL_HASH_SIZE;
+ iter = objf->msymbol_demangled_hash[hash];
+ while (iter)
+ {
+ if (SYMBOL_MATCHES_SEARCH_NAME (iter, name))
+ (*callback) (iter, user_data);
+ iter = iter->demangled_hash_next;
+ }
+}
+
/* Look through all the current minimal symbol tables and find the
first minimal symbol that matches NAME and has text type. If OBJF
is non-NULL, limit the search to that objfile. Returns a pointer
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index 592b52e..dcf9459 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -952,49 +952,7 @@ classes_info (char *regexp, int from_tty)
printf_filtered (_("No classes matching \"%s\"\n"), regexp ? regexp : "*");
}
-/*
- * Function: find_imps (char *selector, struct symbol **sym_arr)
- *
- * Input: a string representing a selector
- * a pointer to an array of symbol pointers
- * possibly a pointer to a symbol found by the caller.
- *
- * Output: number of methods that implement that selector. Side
- * effects: The array of symbol pointers is filled with matching syms.
- *
- * By analogy with function "find_methods" (symtab.c), builds a list
- * of symbols matching the ambiguous input, so that "decode_line_2"
- * (symtab.c) can list them and ask the user to choose one or more.
- * In this case the matches are objective c methods
- * ("implementations") matching an objective c selector.
- *
- * Note that it is possible for a normal (c-style) function to have
- * the same name as an objective c selector. To prevent the selector
- * from eclipsing the function, we allow the caller (decode_line_1) to
- * search for such a function first, and if it finds one, pass it in
- * to us. We will then integrate it into the list. We also search
- * for one here, among the minsyms.
- *
- * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
- * into two parts: debuggable (struct symbol) syms, and
- * non_debuggable (struct minimal_symbol) syms. The debuggable
- * ones will come first, before NUM_DEBUGGABLE (which will thus
- * be the index of the first non-debuggable one).
- */
-
-/*
- * Function: total_number_of_imps (char *selector);
- *
- * Input: a string representing a selector
- * Output: number of methods that implement that selector.
- *
- * By analogy with function "total_number_of_methods", this allows
- * decode_line_1 (symtab.c) to detect if there are objective c methods
- * matching the input, and to allocate an array of pointers to them
- * which can be manipulated by "decode_line_2" (also in symtab.c).
- */
-
-char *
+static char *
parse_selector (char *method, char **selector)
{
char *s1 = NULL;
@@ -1050,7 +1008,7 @@ parse_selector (char *method, char **selector)
return s2;
}
-char *
+static char *
parse_method (char *method, char *type, char **class,
char **category, char **selector)
{
@@ -1154,15 +1112,11 @@ parse_method (char *method, char *type, char **class,
}
static void
-find_methods (struct symtab *symtab, char type,
- const char *class, const char *category,
- const char *selector, struct symbol **syms,
- unsigned int *nsym, unsigned int *ndebug)
+find_methods (char type, const char *class, const char *category,
+ const char *selector,
+ VEC (const_char_ptr) **symbol_names)
{
struct objfile *objfile = NULL;
- struct minimal_symbol *msymbol = NULL;
- struct block *block = NULL;
- struct symbol *sym = NULL;
char *symname = NULL;
@@ -1171,21 +1125,15 @@ find_methods (struct symtab *symtab, char type,
char *ncategory = NULL;
char *nselector = NULL;
- unsigned int csym = 0;
- unsigned int cdebug = 0;
-
static char *tmp = NULL;
static unsigned int tmplen = 0;
- gdb_assert (nsym != NULL);
- gdb_assert (ndebug != NULL);
-
- if (symtab)
- block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
+ gdb_assert (symbol_names != NULL);
ALL_OBJFILES (objfile)
{
unsigned int *objc_csym;
+ struct minimal_symbol *msymbol = NULL;
/* The objfile_csym variable counts the number of ObjC methods
that this objfile defines. We save that count as a private
@@ -1202,7 +1150,6 @@ find_methods (struct symtab *symtab, char type,
ALL_OBJFILE_MSYMBOLS (objfile, msymbol)
{
struct gdbarch *gdbarch = get_objfile_arch (objfile);
- CORE_ADDR pc = SYMBOL_VALUE_ADDRESS (msymbol);
QUIT;
@@ -1216,18 +1163,8 @@ find_methods (struct symtab *symtab, char type,
/* Not a method name. */
continue;
- /* The minimal symbol might point to a function descriptor;
- resolve it to the actual code address instead. */
- pc = gdbarch_convert_from_func_ptr_addr (gdbarch, pc,
- ¤t_target);
-
objfile_csym++;
- if (symtab)
- if (pc < BLOCK_START (block) || pc >= BLOCK_END (block))
- /* Not in the specified symtab. */
- continue;
-
/* Now that thinks are a bit sane, clean up the symname. */
while ((strlen (symname) + 1) >= tmplen)
{
@@ -1255,41 +1192,9 @@ find_methods (struct symtab *symtab, char type,
((nselector == NULL) || (strcmp (selector, nselector) != 0)))
continue;
- sym = find_pc_function (pc);
- if (sym != NULL)
- {
- const char *newsymname = SYMBOL_NATURAL_NAME (sym);
-
- if (strcmp (symname, newsymname) == 0)
- {
- /* Found a high-level method sym: swap it into the
- lower part of sym_arr (below num_debuggable). */
- if (syms != NULL)
- {
- syms[csym] = syms[cdebug];
- syms[cdebug] = sym;
- }
- csym++;
- cdebug++;
- }
- else
- {
- warning (
-"debugging symbol \"%s\" does not match minimal symbol (\"%s\"); ignoring",
- newsymname, symname);
- if (syms != NULL)
- syms[csym] = (struct symbol *) msymbol;
- csym++;
- }
- }
- else
- {
- /* Found a non-debuggable method symbol. */
- if (syms != NULL)
- syms[csym] = (struct symbol *) msymbol;
- csym++;
- }
+ VEC_safe_push (const_char_ptr, *symbol_names, symname);
}
+
if (objc_csym == NULL)
{
objc_csym = obstack_alloc (&objfile->objfile_obstack,
@@ -1301,38 +1206,79 @@ find_methods (struct symtab *symtab, char type,
/* Count of ObjC methods in this objfile should be constant. */
gdb_assert (*objc_csym == objfile_csym);
}
+}
+
+/* Uniquify a VEC of strings. */
- if (nsym != NULL)
- *nsym = csym;
- if (ndebug != NULL)
- *ndebug = cdebug;
+static void
+uniquify_strings (VEC (const_char_ptr) **strings)
+{
+ int ix;
+ const char *elem, *last = NULL;
+ int out;
+
+ qsort (VEC_address (const_char_ptr, *strings),
+ VEC_length (const_char_ptr, *strings),
+ sizeof (const_char_ptr),
+ compare_strings);
+ out = 0;
+ for (ix = 0; VEC_iterate (const_char_ptr, *strings, ix, elem); ++ix)
+ {
+ if (last == NULL || strcmp (last, elem) != 0)
+ {
+ /* Keep ELEM. */
+ VEC_replace (const_char_ptr, *strings, out, elem);
+ ++out;
+ }
+ last = elem;
+ }
+ VEC_truncate (const_char_ptr, *strings, out);
}
-char *find_imps (struct symtab *symtab, struct block *block,
- char *method, struct symbol **syms,
- unsigned int *nsym, unsigned int *ndebug)
+/*
+ * Function: find_imps (char *selector, struct symbol **sym_arr)
+ *
+ * Input: a string representing a selector
+ * a pointer to an array of symbol pointers
+ * possibly a pointer to a symbol found by the caller.
+ *
+ * Output: number of methods that implement that selector. Side
+ * effects: The array of symbol pointers is filled with matching syms.
+ *
+ * By analogy with function "find_methods" (symtab.c), builds a list
+ * of symbols matching the ambiguous input, so that "decode_line_2"
+ * (symtab.c) can list them and ask the user to choose one or more.
+ * In this case the matches are objective c methods
+ * ("implementations") matching an objective c selector.
+ *
+ * Note that it is possible for a normal (c-style) function to have
+ * the same name as an objective c selector. To prevent the selector
+ * from eclipsing the function, we allow the caller (decode_line_1) to
+ * search for such a function first, and if it finds one, pass it in
+ * to us. We will then integrate it into the list. We also search
+ * for one here, among the minsyms.
+ *
+ * NOTE: if NUM_DEBUGGABLE is non-zero, the sym_arr will be divided
+ * into two parts: debuggable (struct symbol) syms, and
+ * non_debuggable (struct minimal_symbol) syms. The debuggable
+ * ones will come first, before NUM_DEBUGGABLE (which will thus
+ * be the index of the first non-debuggable one).
+ */
+
+char *
+find_imps (char *method, VEC (const_char_ptr) **symbol_names)
{
char type = '\0';
char *class = NULL;
char *category = NULL;
char *selector = NULL;
- unsigned int csym = 0;
- unsigned int cdebug = 0;
-
- unsigned int ncsym = 0;
- unsigned int ncdebug = 0;
-
char *buf = NULL;
char *tmp = NULL;
- gdb_assert (nsym != NULL);
- gdb_assert (ndebug != NULL);
+ int selector_case = 0;
- if (nsym != NULL)
- *nsym = 0;
- if (ndebug != NULL)
- *ndebug = 0;
+ gdb_assert (symbol_names != NULL);
buf = (char *) alloca (strlen (method) + 1);
strcpy (buf, method);
@@ -1340,99 +1286,37 @@ char *find_imps (struct symtab *symtab, struct block *block,
if (tmp == NULL)
{
- struct symbol *sym = NULL;
- struct minimal_symbol *msym = NULL;
-
strcpy (buf, method);
tmp = parse_selector (buf, &selector);
if (tmp == NULL)
return NULL;
- sym = lookup_symbol (selector, block, VAR_DOMAIN, 0);
- if (sym != NULL)
- {
- if (syms)
- syms[csym] = sym;
- csym++;
- cdebug++;
- }
-
- if (sym == NULL)
- msym = lookup_minimal_symbol (selector, 0, 0);
-
- if (msym != NULL)
- {
- if (syms)
- syms[csym] = (struct symbol *)msym;
- csym++;
- }
+ selector_case = 1;
}
- if (syms != NULL)
- find_methods (symtab, type, class, category, selector,
- syms + csym, &ncsym, &ncdebug);
- else
- find_methods (symtab, type, class, category, selector,
- NULL, &ncsym, &ncdebug);
-
- /* If we didn't find any methods, just return. */
- if (ncsym == 0 && ncdebug == 0)
- return method;
+ find_methods (type, class, category, selector, symbol_names);
- /* Take debug symbols from the second batch of symbols and swap them
- * with debug symbols from the first batch. Repeat until either the
- * second section is out of debug symbols or the first section is
- * full of debug symbols. Either way we have all debug symbols
- * packed to the beginning of the buffer.
- */
-
- if (syms != NULL)
+ /* If we hit the "selector" case, and we found some methods, then
+ add the selector itself as a symbol, if it exists. */
+ if (selector_case && !VEC_empty (const_char_ptr, *symbol_names))
{
- while ((cdebug < csym) && (ncdebug > 0))
+ struct symbol *sym = lookup_symbol (selector, NULL, VAR_DOMAIN, 0);
+
+ if (sym != NULL)
+ VEC_safe_push (const_char_ptr, *symbol_names,
+ SYMBOL_NATURAL_NAME (sym));
+ else
{
- struct symbol *s = NULL;
- /* First non-debugging symbol. */
- unsigned int i = cdebug;
- /* Last of second batch of debug symbols. */
- unsigned int j = csym + ncdebug - 1;
-
- s = syms[j];
- syms[j] = syms[i];
- syms[i] = s;
-
- /* We've moved a symbol from the second debug section to the
- first one. */
- cdebug++;
- ncdebug--;
+ struct minimal_symbol *msym = lookup_minimal_symbol (selector, 0, 0);
+
+ if (msym != NULL)
+ VEC_safe_push (const_char_ptr, *symbol_names,
+ SYMBOL_NATURAL_NAME (msym));
}
}
- csym += ncsym;
- cdebug += ncdebug;
-
- if (nsym != NULL)
- *nsym = csym;
- if (ndebug != NULL)
- *ndebug = cdebug;
-
- if (syms == NULL)
- return method + (tmp - buf);
-
- if (csym > 1)
- {
- /* Sort debuggable symbols. */
- if (cdebug > 1)
- qsort (syms, cdebug, sizeof (struct minimal_symbol *),
- compare_classes);
-
- /* Sort minimal_symbols. */
- if ((csym - cdebug) > 1)
- qsort (&syms[cdebug], csym - cdebug,
- sizeof (struct minimal_symbol *), compare_classes);
- }
- /* Terminate the sym_arr list. */
- syms[csym] = 0;
+ uniquify_strings (symbol_names);
return method + (tmp - buf);
}
diff --git a/gdb/objc-lang.h b/gdb/objc-lang.h
index ee4cc29..351af7b 100644
--- a/gdb/objc-lang.h
+++ b/gdb/objc-lang.h
@@ -21,6 +21,8 @@
#if !defined(OBJC_LANG_H)
#define OBJC_LANG_H
+#include "cp-support.h" /* For VEC (const_char_ptr) */
+
struct stoken;
struct value;
@@ -39,15 +41,7 @@ extern char *objc_demangle (const char *mangled, int options);
extern int find_objc_msgcall (CORE_ADDR pc, CORE_ADDR *new_pc);
-extern char *parse_selector (char *method, char **selector);
-
-extern char *parse_method (char *method, char *type,
- char **class, char **category,
- char **selector);
-
-extern char *find_imps (struct symtab *symtab, struct block *block,
- char *method, struct symbol **syms,
- unsigned int *nsym, unsigned int *ndebug);
+extern char *find_imps (char *method, VEC (const_char_ptr) **symbol_names);
extern struct value *value_nsstring (struct gdbarch *gdbarch,
char *ptr, int len);
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index 6c4507d..c20fd78 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -125,13 +125,42 @@ require_partial_symbols (struct objfile *objfile, int verbose)
ALL_OBJFILES (objfile) \
ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, p)
-/* Lookup the partial symbol table of a source file named NAME.
- *If* there is no '/' in the name, a match after a '/'
- in the psymtab filename will also work. */
+/* Helper function for partial_map_symtabs_matching_filename that
+ expands the symtabs and calls the iterator. */
-static struct partial_symtab *
-lookup_partial_symtab (struct objfile *objfile, const char *name,
- const char *full_path, const char *real_path)
+static int
+partial_map_expand_apply (struct objfile *objfile,
+ const char *name,
+ const char *full_path,
+ const char *real_path,
+ struct partial_symtab *pst,
+ int (*callback) (struct symtab *, void *),
+ void *data)
+{
+ struct symtab *last_made = objfile->symtabs;
+
+ /* Don't visit already-expanded psymtabs. */
+ if (pst->readin)
+ return 0;
+
+ /* This may expand more than one symtab, and we want to iterate over
+ all of them. */
+ psymtab_to_symtab (pst);
+
+ return iterate_over_some_symtabs (name, full_path, real_path, callback, data,
+ objfile->symtabs, last_made);
+}
+
+/* Implementation of the map_symtabs_matching_filename method. */
+
+static int
+partial_map_symtabs_matching_filename (struct objfile *objfile,
+ const char *name,
+ const char *full_path,
+ const char *real_path,
+ int (*callback) (struct symtab *,
+ void *),
+ void *data)
{
struct partial_symtab *pst;
const char *name_basename = lbasename (name);
@@ -140,7 +169,9 @@ lookup_partial_symtab (struct objfile *objfile, const char *name,
{
if (FILENAME_CMP (name, pst->filename) == 0)
{
- return (pst);
+ if (partial_map_expand_apply (objfile, name, full_path, real_path,
+ pst, callback, data))
+ return 1;
}
/* Before we invoke realpath, which can get expensive when many
@@ -157,7 +188,9 @@ lookup_partial_symtab (struct objfile *objfile, const char *name,
if (pst->fullname != NULL
&& FILENAME_CMP (full_path, pst->fullname) == 0)
{
- return pst;
+ if (partial_map_expand_apply (objfile, name, full_path, real_path,
+ pst, callback, data))
+ return 1;
}
}
@@ -172,7 +205,9 @@ lookup_partial_symtab (struct objfile *objfile, const char *name,
}
if (rp != NULL && FILENAME_CMP (real_path, rp) == 0)
{
- return pst;
+ if (partial_map_expand_apply (objfile, name, full_path, real_path,
+ pst, callback, data))
+ return 1;
}
}
}
@@ -183,29 +218,12 @@ lookup_partial_symtab (struct objfile *objfile, const char *name,
ALL_OBJFILE_PSYMTABS_REQUIRED (objfile, pst)
{
if (FILENAME_CMP (lbasename (pst->filename), name) == 0)
- return (pst);
+ if (partial_map_expand_apply (objfile, name, full_path, real_path, pst,
+ callback, data))
+ return 1;
}
- return (NULL);
-}
-
-static int
-lookup_symtab_via_partial_symtab (struct objfile *objfile, const char *name,
- const char *full_path, const char *real_path,
- struct symtab **result)
-{
- struct partial_symtab *ps;
-
- ps = lookup_partial_symtab (objfile, name, full_path, real_path);
- if (!ps)
- return 0;
-
- if (ps->readin)
- error (_("Internal: readin %s pst for `%s' found when no symtab found."),
- ps->filename, name);
-
- *result = PSYMTAB_TO_SYMTAB (ps);
- return 1;
+ return 0;
}
/* Find which partial symtab contains PC and SECTION starting at psymtab PST.
@@ -1304,7 +1322,7 @@ const struct quick_symbol_functions psym_functions =
objfile_has_psyms,
find_last_source_symtab_from_partial,
forget_cached_source_info_partial,
- lookup_symtab_via_partial_symtab,
+ partial_map_symtabs_matching_filename,
lookup_symbol_aux_psymtabs,
pre_expand_symtabs_matching_psymtabs,
print_psymtab_stats_for_objfile,
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index b671cef..ab6c0ec 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -947,7 +947,7 @@ DEF_VEC_O (type_equality_entry_d);
the same, 0 otherwise. Handles NULLs properly. */
static int
-compare_strings (const char *s, const char *t)
+compare_maybe_null_strings (const char *s, const char *t)
{
if (s == NULL && t != NULL)
return 0;
@@ -983,9 +983,10 @@ check_types_equal (struct type *type1, struct type *type2,
|| TYPE_NFIELDS (type1) != TYPE_NFIELDS (type2))
return Py_NE;
- if (!compare_strings (TYPE_TAG_NAME (type1), TYPE_TAG_NAME (type2)))
+ if (!compare_maybe_null_strings (TYPE_TAG_NAME (type1),
+ TYPE_TAG_NAME (type2)))
return Py_NE;
- if (!compare_strings (TYPE_NAME (type1), TYPE_NAME (type2)))
+ if (!compare_maybe_null_strings (TYPE_NAME (type1), TYPE_NAME (type2)))
return Py_NE;
if (TYPE_CODE (type1) == TYPE_CODE_RANGE)
@@ -1008,7 +1009,8 @@ check_types_equal (struct type *type1, struct type *type2,
|| FIELD_BITSIZE (*field1) != FIELD_BITSIZE (*field2)
|| FIELD_LOC_KIND (*field1) != FIELD_LOC_KIND (*field2))
return Py_NE;
- if (!compare_strings (FIELD_NAME (*field1), FIELD_NAME (*field2)))
+ if (!compare_maybe_null_strings (FIELD_NAME (*field1),
+ FIELD_NAME (*field2)))
return Py_NE;
switch (FIELD_LOC_KIND (*field1))
{
@@ -1022,8 +1024,8 @@ check_types_equal (struct type *type1, struct type *type2,
return Py_NE;
break;
case FIELD_LOC_KIND_PHYSNAME:
- if (!compare_strings (FIELD_STATIC_PHYSNAME (*field1),
- FIELD_STATIC_PHYSNAME (*field2)))
+ if (!compare_maybe_null_strings (FIELD_STATIC_PHYSNAME (*field1),
+ FIELD_STATIC_PHYSNAME (*field2)))
return Py_NE;
break;
case FIELD_LOC_KIND_DWARF_BLOCK:
diff --git a/gdb/python/python.c b/gdb/python/python.c
index 6022572..b0b9a9c 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -512,7 +512,7 @@ gdbpy_decode_line (PyObject *self, PyObject *args)
{
copy = xstrdup (arg);
make_cleanup (xfree, copy);
- sals = decode_line_1 (©, 0, 0, 0, 0);
+ sals = decode_line_1 (©, 0, 0, 0);
make_cleanup (xfree, sals.sals);
}
else
diff --git a/gdb/skip.c b/gdb/skip.c
index 9f15c2f..07ca3f7 100644
--- a/gdb/skip.c
+++ b/gdb/skip.c
@@ -164,7 +164,7 @@ skip_function_command (char *arg, int from_tty)
TRY_CATCH (decode_exception, RETURN_MASK_ERROR)
{
- sals = decode_line_1 (&arg, 1, 0, 0, 0);
+ sals = decode_line_1 (&arg, DECODE_LINE_FUNFIRSTLINE, 0, 0);
}
if (decode_exception.reason < 0)
@@ -514,7 +514,7 @@ skip_re_set (void)
TRY_CATCH (decode_exception, RETURN_MASK_ERROR)
{
- sals = decode_line_1 (&func_name, 1, 0, 0, 0);
+ sals = decode_line_1 (&func_name, DECODE_LINE_FUNFIRSTLINE, 0, 0);
}
if (decode_exception.reason >= 0
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
index 888aa34..21efbdf 100644
--- a/gdb/solib-target.c
+++ b/gdb/solib-target.c
@@ -28,8 +28,6 @@
#include "gdb_string.h"
-DEF_VEC_I(CORE_ADDR);
-
/* Private data for each loaded library. */
struct lm_info
{
diff --git a/gdb/source.c b/gdb/source.c
index 77df541..57f5ad8 100644
--- a/gdb/source.c
+++ b/gdb/source.c
@@ -245,7 +245,7 @@ select_source_symtab (struct symtab *s)
if one exists. */
if (lookup_symbol (main_name (), 0, VAR_DOMAIN, 0))
{
- sals = decode_line_spec (main_name (), 1);
+ sals = decode_line_spec (main_name (), DECODE_LINE_FUNFIRSTLINE);
sal = sals.sals[0];
xfree (sals.sals);
current_source_pspace = sal.pspace;
@@ -1413,12 +1413,14 @@ line_info (char *arg, int from_tty)
struct symtab_and_line sal;
CORE_ADDR start_pc, end_pc;
int i;
+ struct cleanup *cleanups;
init_sal (&sal); /* initialize to zeroes */
if (arg == 0)
{
sal.symtab = current_source_symtab;
+ sal.pspace = current_program_space;
sal.line = last_line_listed;
sals.nelts = 1;
sals.sals = (struct symtab_and_line *)
@@ -1427,16 +1429,20 @@ line_info (char *arg, int from_tty)
}
else
{
- sals = decode_line_spec_1 (arg, 0);
+ sals = decode_line_spec_1 (arg, DECODE_LINE_LIST_MODE);
dont_repeat ();
}
+ cleanups = make_cleanup (xfree, sals.sals);
+
/* C++ More than one line may have been specified, as when the user
specifies an overloaded function name. Print info on them all. */
for (i = 0; i < sals.nelts; i++)
{
sal = sals.sals[i];
+ if (sal.pspace != current_program_space)
+ continue;
if (sal.symtab == 0)
{
@@ -1502,7 +1508,7 @@ line_info (char *arg, int from_tty)
printf_filtered (_("Line number %d is out of range for \"%s\".\n"),
sal.line, sal.symtab->filename);
}
- xfree (sals.sals);
+ do_cleanups (cleanups);
}
\f
/* Commands to search the source file for a regexp. */
diff --git a/gdb/stack.c b/gdb/stack.c
index 9136daa..c5c54db 100644
--- a/gdb/stack.c
+++ b/gdb/stack.c
@@ -47,6 +47,7 @@
#include "cp-support.h"
#include "disasm.h"
#include "inline-frame.h"
+#include "linespec.h"
#include "gdb_assert.h"
#include <ctype.h>
@@ -2444,20 +2445,25 @@ func_command (char *arg, int from_tty)
int i;
int level = 1;
struct function_bounds *func_bounds = NULL;
+ struct cleanup *cleanups;
if (arg != NULL)
return;
frame = parse_frame_specification ("0");
- sals = decode_line_spec (arg, 1);
+ sals = decode_line_spec (arg, DECODE_LINE_FUNFIRSTLINE);
+ cleanups = make_cleanup (xfree, sals.sals);
func_bounds = (struct function_bounds *) xmalloc (
sizeof (struct function_bounds) * sals.nelts);
+ make_cleanup (xfree, func_bounds);
for (i = 0; (i < sals.nelts && !found); i++)
{
- if (sals.sals[i].pc == 0
- || find_pc_partial_function (sals.sals[i].pc, NULL,
- &func_bounds[i].low,
- &func_bounds[i].high) == 0)
+ if (sals.sals[i].pspace != current_program_space)
+ func_bounds[i].low = func_bounds[i].high = 0;
+ else if (sals.sals[i].pc == 0
+ || find_pc_partial_function (sals.sals[i].pc, NULL,
+ &func_bounds[i].low,
+ &func_bounds[i].high) == 0)
{
func_bounds[i].low = func_bounds[i].high = 0;
}
@@ -2476,8 +2482,7 @@ func_command (char *arg, int from_tty)
}
while (!found && level == 0);
- if (func_bounds)
- xfree (func_bounds);
+ do_cleanups (cleanups);
if (!found)
printf_filtered (_("'%s' not within current stack frame.\n"), arg);
diff --git a/gdb/symfile.h b/gdb/symfile.h
index accd20e..dfe5042 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -152,22 +152,24 @@ struct quick_symbol_functions
/* Forget all cached full file names for OBJFILE. */
void (*forget_cached_source_info) (struct objfile *objfile);
- /* Look up the symbol table, in OBJFILE, of a source file named
- NAME. If there is no '/' in the name, a match after a '/' in the
- symbol table's file name will also work. FULL_PATH is the
- absolute file name, and REAL_PATH is the same, run through
- gdb_realpath.
-
- If no such symbol table can be found, returns 0.
-
- Otherwise, sets *RESULT to the symbol table and returns 1. This
- might return 1 and set *RESULT to NULL if the requested file is
- an include file that does not have a symtab of its own. */
- int (*lookup_symtab) (struct objfile *objfile,
- const char *name,
- const char *full_path,
- const char *real_path,
- struct symtab **result);
+ /* Expand and iterate over each "partial" symbol table in OBJFILE
+ where the source file is named NAME.
+
+ If there is no '/' in the name, a match after a '/' in the symbol
+ table's file name will also work. FULL_PATH is the absolute file
+ name, and REAL_PATH is the same, run through gdb_realpath.
+
+ If a match is found, the "partial" symbol table is expanded.
+ Then, this calls iterate_over_some_symtabs (or equivalent) over
+ all newly-created symbol tables, passing CALLBACK and DATA to it.
+ The result of this call is returned. */
+ int (*map_symtabs_matching_filename) (struct objfile *objfile,
+ const char *name,
+ const char *full_path,
+ const char *real_path,
+ int (*callback) (struct symtab *,
+ void *),
+ void *data);
/* Check to see if the symbol is defined in a "partial" symbol table
of OBJFILE. KIND should be either GLOBAL_BLOCK or STATIC_BLOCK,
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 3d94e6b..3ae5cf9 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -81,7 +81,7 @@ static void sources_info (char *, int);
static void output_source_filename (const char *, int *);
-static int find_line_common (struct linetable *, int, int *);
+static int find_line_common (struct linetable *, int, int *, int);
static struct symbol *lookup_symbol_aux (const char *name,
const struct block *block,
@@ -147,44 +147,38 @@ multiple_symbols_select_mode (void)
const struct block *block_found;
-/* Check for a symtab of a specific name; first in symtabs, then in
- psymtabs. *If* there is no '/' in the name, a match after a '/'
- in the symtab filename will also work. */
+/* Check for a symtab of a specific name by searching some symtabs.
+ This is a helper function for callbacks of iterate_over_symtabs.
-struct symtab *
-lookup_symtab (const char *name)
+ The return value, NAME, FULL_PATH, REAL_PATH, CALLBACK, and DATA
+ are identical to the `map_symtabs_matching_filename' method of
+ quick_symbol_functions.
+
+ FIRST and AFTER_LAST indicate the range of symtabs to search.
+ AFTER_LAST is one past the last symtab to search; NULL means to
+ search until the end of the list. */
+
+int
+iterate_over_some_symtabs (const char *name,
+ const char *full_path,
+ const char *real_path,
+ int (*callback) (struct symtab *symtab,
+ void *data),
+ void *data,
+ struct symtab *first,
+ struct symtab *after_last)
{
- int found;
struct symtab *s = NULL;
- struct objfile *objfile;
- char *real_path = NULL;
- char *full_path = NULL;
struct cleanup *cleanup;
const char* base_name = lbasename (name);
- cleanup = make_cleanup (null_cleanup, NULL);
-
- /* Here we are interested in canonicalizing an absolute path, not
- absolutizing a relative path. */
- if (IS_ABSOLUTE_PATH (name))
+ for (s = first; s != NULL && s != after_last; s = s->next)
{
- full_path = xfullpath (name);
- make_cleanup (xfree, full_path);
- real_path = gdb_realpath (name);
- make_cleanup (xfree, real_path);
- }
-
-got_symtab:
-
- /* First, search for an exact match. */
-
- ALL_SYMTABS (objfile, s)
- {
- if (FILENAME_CMP (name, s->filename) == 0)
- {
- do_cleanups (cleanup);
- return s;
- }
+ if (FILENAME_CMP (name, s->filename) == 0)
+ {
+ if (callback (s, data))
+ return 1;
+ }
/* Before we invoke realpath, which can get expensive when many
files are involved, do a quick comparison of the basenames. */
@@ -201,8 +195,8 @@ got_symtab:
if (fp != NULL && FILENAME_CMP (full_path, fp) == 0)
{
- do_cleanups (cleanup);
- return s;
+ if (callback (s, data))
+ return 1;
}
}
@@ -216,62 +210,114 @@ got_symtab:
make_cleanup (xfree, rp);
if (FILENAME_CMP (real_path, rp) == 0)
- {
- do_cleanups (cleanup);
- return s;
- }
+ {
+ if (callback (s, data))
+ return 1;
+ }
}
}
- }
+ }
/* Now, search for a matching tail (only if name doesn't have any dirs). */
if (lbasename (name) == name)
- ALL_SYMTABS (objfile, s)
{
- if (FILENAME_CMP (lbasename (s->filename), name) == 0)
+ for (s = first; s != NULL && s != after_last; s = s->next)
{
- do_cleanups (cleanup);
- return s;
+ if (FILENAME_CMP (lbasename (s->filename), name) == 0)
+ {
+ if (callback (s, data))
+ return 1;
+ }
}
}
+ return 0;
+}
+
+/* Check for a symtab of a specific name; first in symtabs, then in
+ psymtabs. *If* there is no '/' in the name, a match after a '/'
+ in the symtab filename will also work.
+
+ Calls CALLBACK with each symtab that is found and with the supplied
+ DATA. If CALLBACK returns true, the search stops. */
+
+void
+iterate_over_symtabs (const char *name,
+ int (*callback) (struct symtab *symtab,
+ void *data),
+ void *data)
+{
+ struct symtab *s = NULL;
+ struct objfile *objfile;
+ char *real_path = NULL;
+ char *full_path = NULL;
+ struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
+
+ /* Here we are interested in canonicalizing an absolute path, not
+ absolutizing a relative path. */
+ if (IS_ABSOLUTE_PATH (name))
+ {
+ full_path = xfullpath (name);
+ make_cleanup (xfree, full_path);
+ real_path = gdb_realpath (name);
+ make_cleanup (xfree, real_path);
+ }
+
+ ALL_OBJFILES (objfile)
+ {
+ if (iterate_over_some_symtabs (name, full_path, real_path, callback, data,
+ objfile->symtabs, NULL))
+ {
+ do_cleanups (cleanups);
+ return;
+ }
+ }
+
/* Same search rules as above apply here, but now we look thru the
psymtabs. */
- found = 0;
ALL_OBJFILES (objfile)
{
if (objfile->sf
- && objfile->sf->qf->lookup_symtab (objfile, name, full_path, real_path,
- &s))
+ && objfile->sf->qf->map_symtabs_matching_filename (objfile,
+ name,
+ full_path,
+ real_path,
+ callback,
+ data))
{
- found = 1;
- break;
+ do_cleanups (cleanups);
+ return;
}
}
- if (s != NULL)
- {
- do_cleanups (cleanup);
- return s;
- }
- if (!found)
- {
- do_cleanups (cleanup);
- return NULL;
- }
+ do_cleanups (cleanups);
+}
+
+/* The callback function used by lookup_symtab. */
+
+static int
+lookup_symtab_callback (struct symtab *symtab, void *data)
+{
+ struct symtab **result_ptr = data;
- /* At this point, we have located the psymtab for this file, but
- the conversion to a symtab has failed. This usually happens
- when we are looking up an include file. In this case,
- PSYMTAB_TO_SYMTAB doesn't return a symtab, even though one has
- been created. So, we need to run through the symtabs again in
- order to find the file.
- XXX - This is a crock, and should be fixed inside of the
- symbol parsing routines. */
- goto got_symtab;
+ *result_ptr = symtab;
+ return 1;
}
+
+/* A wrapper for iterate_over_symtabs that returns the first matching
+ symtab, or NULL. */
+
+struct symtab *
+lookup_symtab (const char *name)
+{
+ struct symtab *result = NULL;
+
+ iterate_over_symtabs (name, lookup_symtab_callback, &result);
+ return result;
+}
+
\f
/* Mangle a GDB method stub type. This actually reassembles the pieces of the
full method name, which consist of the class name (from T), the unadorned
@@ -1006,33 +1052,16 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
return sym;
}
-/* Find the definition for a specified symbol name NAME
- in domain DOMAIN, visible from lexical block BLOCK.
- Returns the struct symbol pointer, or zero if no symbol is found.
- C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if
- NAME is a field of the current implied argument `this'. If so set
- *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero.
- BLOCK_FOUND is set to the block in which NAME is found (in the case of
- a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */
+/* Compute the demangled form of NAME as used by the various symbol
+ lookup functions. The result is stored in *RESULT_NAME. Returns a
+ cleanup which can be used to clean up the result. */
-/* This function has a bunch of loops in it and it would seem to be
- attractive to put in some QUIT's (though I'm not really sure
- whether it can run long enough to be really important). But there
- are a few calls for which it would appear to be bad news to quit
- out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c. (Note
- that there is C++ code below which can error(), but that probably
- doesn't affect these calls since they are looking for a known
- variable and thus can probably assume it will never hit the C++
- code). */
-
-struct symbol *
-lookup_symbol_in_language (const char *name, const struct block *block,
- const domain_enum domain, enum language lang,
- int *is_a_field_of_this)
+struct cleanup *
+demangle_for_lookup (const char *name, enum language lang,
+ const char **result_name)
{
char *demangled_name = NULL;
const char *modified_name = NULL;
- struct symbol *returnval;
struct cleanup *cleanup = make_cleanup (null_cleanup, 0);
modified_name = name;
@@ -1079,6 +1108,38 @@ lookup_symbol_in_language (const char *name, const struct block *block,
}
}
+ *result_name = modified_name;
+ return cleanup;
+}
+
+/* Find the definition for a specified symbol name NAME
+ in domain DOMAIN, visible from lexical block BLOCK.
+ Returns the struct symbol pointer, or zero if no symbol is found.
+ C++: if IS_A_FIELD_OF_THIS is nonzero on entry, check to see if
+ NAME is a field of the current implied argument `this'. If so set
+ *IS_A_FIELD_OF_THIS to 1, otherwise set it to zero.
+ BLOCK_FOUND is set to the block in which NAME is found (in the case of
+ a field of `this', value_of_this sets BLOCK_FOUND to the proper value.) */
+
+/* This function has a bunch of loops in it and it would seem to be
+ attractive to put in some QUIT's (though I'm not really sure
+ whether it can run long enough to be really important). But there
+ are a few calls for which it would appear to be bad news to quit
+ out of here: find_proc_desc in alpha-tdep.c and mips-tdep.c. (Note
+ that there is C++ code below which can error(), but that probably
+ doesn't affect these calls since they are looking for a known
+ variable and thus can probably assume it will never hit the C++
+ code). */
+
+struct symbol *
+lookup_symbol_in_language (const char *name, const struct block *block,
+ const domain_enum domain, enum language lang,
+ int *is_a_field_of_this)
+{
+ const char *modified_name;
+ struct symbol *returnval;
+ struct cleanup *cleanup = demangle_for_lookup (name, lang, &modified_name);
+
returnval = lookup_symbol_aux (modified_name, block, domain, lang,
is_a_field_of_this);
do_cleanups (cleanup);
@@ -1771,6 +1832,44 @@ lookup_block_symbol (const struct block *block, const char *name,
}
}
+/* Iterate over the symbols named NAME, matching DOMAIN, starting with
+ BLOCK.
+
+ For each symbol that matches, CALLBACK is called. The symbol and
+ DATA are passed to the callback.
+
+ If CALLBACK returns zero, the iteration ends. Otherwise, the
+ search continues. This function iterates upward through blocks.
+ When the outermost block has been finished, the function
+ returns. */
+
+void
+iterate_over_symbols (const struct block *block, const char *name,
+ const domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data)
+{
+ while (block)
+ {
+ struct dict_iterator iter;
+ struct symbol *sym;
+
+ for (sym = dict_iter_name_first (BLOCK_DICT (block), name, &iter);
+ sym != NULL;
+ sym = dict_iter_name_next (name, &iter))
+ {
+ if (symbol_matches_domain (SYMBOL_LANGUAGE (sym),
+ SYMBOL_DOMAIN (sym), domain))
+ {
+ if (!callback (sym, data))
+ return;
+ }
+ }
+
+ block = BLOCK_SUPERBLOCK (block);
+ }
+}
+
/* Find the symtab associated with PC and SECTION. Look through the
psymtabs and read in another symtab if necessary. */
@@ -2196,7 +2295,7 @@ find_line_symtab (struct symtab *symtab, int line,
/* First try looking it up in the given symtab. */
best_linetable = LINETABLE (symtab);
best_symtab = symtab;
- best_index = find_line_common (best_linetable, line, &exact);
+ best_index = find_line_common (best_linetable, line, &exact, 0);
if (best_index < 0 || !exact)
{
/* Didn't find an exact match. So we better keep looking for
@@ -2241,7 +2340,7 @@ find_line_symtab (struct symtab *symtab, int line,
&& FILENAME_CMP (symtab->fullname, s->fullname) != 0)
continue;
l = LINETABLE (s);
- ind = find_line_common (l, line, &exact);
+ ind = find_line_common (l, line, &exact, 0);
if (ind >= 0)
{
if (exact)
@@ -2272,6 +2371,46 @@ done:
return best_symtab;
}
+
+/* Given SYMTAB, returns all the PCs function in the symtab that
+ exactly match LINE. Returns NULL if there are no exact matches,
+ but updates BEST_ITEM in this case. */
+
+VEC (CORE_ADDR) *
+find_pcs_for_symtab_line (struct symtab *symtab, int line,
+ struct linetable_entry **best_item)
+{
+ int start = 0, ix;
+ struct symbol *previous_function = NULL;
+ VEC (CORE_ADDR) *result = NULL;
+
+ /* First, collect all the PCs that are at this line. */
+ while (1)
+ {
+ int was_exact;
+ int idx;
+
+ idx = find_line_common (LINETABLE (symtab), line, &was_exact, start);
+ if (idx < 0)
+ break;
+
+ if (!was_exact)
+ {
+ struct linetable_entry *item = &LINETABLE (symtab)->item[idx];
+
+ if (*best_item == NULL || item->line < (*best_item)->line)
+ *best_item = item;
+
+ break;
+ }
+
+ VEC_safe_push (CORE_ADDR, result, LINETABLE (symtab)->item[idx].pc);
+ start = idx + 1;
+ }
+
+ return result;
+}
+
\f
/* Set the PC value for a given source file and line number and return true.
Returns zero for invalid line number (and sets the PC to 0).
@@ -2340,12 +2479,13 @@ find_line_pc_range (struct symtab_and_line sal, CORE_ADDR *startptr,
/* Given a line table and a line number, return the index into the line
table for the pc of the nearest line whose number is >= the specified one.
Return -1 if none is found. The value is >= 0 if it is an index.
+ START is the index at which to start searching the line table.
Set *EXACT_MATCH nonzero if the value returned is an exact match. */
static int
find_line_common (struct linetable *l, int lineno,
- int *exact_match)
+ int *exact_match, int start)
{
int i;
int len;
@@ -2365,7 +2505,7 @@ find_line_common (struct linetable *l, int lineno,
return -1;
len = l->nitems;
- for (i = 0; i < len; i++)
+ for (i = start; i < len; i++)
{
struct linetable_entry *item = &(l->item[i]);
@@ -4518,7 +4658,7 @@ skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
}
\f
struct symtabs_and_lines
-decode_line_spec (char *string, int funfirstline)
+decode_line_spec (char *string, int flags)
{
struct symtabs_and_lines sals;
struct symtab_and_line cursal;
@@ -4530,9 +4670,8 @@ decode_line_spec (char *string, int funfirstline)
and get a default or it will recursively call us! */
cursal = get_current_source_symtab_and_line ();
- sals = decode_line_1 (&string, funfirstline,
- cursal.symtab, cursal.line,
- NULL);
+ sals = decode_line_1 (&string, flags,
+ cursal.symtab, cursal.line);
if (*string)
error (_("Junk at end of line specification: %s"), string);
@@ -4620,211 +4759,6 @@ symtab_observer_executable_changed (void)
set_main_name (NULL);
}
-/* Helper to expand_line_sal below. Appends new sal to SAL,
- initializing it from SYMTAB, LINENO and PC. */
-static void
-append_expanded_sal (struct symtabs_and_lines *sal,
- struct program_space *pspace,
- struct symtab *symtab,
- int lineno, CORE_ADDR pc)
-{
- sal->sals = xrealloc (sal->sals,
- sizeof (sal->sals[0])
- * (sal->nelts + 1));
- init_sal (sal->sals + sal->nelts);
- sal->sals[sal->nelts].pspace = pspace;
- sal->sals[sal->nelts].symtab = symtab;
- sal->sals[sal->nelts].section = NULL;
- sal->sals[sal->nelts].end = 0;
- sal->sals[sal->nelts].line = lineno;
- sal->sals[sal->nelts].pc = pc;
- ++sal->nelts;
-}
-
-/* Helper to expand_line_sal below. Search in the symtabs for any
- linetable entry that exactly matches FULLNAME and LINENO and append
- them to RET. If FULLNAME is NULL or if a symtab has no full name,
- use FILENAME and LINENO instead. If there is at least one match,
- return 1; otherwise, return 0, and return the best choice in BEST_ITEM
- and BEST_SYMTAB. */
-
-static int
-append_exact_match_to_sals (char *filename, char *fullname, int lineno,
- struct symtabs_and_lines *ret,
- struct linetable_entry **best_item,
- struct symtab **best_symtab)
-{
- struct program_space *pspace;
- struct objfile *objfile;
- struct symtab *symtab;
- int exact = 0;
- int j;
- *best_item = 0;
- *best_symtab = 0;
-
- ALL_PSPACES (pspace)
- ALL_PSPACE_SYMTABS (pspace, objfile, symtab)
- {
- if (FILENAME_CMP (filename, symtab->filename) == 0)
- {
- struct linetable *l;
- int len;
-
- if (fullname != NULL
- && symtab_to_fullname (symtab) != NULL
- && FILENAME_CMP (fullname, symtab->fullname) != 0)
- continue;
- l = LINETABLE (symtab);
- if (!l)
- continue;
- len = l->nitems;
-
- for (j = 0; j < len; j++)
- {
- struct linetable_entry *item = &(l->item[j]);
-
- if (item->line == lineno)
- {
- exact = 1;
- append_expanded_sal (ret, objfile->pspace,
- symtab, lineno, item->pc);
- }
- else if (!exact && item->line > lineno
- && (*best_item == NULL
- || item->line < (*best_item)->line))
- {
- *best_item = item;
- *best_symtab = symtab;
- }
- }
- }
- }
- return exact;
-}
-
-/* Compute a set of all sals in all program spaces that correspond to
- same file and line as SAL and return those. If there are several
- sals that belong to the same block, only one sal for the block is
- included in results. */
-
-struct symtabs_and_lines
-expand_line_sal (struct symtab_and_line sal)
-{
- struct symtabs_and_lines ret;
- int i, j;
- struct objfile *objfile;
- int lineno;
- int deleted = 0;
- struct block **blocks = NULL;
- int *filter;
- struct cleanup *old_chain;
-
- ret.nelts = 0;
- ret.sals = NULL;
-
- /* Only expand sals that represent file.c:line. */
- if (sal.symtab == NULL || sal.line == 0 || sal.pc != 0)
- {
- ret.sals = xmalloc (sizeof (struct symtab_and_line));
- ret.sals[0] = sal;
- ret.nelts = 1;
- return ret;
- }
- else
- {
- struct program_space *pspace;
- struct linetable_entry *best_item = 0;
- struct symtab *best_symtab = 0;
- int exact = 0;
- char *match_filename;
-
- lineno = sal.line;
- match_filename = sal.symtab->filename;
-
- /* We need to find all symtabs for a file which name
- is described by sal. We cannot just directly
- iterate over symtabs, since a symtab might not be
- yet created. We also cannot iterate over psymtabs,
- calling PSYMTAB_TO_SYMTAB and working on that symtab,
- since PSYMTAB_TO_SYMTAB will return NULL for psymtab
- corresponding to an included file. Therefore, we do
- first pass over psymtabs, reading in those with
- the right name. Then, we iterate over symtabs, knowing
- that all symtabs we're interested in are loaded. */
-
- old_chain = save_current_program_space ();
- ALL_PSPACES (pspace)
- {
- set_current_program_space (pspace);
- ALL_PSPACE_OBJFILES (pspace, objfile)
- {
- if (objfile->sf)
- objfile->sf->qf->expand_symtabs_with_filename (objfile,
- sal.symtab->filename);
- }
- }
- do_cleanups (old_chain);
-
- /* Now search the symtab for exact matches and append them. If
- none is found, append the best_item and all its exact
- matches. */
- symtab_to_fullname (sal.symtab);
- exact = append_exact_match_to_sals (sal.symtab->filename,
- sal.symtab->fullname, lineno,
- &ret, &best_item, &best_symtab);
- if (!exact && best_item)
- append_exact_match_to_sals (best_symtab->filename,
- best_symtab->fullname, best_item->line,
- &ret, &best_item, &best_symtab);
- }
-
- /* For optimized code, compiler can scatter one source line accross
- disjoint ranges of PC values, even when no duplicate functions
- or inline functions are involved. For example, 'for (;;)' inside
- non-template non-inline non-ctor-or-dtor function can result
- in two PC ranges. In this case, we don't want to set breakpoint
- on first PC of each range. To filter such cases, we use containing
- blocks -- for each PC found above we see if there are other PCs
- that are in the same block. If yes, the other PCs are filtered out. */
-
- old_chain = save_current_program_space ();
- filter = alloca (ret.nelts * sizeof (int));
- blocks = alloca (ret.nelts * sizeof (struct block *));
- for (i = 0; i < ret.nelts; ++i)
- {
- set_current_program_space (ret.sals[i].pspace);
-
- filter[i] = 1;
- blocks[i] = block_for_pc_sect (ret.sals[i].pc, ret.sals[i].section);
- }
- do_cleanups (old_chain);
-
- for (i = 0; i < ret.nelts; ++i)
- if (blocks[i] != NULL)
- for (j = i+1; j < ret.nelts; ++j)
- if (blocks[j] == blocks[i])
- {
- filter[j] = 0;
- ++deleted;
- break;
- }
-
- {
- struct symtab_and_line *final =
- xmalloc (sizeof (struct symtab_and_line) * (ret.nelts-deleted));
-
- for (i = 0, j = 0; i < ret.nelts; ++i)
- if (filter[i])
- final[j++] = ret.sals[i];
-
- ret.nelts -= deleted;
- xfree (ret.sals);
- ret.sals = final;
- }
-
- return ret;
-}
-
/* Return 1 if the supplied producer string matches the ARM RealView
compiler (armcc). */
diff --git a/gdb/symtab.h b/gdb/symtab.h
index 39a61f4..7b52c88 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -22,6 +22,8 @@
#if !defined (SYMTAB_H)
#define SYMTAB_H 1
+#include "vec.h"
+
/* Opaque declarations. */
struct ui_file;
struct frame_info;
@@ -1056,6 +1058,12 @@ extern struct minimal_symbol *lookup_minimal_symbol_by_pc_name
extern struct minimal_symbol *lookup_minimal_symbol_by_pc (CORE_ADDR);
+extern void iterate_over_minimal_symbols (struct objfile *objf,
+ const char *name,
+ void (*callback) (struct minimal_symbol *,
+ void *),
+ void *user_data);
+
extern int in_gnu_ifunc_stub (CORE_ADDR pc);
/* Functions for resolving STT_GNU_IFUNC symbols which are implemented only
@@ -1295,8 +1303,6 @@ struct symbol *lookup_global_symbol_from_objfile (const struct objfile *,
const char *name,
const domain_enum domain);
-extern struct symtabs_and_lines expand_line_sal (struct symtab_and_line sal);
-
/* Return 1 if the supplied producer string matches the ARM RealView
compiler (armcc). */
int producer_is_realview (const char *producer);
@@ -1308,4 +1314,31 @@ struct objfile *lookup_objfile_from_block (const struct block *block);
extern int basenames_may_differ;
+int iterate_over_some_symtabs (const char *name,
+ const char *full_path,
+ const char *real_path,
+ int (*callback) (struct symtab *symtab,
+ void *data),
+ void *data,
+ struct symtab *first,
+ struct symtab *after_last);
+
+void iterate_over_symtabs (const char *name,
+ int (*callback) (struct symtab *symtab,
+ void *data),
+ void *data);
+
+DEF_VEC_I (CORE_ADDR);
+
+VEC (CORE_ADDR) *find_pcs_for_symtab_line (struct symtab *symtab, int line,
+ struct linetable_entry **best_entry);
+
+void iterate_over_symbols (const struct block *block, const char *name,
+ const domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data);
+
+struct cleanup *demangle_for_lookup (const char *name, enum language lang,
+ const char **result_name);
+
#endif /* !defined(SYMTAB_H) */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 8c0c1c0..cd3ca73 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,37 @@
+2011-11-18 Tom Tromey <tromey@redhat.com>
+
+ * gdb.base/solib-weak.exp (do_test): Remove kfail.
+ * gdb.trace/tracecmd.exp: Disable pending breakpoints earlier.
+ * gdb.objc/objcdecode.exp: Update for output changes.
+ * gdb.linespec/linespec.exp: New file.
+ * gdb.linespec/lspec.cc: New file.
+ * gdb.linespec/lspec.h: New file.
+ * gdb.linespec/body.h: New file.
+ * gdb.linespec/base/two/thefile.cc: New file.
+ * gdb.linespec/base/one/thefile.cc: New file.
+ * gdb.linespec/Makefile.in: New file.
+ * gdb.cp/templates.exp (test_template_breakpoints): Update for
+ output changes.
+ * gdb.cp/re-set-overloaded.exp: Remove kfail.
+ * gdb.cp/ovldbreak.exp: Update for output changes. "all" test now
+ makes one breakpoint.
+ * gdb.cp/method2.exp (test_break): Update for output changes.
+ * gdb.cp/mb-templates.exp: Update for output changes.
+ * gdb.cp/mb-inline.exp: Update for output changes.
+ * gdb.cp/mb-ctor.exp: Update for output changes.
+ * gdb.cp/ovsrch.exp: Use fully-qualified names.
+ * gdb.base/solib-symbol.exp: Run to main later. Breakpoint now
+ has multiple matches.
+ * gdb.base/sepdebug.exp: Disable pending breakpoints. Update for
+ error message change.
+ * gdb.base/list.exp (test_list_filename_and_number): Update for
+ error message change.
+ * gdb.base/break.exp: Disable pending breakpoints. Update for
+ output changes.
+ * configure.ac: Add gdb.linespec.
+ * configure: Rebuild.
+ * Makefile.in (ALL_SUBDIRS): Add gdb.linespec.
+
2011-11-25 Jan Kratochvil <jan.kratochvil@redhat.com>
PR testsuite/12649
diff --git a/gdb/testsuite/Makefile.in b/gdb/testsuite/Makefile.in
index 8b22324..d3c9cfc 100644
--- a/gdb/testsuite/Makefile.in
+++ b/gdb/testsuite/Makefile.in
@@ -35,7 +35,7 @@ SUBDIRS = @subdirs@
RPATH_ENVVAR = @RPATH_ENVVAR@
ALL_SUBDIRS = gdb.ada gdb.arch gdb.asm gdb.base gdb.cell gdb.cp gdb.disasm \
gdb.dwarf2 gdb.fortran gdb.gdb gdb.hp \
- gdb.java gdb.mi gdb.modula2 gdb.multi \
+ gdb.java gdb.linespec gdb.mi gdb.modula2 gdb.multi \
gdb.objc gdb.opencl gdb.opt gdb.pascal gdb.python gdb.server \
gdb.stabs gdb.reverse gdb.threads gdb.trace gdb.xml \
$(SUBDIRS)
diff --git a/gdb/testsuite/configure b/gdb/testsuite/configure
index 82206b3..fb70b3d 100755
--- a/gdb/testsuite/configure
+++ b/gdb/testsuite/configure
@@ -3448,7 +3448,7 @@ done
-ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
+ac_config_files="$ac_config_files Makefile gdb.ada/Makefile gdb.arch/Makefile gdb.asm/Makefile gdb.base/Makefile gdb.cell/Makefile gdb.cp/Makefile gdb.disasm/Makefile gdb.dwarf2/Makefile gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile gdb.threads/Makefile gdb.trace/Makefile gdb.xml/Makefile"
cat >confcache <<\_ACEOF
# This file is a shell script that caches the results of configure
@@ -4166,6 +4166,7 @@ do
"gdb.hp/gdb.aCC/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/gdb.aCC/Makefile" ;;
"gdb.hp/gdb.compat/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/gdb.compat/Makefile" ;;
"gdb.hp/gdb.defects/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.hp/gdb.defects/Makefile" ;;
+ "gdb.linespec/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.linespec/Makefile" ;;
"gdb.mi/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.mi/Makefile" ;;
"gdb.modula2/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.modula2/Makefile" ;;
"gdb.multi/Makefile") CONFIG_FILES="$CONFIG_FILES gdb.multi/Makefile" ;;
diff --git a/gdb/testsuite/configure.ac b/gdb/testsuite/configure.ac
index 8631442..121fd37 100644
--- a/gdb/testsuite/configure.ac
+++ b/gdb/testsuite/configure.ac
@@ -95,7 +95,7 @@ AC_OUTPUT([Makefile \
gdb.fortran/Makefile gdb.server/Makefile gdb.java/Makefile \
gdb.hp/Makefile gdb.hp/gdb.objdbg/Makefile gdb.hp/gdb.base-hp/Makefile \
gdb.hp/gdb.aCC/Makefile gdb.hp/gdb.compat/Makefile \
- gdb.hp/gdb.defects/Makefile \
+ gdb.hp/gdb.defects/Makefile gdb.linespec/Makefile \
gdb.mi/Makefile gdb.modula2/Makefile gdb.multi/Makefile \
gdb.objc/Makefile gdb.opencl/Makefile gdb.opt/Makefile gdb.pascal/Makefile \
gdb.python/Makefile gdb.reverse/Makefile gdb.stabs/Makefile \
diff --git a/gdb/testsuite/gdb.base/break.exp b/gdb/testsuite/gdb.base/break.exp
index 92fcc69..c5885ba 100644
--- a/gdb/testsuite/gdb.base/break.exp
+++ b/gdb/testsuite/gdb.base/break.exp
@@ -540,8 +540,9 @@ gdb_test_multiple "catch exec" "$name" {
# Verify that GDB responds gracefully when asked to set a breakpoint
# on a nonexistent source line.
#
+gdb_test_no_output "set breakpoint pending off"
gdb_test "break 999" \
- "No line 999 in file .*" \
+ "No line 999 in the current file." \
"break on non-existent source line"
# Run to the desired default location. If not positioned here, the
diff --git a/gdb/testsuite/gdb.base/list.exp b/gdb/testsuite/gdb.base/list.exp
index 5b9fe15..d4935ee 100644
--- a/gdb/testsuite/gdb.base/list.exp
+++ b/gdb/testsuite/gdb.base/list.exp
@@ -489,7 +489,7 @@ proc test_list_filename_and_function {} {
gdb_test "list foobar.c:main" "No source file named foobar.c.|Location not found" "list filename:function; nonexistant file"
- gdb_test "list list0.h:foobar" "Function \"foobar\" not defined.|Location not found" "list filename:function; nonexistant function"
+ gdb_test "list list0.h:foobar" "Function \"foobar\" not defined in \"list0.h\"." "list filename:function; nonexistant function"
}
diff --git a/gdb/testsuite/gdb.base/sepdebug.exp b/gdb/testsuite/gdb.base/sepdebug.exp
index 1a9072d..bb0b914 100644
--- a/gdb/testsuite/gdb.base/sepdebug.exp
+++ b/gdb/testsuite/gdb.base/sepdebug.exp
@@ -337,7 +337,8 @@ gdb_test_multiple "catch exec" $name {
# on a nonexistent source line.
#
-gdb_test "break 999" "No line 999 in file .*" \
+gdb_test_no_output "set breakpoint pending off"
+gdb_test "break 999" "No line 999 in the current file." \
"break on non-existent source line"
# Run to the desired default location. If not positioned here, the
diff --git a/gdb/testsuite/gdb.base/solib-symbol.exp b/gdb/testsuite/gdb.base/solib-symbol.exp
index aa723c6..d402ebb 100644
--- a/gdb/testsuite/gdb.base/solib-symbol.exp
+++ b/gdb/testsuite/gdb.base/solib-symbol.exp
@@ -46,11 +46,6 @@ gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
gdb_load_shlibs $binfile_lib
-if ![runto_main] then {
- fail "Can't run to main"
- return 0
-}
-
# Set a breakpoint in the binary.
gdb_test "br foo2" \
"Breakpoint.*file.*${testfile}\\.c.*" \
@@ -58,6 +53,11 @@ gdb_test "br foo2" \
delete_breakpoints
+if ![runto_main] then {
+ fail "Can't run to main"
+ return 0
+}
+
# Break in the library.
gdb_test "br foo" \
"Breakpoint.*file.*${libname}\\.c.*" \
@@ -67,9 +67,9 @@ gdb_test "continue" \
"Continuing.*" \
"continue"
-# This symbol is now looked up in the ELF library.
+# This symbol is now looked up in the ELF library and the binary.
gdb_test "br foo2" \
- "Breakpoint.*file.*${libname}\\.c.*" \
+ "Breakpoint.*: foo2. .2 locations..*" \
"foo2 in mdlib"
gdb_exit
diff --git a/gdb/testsuite/gdb.base/solib-weak.exp b/gdb/testsuite/gdb.base/solib-weak.exp
index 1f23aa2..52fd72d 100644
--- a/gdb/testsuite/gdb.base/solib-weak.exp
+++ b/gdb/testsuite/gdb.base/solib-weak.exp
@@ -101,15 +101,6 @@ proc do_test { lib1opts lib2opts lib1first } {
gdb_breakpoint "bar"
- # If the library which will be used is compiled without debugging
- # information, GDB will pick the wrong copy of "bar", i.e. the one
- # with debugging information.
-
- if {(${lib1opts} == "" && ${lib2opts} != "" && ${lib1first} == 1)
- || (${lib1opts} != "" && ${lib2opts} == "" && ${lib1first} == 0)} {
- setup_kfail gdb/1824 *-*-*
- }
-
gdb_test "continue" "Breakpoint .* \\.?bar .*${expected_file}\\..*" \
"run to breakpoint - $testopts"
}
diff --git a/gdb/testsuite/gdb.cp/mb-ctor.exp b/gdb/testsuite/gdb.cp/mb-ctor.exp
index 6a99175..0438424 100644
--- a/gdb/testsuite/gdb.cp/mb-ctor.exp
+++ b/gdb/testsuite/gdb.cp/mb-ctor.exp
@@ -50,13 +50,13 @@ if ![runto_main] then {
# and a condition.
gdb_test "break 'Derived::Derived(int)'" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: Derived::Derived.int.. \\(2 locations\\).*" \
"set-breakpoint at ctor"
gdb_breakpoint [gdb_get_line_number "set breakpoint here"]
gdb_test "break 'Derived::~Derived()'" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: Derived::~Derived... \\(2 locations\\).*" \
"set-breakpoint at dtor"
gdb_test "continue" \
diff --git a/gdb/testsuite/gdb.cp/mb-inline.exp b/gdb/testsuite/gdb.cp/mb-inline.exp
index d670b56..05b378c 100644
--- a/gdb/testsuite/gdb.cp/mb-inline.exp
+++ b/gdb/testsuite/gdb.cp/mb-inline.exp
@@ -62,7 +62,7 @@ set bp_location [gdb_get_line_number "set breakpoint here" $hdrfile]
# Set a breakpoint with multiple locations.
gdb_test "break $hdrfile:$bp_location" \
- "Breakpoint.*at.* file .*$hdrfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $hdrfile:$bp_location. \\(2 locations\\).*" \
"set breakpoint"
gdb_run_cmd
@@ -128,7 +128,7 @@ if { ![runto_main] } {
}
gdb_test "break $hdrfile:$bp_location" \
- "Breakpoint.*at.* file .*$hdrfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $hdrfile:$bp_location. \\(2 locations\\).*" \
"set multi_line_foo breakpoint"
gdb_test "continue" \
".*Breakpoint.*multi_line_foo \\(i=0\\).*" \
diff --git a/gdb/testsuite/gdb.cp/mb-templates.exp b/gdb/testsuite/gdb.cp/mb-templates.exp
index 80c080b..933d690 100644
--- a/gdb/testsuite/gdb.cp/mb-templates.exp
+++ b/gdb/testsuite/gdb.cp/mb-templates.exp
@@ -52,7 +52,7 @@ set bp_location [gdb_get_line_number "set breakpoint here"]
# and a condition.
gdb_test "break $srcfile:$bp_location if i==1" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $srcfile:$bp_location. \\(2 locations\\).*" \
"initial condition: set breakpoint"
gdb_run_cmd
@@ -80,7 +80,7 @@ gdb_reinitialize_dir $srcdir/$subdir
gdb_load ${binfile}
gdb_test "break $srcfile:$bp_location" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $srcfile:$bp_location. \\(2 locations\\).*" \
"separate condition: set breakpoint"
gdb_test_no_output "condition 1 i==1" \
@@ -177,7 +177,7 @@ if { ![runto_main] } {
}
gdb_test "break $srcfile:$bp_location" \
- "Breakpoint.*at.* file .*$srcfile, line.*\\(2 locations\\).*" \
+ "Breakpoint.*at.*: $srcfile:$bp_location. \\(2 locations\\).*" \
"set multi_line_foo breakpoint"
gdb_test "continue" \
".*Breakpoint.*multi_line_foo<int> \\(i=0\\).*" \
diff --git a/gdb/testsuite/gdb.cp/method2.exp b/gdb/testsuite/gdb.cp/method2.exp
index 2fa4169..cc68891 100644
--- a/gdb/testsuite/gdb.cp/method2.exp
+++ b/gdb/testsuite/gdb.cp/method2.exp
@@ -51,7 +51,7 @@ proc test_break { lang } {
"setting language $lang"
gdb_test_multiple "break A::method" "breaking in method ($lang)" {
- -re ".0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. A::method\\(A\\*\\) at .*\[\r\n\]*.3. A::method\\(int\\) at .*\[\r\n\]*\[\r\n\]*.4. A::method\\(\\) at .*\[\r\n\]*> $" {
+ -re ".0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. .*:A::method\\(A\\*\\):\[0-9\]+\[\r\n\]*.3. .*:A::method\\(int\\):\[0-9\]+\[\r\n\]*.4. .*:A::method\\(\\):\[0-9\]+\[\r\n\]*> $" {
gdb_test "0" \
"canceled" \
"breaking in method ($lang)"
diff --git a/gdb/testsuite/gdb.cp/ovldbreak.exp b/gdb/testsuite/gdb.cp/ovldbreak.exp
index f5d4051..9996728 100644
--- a/gdb/testsuite/gdb.cp/ovldbreak.exp
+++ b/gdb/testsuite/gdb.cp/ovldbreak.exp
@@ -130,18 +130,18 @@ proc set_bp_overloaded {name expectedmenu mychoice bpnumber linenumber} {
set menu_overload1arg "\\\[0\\\] cancel\r\n"
append menu_overload1arg "\\\[1\\\] all\r\n"
-append menu_overload1arg "\\\[2\\\] foo::overload1arg\\(double\\) at.*$srcfile:121\r\n"
-append menu_overload1arg "\\\[3\\\] foo::overload1arg\\(float\\) at.*$srcfile:120\r\n"
-append menu_overload1arg "\\\[4\\\] foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r\n"
-append menu_overload1arg "\\\[5\\\] foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r\n"
-append menu_overload1arg "\\\[6\\\] foo::overload1arg\\((unsigned int|unsigned)\\) at.*$srcfile:117\r\n"
-append menu_overload1arg "\\\[7\\\] foo::overload1arg\\(int\\) at.*$srcfile:116\r\n"
-append menu_overload1arg "\\\[8\\\] foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r\n"
-append menu_overload1arg "\\\[9\\\] foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r\n"
-append menu_overload1arg "\\\[10\\\] foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r\n"
-append menu_overload1arg "\\\[11\\\] foo::overload1arg\\(signed char\\) at.*$srcfile:112\r\n"
-append menu_overload1arg "\\\[12\\\] foo::overload1arg\\(char\\) at.*$srcfile:111\r\n"
-append menu_overload1arg "\\\[13\\\] foo::overload1arg\\((void|)\\) at.*$srcfile:110\r\n"
+append menu_overload1arg "\\\[2\\\] .*$srcfile:foo::overload1arg\\(double\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[3\\\] .*$srcfile:foo::overload1arg\\(float\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[4\\\] .*$srcfile:foo::overload1arg\\((unsigned long|long unsigned)( int)?\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[5\\\] .*$srcfile:foo::overload1arg\\(long( int)?\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[6\\\] .*$srcfile:foo::overload1arg\\((unsigned int|unsigned)\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[7\\\] .*$srcfile:foo::overload1arg\\(int\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[8\\\] .*$srcfile:foo::overload1arg\\((unsigned short|short unsigned)( int)?\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[9\\\] .*$srcfile:foo::overload1arg\\(short( int)?\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[10\\\] .*$srcfile:foo::overload1arg\\(unsigned char\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[11\\\] .*$srcfile:foo::overload1arg\\(signed char\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[12\\\] .*$srcfile:foo::overload1arg\\(char\\):\[0-9\]+\r\n"
+append menu_overload1arg "\\\[13\\\] .*$srcfile:foo::overload1arg\\((void|)\\):\[0-9\]+\r\n"
append menu_overload1arg "> $"
# Set multiple-symbols to "ask", to allow us to test the use
@@ -279,7 +279,7 @@ gdb_expect {
# Choose all.
send_gdb "1\n"
gdb_expect {
- -re "Breakpoint $decimal at $hex: file.*$srcfile, line 121.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 120.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 119.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 118.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 117.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 116.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 115.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 114.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 113.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 112.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 111.\r\nBreakpoint $decimal at $hex: file.*$srcfile, line 110.\r\nwarning: Multiple breakpoints were set.\r\nUse the .delete. command to delete unwanted breakpoints.\r\n$gdb_prompt $" {
+ -re "Breakpoint $decimal at $hex: foo::overload1arg. .12 locations.\r\n.*$gdb_prompt $" {
pass "set bp on overload1arg all"
}
-re ".*$gdb_prompt $" {
@@ -306,18 +306,19 @@ gdb_expect {
gdb_test "info break" \
"Num Type\[\t \]+Disp Enb Address\[\t \]+What.*
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
-\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((void|)\\) at.*$srcfile:110" \
+\[0-9\]+\[\t \]+breakpoint keep y\[\t \]+<MULTIPLE>\[\t \]*\r
+\[0-9\]+.1\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(double\\) at.*$srcfile:121\r
+\[0-9\]+.2\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(float\\) at.*$srcfile:120\r
+\[0-9\]+.3\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned long|long unsigned)( int)?\\) at.*$srcfile:119\r
+\[0-9\]+.4\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(long( int)?\\) at.*$srcfile:118\r
+\[0-9\]+.5\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned|unsigned int)\\) at.*$srcfile:117\r
+\[0-9\]+.6\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(int\\) at.*$srcfile:116\r
+\[0-9\]+.7\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((unsigned short|short unsigned)( int)?\\) at.*$srcfile:115\r
+\[0-9\]+.8\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(short( int)?\\) at.*$srcfile:114\r
+\[0-9\]+.9\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(unsigned char\\) at.*$srcfile:113\r
+\[0-9\]+.10\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(signed char\\) at.*$srcfile:112\r
+\[0-9\]+.11\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\(char\\) at.*$srcfile:111\r
+\[0-9\]+.12\[\t \]+y\[\t \]+$hex\[\t \]+in foo::overload1arg\\((void|)\\) at.*$srcfile:110" \
"breakpoint info (after setting on all)"
@@ -333,10 +334,10 @@ proc continue_to_bp_overloaded {might_kfail bpnumber argtype actuals} {
send_gdb "continue\n"
gdb_expect {
- -re "Continuing.\r\n\r\nBreakpoint ${bpnumber}, (${hex} in )?foo::overload1arg(\\(${argtype}\\))? \\(this=${hex}(, )?${actuals}\\) at.*${srcfile}:${decimal}\r\n${decimal}\[\t \]+int foo::overload1arg \\(${argtype}( arg)?\\).*\r\n.*$gdb_prompt $" {
+ -re "Continuing.\r\n\r\nBreakpoint ${bpnumber}, foo::overload1arg \\(this=${hex}(, )?${actuals}\\) at.*${srcfile}:${decimal}\r\n${decimal}\[\t \]+int foo::overload1arg \\(${argtype}( arg)?\\).*\r\n.*$gdb_prompt $" {
pass "continue to bp overloaded : ${argtype}"
}
- -re "Continuing.\r\n\r\nBreakpoint ${bpnumber}, (${hex} in )?foo::overload1arg(\\(${argtype}\\))? \\(this=${hex}, arg=.*\\) at.*${srcfile}:${decimal}\r\n${decimal}\[\t \]+int foo::overload1arg \\(${argtype}( arg)?\\).*\r\n.*$gdb_prompt $" {
+ -re "Continuing.\r\n\r\nBreakpoint ${bpnumber}, foo::overload1arg \\(this=${hex}, arg=.*\\) at.*${srcfile}:${decimal}\r\n${decimal}\[\t \]+int foo::overload1arg \\(${argtype}( arg)?\\).*\r\n.*$gdb_prompt $" {
if $might_kfail {
kfail "gdb/1025" "continue to bp overloaded : ${argtype}"
} else {
@@ -352,17 +353,17 @@ proc continue_to_bp_overloaded {might_kfail bpnumber argtype actuals} {
}
}
-continue_to_bp_overloaded 0 25 "(void|)" ""
-continue_to_bp_overloaded 1 24 "char" "arg=2 \\'\\\\002\\'"
-continue_to_bp_overloaded 1 23 "signed char" "arg=3 \\'\\\\003\\'"
-continue_to_bp_overloaded 1 22 "unsigned char" "arg=4 \\'\\\\004\\'"
-continue_to_bp_overloaded 1 21 "short" "arg=5"
-continue_to_bp_overloaded 1 20 "unsigned short" "arg=6"
-continue_to_bp_overloaded 0 19 "int" "arg=7"
-continue_to_bp_overloaded 0 18 "(unsigned|unsigned int)" "arg=8"
-continue_to_bp_overloaded 0 17 "long" "arg=9"
-continue_to_bp_overloaded 0 16 "unsigned long" "arg=10"
-continue_to_bp_overloaded 0 15 "float" "arg=100"
+continue_to_bp_overloaded 0 14 "(void|)" ""
+continue_to_bp_overloaded 1 14 "char" "arg=2 \\'\\\\002\\'"
+continue_to_bp_overloaded 1 14 "signed char" "arg=3 \\'\\\\003\\'"
+continue_to_bp_overloaded 1 14 "unsigned char" "arg=4 \\'\\\\004\\'"
+continue_to_bp_overloaded 1 14 "short" "arg=5"
+continue_to_bp_overloaded 1 14 "unsigned short" "arg=6"
+continue_to_bp_overloaded 0 14 "int" "arg=7"
+continue_to_bp_overloaded 0 14 "(unsigned|unsigned int)" "arg=8"
+continue_to_bp_overloaded 0 14 "long" "arg=9"
+continue_to_bp_overloaded 0 14 "unsigned long" "arg=10"
+continue_to_bp_overloaded 0 14 "float" "arg=100"
continue_to_bp_overloaded 1 14 "double" "arg=200"
# Test breaking on an overloaded function when multiple-symbols
@@ -375,7 +376,7 @@ gdb_test "break foo::foofunc" \
# is set to "all"
gdb_test_no_output "set multiple-symbols all"
gdb_test "break foo::foofunc" \
- "Breakpoint \[0-9\]+ at ${hex}: file .*ovldbreak\\.cc, line \[0-9\]+\\.\r\nBreakpoint \[0-9\]+ at ${hex}: file .*ovldbreak\\.cc, line \[0-9\]+\\.\r\nwarning: Multiple breakpoints were set\\.\r\nUse the \"delete\" command to delete unwanted breakpoints\\."
+ "Breakpoint \[0-9\]+ at ${hex}: foo::foofunc. .2 locations..*"
# That's all, folks.
diff --git a/gdb/testsuite/gdb.cp/ovsrch.exp b/gdb/testsuite/gdb.cp/ovsrch.exp
index b509a25..f6ad34b 100644
--- a/gdb/testsuite/gdb.cp/ovsrch.exp
+++ b/gdb/testsuite/gdb.cp/ovsrch.exp
@@ -49,7 +49,7 @@ proc test_class {class} {
# Test whether open parentheses are correctly identified as overload
# information or conditional.
- gdb_test "break ${class}::foo if (a == 3)" "Breakpoint (\[0-9\]).*"
+ gdb_test "break ${class}::hibob if (a_param == 3)" "Breakpoint (\[0-9\]).*"
}
if { [skip_cplus_tests] } { continue }
@@ -73,28 +73,28 @@ if {![runto_main]} {
}
# Break in A::stop_here and run tests.
-if {[gdb_breakpoint "stop_here"]} {
- pass "break stop_here"
+if {[gdb_breakpoint "A::stop_here"]} {
+ pass "break A::stop_here"
}
-if {[gdb_breakpoint "'stop_here'"]} {
- pass "break 'stop_here'"
+if {[gdb_breakpoint "'A::stop_here'"]} {
+ pass "break 'A::stop_here'"
}
gdb_continue_to_breakpoint "stop_here"
-test_class outer
+test_class A::outer
# Break in A::B::stop_here_too and run tests.
-if {[gdb_breakpoint "B::stop_here_too"]} {
- pass "break B::stop_here_too"
+if {[gdb_breakpoint "A::B::stop_here_too"]} {
+ pass "break A::B::stop_here_too"
}
-if {[gdb_breakpoint "'B::stop_here_too'"]} {
- pass "break 'B::stop_here_too'"
+if {[gdb_breakpoint "'A::B::stop_here_too'"]} {
+ pass "break 'A::B::stop_here_too'"
}
gdb_continue_to_breakpoint "stop_here_too"
-test_class inner
+test_class A::B::inner
gdb_exit
return 0
diff --git a/gdb/testsuite/gdb.cp/ovsrch.h b/gdb/testsuite/gdb.cp/ovsrch.h
index b2e518d..983b51e 100644
--- a/gdb/testsuite/gdb.cp/ovsrch.h
+++ b/gdb/testsuite/gdb.cp/ovsrch.h
@@ -24,6 +24,8 @@ namespace A
void foo (int) const;
void foo (char *) const;
bool func (void) { return true; }
+ void hibob (int) const;
+ void hibob (char *) const;
};
namespace B
@@ -34,6 +36,8 @@ namespace A
void foo (void) const;
void foo (int) const;
void foo (char *) const;
+ void hibob (int) const;
+ void hibob (char *) const;
};
}
}
diff --git a/gdb/testsuite/gdb.cp/ovsrch3.cc b/gdb/testsuite/gdb.cp/ovsrch3.cc
index e6e38a4..a7d9551 100644
--- a/gdb/testsuite/gdb.cp/ovsrch3.cc
+++ b/gdb/testsuite/gdb.cp/ovsrch3.cc
@@ -18,11 +18,21 @@
#include "ovsrch.h"
void
-A::outer::foo (int a) const
+A::outer::foo (int a_param) const
{
}
void
-A::B::inner::foo (int a) const
+A::B::inner::foo (int a_param) const
+{
+}
+
+void
+A::outer::hibob (int a_param) const
+{
+}
+
+void
+A::B::inner::hibob (int a_param) const
{
}
diff --git a/gdb/testsuite/gdb.cp/ovsrch4.cc b/gdb/testsuite/gdb.cp/ovsrch4.cc
index 2f0c1a6..5bb08b3 100644
--- a/gdb/testsuite/gdb.cp/ovsrch4.cc
+++ b/gdb/testsuite/gdb.cp/ovsrch4.cc
@@ -18,11 +18,21 @@
#include "ovsrch.h"
void
-A::outer::foo (char *a) const
+A::outer::foo (char *a_param) const
{
}
void
-A::B::inner::foo (char *a) const
+A::B::inner::foo (char *a_param) const
+{
+}
+
+void
+A::outer::hibob (char *a_param) const
+{
+}
+
+void
+A::B::inner::hibob (char *a_param) const
{
}
diff --git a/gdb/testsuite/gdb.cp/re-set-overloaded.exp b/gdb/testsuite/gdb.cp/re-set-overloaded.exp
index 2052552..bd5f3ba 100644
--- a/gdb/testsuite/gdb.cp/re-set-overloaded.exp
+++ b/gdb/testsuite/gdb.cp/re-set-overloaded.exp
@@ -46,7 +46,6 @@ gdb_test_no_output {set variable $brk = $bpnum}
# runto or runto_main would call delete_breakpoints.
gdb_breakpoint "main"
gdb_run_cmd
-setup_kfail breakpoints/11657 *-*-*
gdb_test "" ".*" "start"
set test "breakpoint resolved"
diff --git a/gdb/testsuite/gdb.cp/templates.exp b/gdb/testsuite/gdb.cp/templates.exp
index 6612b4a..5f848c9 100644
--- a/gdb/testsuite/gdb.cp/templates.exp
+++ b/gdb/testsuite/gdb.cp/templates.exp
@@ -109,12 +109,7 @@ proc test_template_breakpoints {} {
global hp_aCC_compiler
gdb_test_multiple "break T5<int>::T5" "constructor breakpoint" {
- -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2. T5<int>::T5\\(int\\) at .*\[\r\n\]*.3. T5<int>::T5\\((T5<int> const|const T5<int>) ?&\\) at .*\[\r\n\]*> $" {
- gdb_test "0" \
- "canceled" \
- "constructor breakpoint (obsolete format!)"
- }
- -re ".0. cancel\[\r\n\]*.1. all\[\r\n\]*.2. T5<int>::T5\\((T5<int> const|const T5<int>) ?&\\) at .*templates.cc:.*\[\r\n\]*.3. T5<int>::T5\\(int\\) at .*templates.cc:.*\[\r\n\]*> $" {
+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2.*templates.cc:T5<int>::T5\\((T5<int> const|const T5<int>) ?&\\):\[0-9\]+\[\r\n\]*.3.*templates.cc:T5<int>::T5\\(int\\):\[0-9\]+\[\r\n\]*> $" {
gdb_test "0" \
"canceled" \
"constructor breakpoint"
@@ -152,9 +147,26 @@ proc test_template_breakpoints {} {
set bp_location [gdb_get_line_number \
"set breakpoint on a line with no real code"]
- gdb_test "break ${testfile}.cc:${bp_location}" \
- "Breakpoint.*at.* file .*${testfile}.cc, line.*(2 locations).*" \
- "breakpoint on a line with no real code"
+
+ gdb_test_multiple "break ${testfile}.cc:${bp_location}" \
+ "breakpoint on a line with no real code" {
+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2.*templates.cc:GetMax<int>\\(int, int\\):\[0-9\]+\[\r\n\]*.3.*templates.cc:GetMax<long>\\(long, long\\):\[0-9\]+\[\r\n\]*> $" {
+ gdb_test "0" \
+ "canceled" \
+ "breakpoint on a line with no real code"
+ }
+ -re "0. cancel.*\[\r\n\]*.1. all.*\[\r\n\]*.2.*\[\r\n\]*.3.*\[\r\n\]*> $" {
+ gdb_test "0" \
+ "nonsense intended to insure that this test fails" \
+ "breakpoint on a line with no real code"
+ }
+ -re ".*\n> $" {
+ gdb_test "0" \
+ "nonsense intended to insure that this test fails" \
+ "breakpoint on a line with no real code"
+ }
+ }
+
delete_breakpoints
}
@@ -168,7 +180,7 @@ proc test_template_calls {} {
if [target_info exists gdb,cannot_call_functions] {
setup_xfail "*-*-*" 2416
- fail "This target can not call functions"
+fail "This target can not call functions"
return
}
diff --git a/gdb/testsuite/gdb.linespec/Makefile.in b/gdb/testsuite/gdb.linespec/Makefile.in
new file mode 100644
index 0000000..2658a24
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/Makefile.in
@@ -0,0 +1,14 @@
+VPATH = @srcdir@
+srcdir = @srcdir@
+
+EXECUTABLES = lspec
+
+all info install-info dvi install uninstall installcheck check:
+ @echo "Nothing to be done for $@..."
+
+clean mostlyclean:
+ -rm -f *~ *.o *.ci
+ -rm -f core $(EXECUTABLES)
+
+distclean maintainer-clean realclean: clean
+ -rm -f Makefile config.status config.log gdb.log gdb.sum
diff --git a/gdb/testsuite/gdb.linespec/base/one/thefile.cc b/gdb/testsuite/gdb.linespec/base/one/thefile.cc
new file mode 100644
index 0000000..f8712c2
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/base/one/thefile.cc
@@ -0,0 +1,20 @@
+/* The commented line must have the same line number in the other
+ "thefile.c". */
+
+#define WANT_F1
+#include "../../lspec.h"
+
+
+
+
+
+
+int m(int x)
+{
+ return x + 23; /* thefile breakpoint */
+}
+
+int NameSpace::overload(int x)
+{
+ return x + 23;
+}
diff --git a/gdb/testsuite/gdb.linespec/base/two/thefile.cc b/gdb/testsuite/gdb.linespec/base/two/thefile.cc
new file mode 100644
index 0000000..ffca87a
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/base/two/thefile.cc
@@ -0,0 +1,20 @@
+/* The commented line must have the same line number in the other
+ "thefile.c". */
+
+#define WANT_F2
+#include "../../lspec.h"
+
+static int dupname(int y)
+{
+ label: return y;
+}
+
+int n(int y)
+{
+ return dupname(y) - 23; /* thefile breakpoint */
+}
+
+int NameSpace::overload(double x)
+{
+ return (int) x - 23;
+}
diff --git a/gdb/testsuite/gdb.linespec/body.h b/gdb/testsuite/gdb.linespec/body.h
new file mode 100644
index 0000000..e8765f6
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/body.h
@@ -0,0 +1,5 @@
+/* This is included directly into the body of a function. */
+
+/* body breakpoint no code */
+
+return x;
diff --git a/gdb/testsuite/gdb.linespec/linespec.exp b/gdb/testsuite/gdb.linespec/linespec.exp
new file mode 100644
index 0000000..440233a
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/linespec.exp
@@ -0,0 +1,117 @@
+# Copyright 2011 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/>.
+
+# Tests of ambiguous linespecs.
+
+set testfile linespec
+
+set exefile lspec
+set binfile ${objdir}/${subdir}/${exefile}
+
+set baseone base/one/thefile.cc
+set basetwo base/two/thefile.cc
+
+if {[skip_cplus_tests]} {
+ unsupported linespec.exp
+ return
+}
+
+if {[prepare_for_testing ${testfile}.exp $exefile \
+ [list lspec.cc $baseone $basetwo] \
+ {debug nowarnings}]} {
+ return -1
+}
+
+gdb_test_no_output "set multiple-symbols all" \
+ "set multiple-symbols to all for linespec tests"
+
+set l1 [gdb_get_line_number "thefile breakpoint" $baseone]
+set l2 [gdb_get_line_number "thefile breakpoint" $basetwo]
+
+if {$l1 != $l2} {
+ error "somebody incompatibly modified the source files needed by linespec.exp"
+}
+
+gdb_test "break thefile.cc:$l1" \
+ "Breakpoint 1 at $hex: thefile.cc:$l1. \[(\]2 locations\[)\]" \
+ "multi-location break using file:line"
+
+# We'd like this to work, but it currently does not.
+# gdb_test "break one/thefile.cc:$l1"
+
+gdb_test "break dupname" \
+ "Breakpoint 2 at $hex: dupname. \[(\]2 locations\[)\]" \
+ "multi-location break using duplicate function name"
+
+gdb_test "break dupname:label" \
+ "Breakpoint 3 at $hex: dupname:label. \[(\]2 locations\[)\]" \
+ "multi-location break using duplicate function name and label"
+
+gdb_test_no_output "set breakpoint pending off" \
+ "disable pending breakpoints for linespec tests"
+
+# This is PR breakpoints/12856.
+gdb_test "break lspec.cc:nosuchfunction" \
+ "Function \"nosuchfunction\" not defined in \"lspec.cc\"." \
+ "set breakpoint on non-existent function"
+
+gdb_test "break NameSpace::overload" \
+ "Breakpoint \[0-9\]+ at $hex: NameSpace::overload. \[(\]3 locations\[)\]" \
+ "set breakpoint at all instances of NameSpace::overload"
+
+gdb_test "break lspec.cc:NameSpace::overload" \
+ "Breakpoint \[0-9\]+ at $hex: file .*lspec.cc, line 7." \
+ "set breakpoint at lspec.cc instance of NameSpace::overload"
+
+gdb_test "break lspec.cc:NameSpace::overload(double)" \
+ "Function \"NameSpace::overload\\(double\\)\" not defined in \"lspec.cc\"." \
+ "set breakpoint at non-existent lspec.cc instance of NameSpace::overload"
+
+gdb_test "break NameSpace::overload()" \
+ "Breakpoint \[0-9\]+ at $hex: file .*lspec.cc, line 7." \
+ "set breakpoint at specific instance of NameSpace::overload"
+
+# This should manage to set a breakpoint even though body.h does not
+# include all of the function in question.
+set line [gdb_get_line_number "body breakpoint no code" body.h]
+gdb_test "break body.h:$line" \
+ "Breakpoint \[0-9\]+.*" \
+ "set breakpoint in body.h"
+
+# This should only have a single location -- in f1.
+set line [gdb_get_line_number "f1 breakpoint" lspec.h]
+gdb_test "break lspec.h:$line" \
+ "Breakpoint \[0-9\]+ at $hex: file .*lspec.h, line $line." \
+ "set breakpoint in f1"
+
+#
+# Multi-inferior tests.
+#
+
+gdb_test "add-inferior" "Added inferior 2" \
+ "add inferior for linespec tests"
+
+gdb_test "inferior 2" "Switching to inferior 2 .*" \
+ "switch to inferior 2 for linespec tests"
+
+# Note that in particular this should not cause errors when re-setting
+# breakpoints.
+gdb_test "file $binfile" \
+ "Reading symbols from .*done." \
+ "set the new inferior file for linespec tests"
+
+gdb_test "break main" \
+ "Breakpoint \[0-9\]+ at $hex: main. .2 locations." \
+ "set breakpoint at main in both inferiors"
diff --git a/gdb/testsuite/gdb.linespec/lspec.cc b/gdb/testsuite/gdb.linespec/lspec.cc
new file mode 100644
index 0000000..b1092e2
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/lspec.cc
@@ -0,0 +1,19 @@
+#include "lspec.h"
+
+static int dupname (int x) { label: return x; }
+
+int NameSpace::overload()
+{
+ return 23;
+}
+
+int body_elsewhere()
+{
+ int x = 5;
+#include "body.h"
+}
+
+int main()
+{
+ return dupname(0) + m(0) + n(0) + f1() + f2() + body_elsewhere();
+}
diff --git a/gdb/testsuite/gdb.linespec/lspec.h b/gdb/testsuite/gdb.linespec/lspec.h
new file mode 100644
index 0000000..0a647fa
--- /dev/null
+++ b/gdb/testsuite/gdb.linespec/lspec.h
@@ -0,0 +1,26 @@
+extern int m(int x);
+extern int n(int y);
+
+namespace NameSpace {
+ int overload ();
+ int overload (int);
+ int overload (double);
+};
+
+#ifdef WANT_F1
+int f1(void)
+{
+ return 1; /* f1 breakpoint */
+}
+#else
+extern int f1(void);
+#endif
+
+#ifdef WANT_F2
+int f2(void)
+{
+ return 1; /* f2 breakpoint */
+}
+#else
+extern int f2(void);
+#endif
diff --git a/gdb/testsuite/gdb.objc/objcdecode.exp b/gdb/testsuite/gdb.objc/objcdecode.exp
index 720bfd8..881f090 100644
--- a/gdb/testsuite/gdb.objc/objcdecode.exp
+++ b/gdb/testsuite/gdb.objc/objcdecode.exp
@@ -52,17 +52,19 @@ proc do_objc_tests {} {
do_objc_tests
+gdb_test_no_output "set multiple-symbols ask"
+
#
# Break on multiply defined method (PR objc/1236)
#
set name "break on multiply defined method"
gdb_test_multiple "break multipleDef" $name \
{
- -re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] -.Decode multipleDef. at .*\r\n\\\[3\\\] multipleDef at .*\r\n> $" {
+ -re "\\\[0\\\] cancel\r\n\\\[1\\\] all\r\n\\\[2\\\] .*${srcfile}:-.Decode multipleDef.:\[0-9\]+\r\n\\\[3\\\] .*${srcfile}:multipleDef:\[0-9\]+\r\n> $" {
send_gdb "3\n"
exp_continue
}
- -re "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*\r\n$gdb_prompt $" { pass $name }
+ -re "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: .*\r\n$gdb_prompt $" { pass $name }
-re ".*$gdb_prompt $" { kfail "gdb/1236" $name }
}
diff --git a/gdb/testsuite/gdb.trace/tracecmd.exp b/gdb/testsuite/gdb.trace/tracecmd.exp
index 679cc32..89a2e24 100644
--- a/gdb/testsuite/gdb.trace/tracecmd.exp
+++ b/gdb/testsuite/gdb.trace/tracecmd.exp
@@ -74,6 +74,7 @@ gdb_test "info trace" "in gdb_recursion_test.*$srcfile:$testline2" \
# 1.2 trace invalid source line
gdb_delete_tracepoints
+gdb_test_no_output "set breakpoint pending off"
gdb_test "trace $srcfile:99999" "No line 99999 in file \".*$srcfile\"." \
"1.2a: trace invalid line in sourcefile"
gdb_test "info trace" "No tracepoints.*" \
@@ -81,7 +82,6 @@ gdb_test "info trace" "No tracepoints.*" \
# 1.3 trace line in invalid source file
gdb_delete_tracepoints
-gdb_test_no_output "set breakpoint pending off"
gdb_test "trace NoSuChFiLe.c:1" "No source file named NoSuChFiLe.c." \
"1.3a: trace invalid source file"
gdb_test "info trace" "No tracepoints.*" \
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index a2e2cd4..e00538c 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -2456,7 +2456,7 @@ trace_find_line_command (char *args, int from_tty)
}
else
{
- sals = decode_line_spec (args, 1);
+ sals = decode_line_spec (args, DECODE_LINE_FUNFIRSTLINE);
sal = sals.sals[0];
}
@@ -2584,7 +2584,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, DECODE_LINE_FUNFIRSTLINE, NULL, 0);
if (sals.nelts == 0)
return; /* Presumably decode_line_1 has already warned. */
diff --git a/gdb/tui/tui-winsource.c b/gdb/tui/tui-winsource.c
index 4c8658d..9b936e1 100644
--- a/gdb/tui/tui-winsource.c
+++ b/gdb/tui/tui-winsource.c
@@ -455,29 +455,34 @@ tui_update_breakpoint_info (struct tui_win_info *win,
bp != (struct breakpoint *) NULL;
bp = bp->next)
{
+ struct bp_location *loc;
+
gdb_assert (line->line_or_addr.loa == LOA_LINE
|| line->line_or_addr.loa == LOA_ADDRESS);
- if ((win == TUI_SRC_WIN
- && bp->source_file
- && (filename_cmp (src->filename, bp->source_file) == 0)
- && line->line_or_addr.loa == LOA_LINE
- && bp->line_number == line->line_or_addr.u.line_no)
- || (win == TUI_DISASM_WIN
- && line->line_or_addr.loa == LOA_ADDRESS
- && bp->loc != NULL
- && bp->loc->address == line->line_or_addr.u.addr))
- {
- if (bp->enable_state == bp_disabled)
- mode |= TUI_BP_DISABLED;
- else
- mode |= TUI_BP_ENABLED;
- if (bp->hit_count)
- mode |= TUI_BP_HIT;
- if (bp->loc->cond)
- mode |= TUI_BP_CONDITIONAL;
- if (bp->type == bp_hardware_breakpoint)
- mode |= TUI_BP_HARDWARE;
- }
+
+ for (loc = bp->loc; loc != NULL; loc = loc->next)
+ {
+ if ((win == TUI_SRC_WIN
+ && loc->source_file
+ && (filename_cmp (src->filename, loc->source_file) == 0)
+ && line->line_or_addr.loa == LOA_LINE
+ && loc->line_number == line->line_or_addr.u.line_no)
+ || (win == TUI_DISASM_WIN
+ && line->line_or_addr.loa == LOA_ADDRESS
+ && loc->address == line->line_or_addr.u.addr))
+ {
+ if (bp->enable_state == bp_disabled)
+ mode |= TUI_BP_DISABLED;
+ else
+ mode |= TUI_BP_ENABLED;
+ if (bp->hit_count)
+ mode |= TUI_BP_HIT;
+ if (bp->loc->cond)
+ mode |= TUI_BP_CONDITIONAL;
+ if (bp->type == bp_hardware_breakpoint)
+ mode |= TUI_BP_HARDWARE;
+ }
+ }
}
if (line->has_break != mode)
{
diff --git a/gdb/utils.c b/gdb/utils.c
index a43b13d..cc93915 100644
--- a/gdb/utils.c
+++ b/gdb/utils.c
@@ -3651,6 +3651,17 @@ compare_positive_ints (const void *ap, const void *bp)
return * (int *) ap - * (int *) bp;
}
+/* String compare function for qsort. */
+
+int
+compare_strings (const void *arg1, const void *arg2)
+{
+ const char **s1 = (const char **) arg1;
+ const char **s2 = (const char **) arg2;
+
+ return strcmp (*s1, *s2);
+}
+
#define AMBIGUOUS_MESS1 ".\nMatching formats:"
#define AMBIGUOUS_MESS2 \
".\nUse \"set gnutarget format-name\" to specify the format."
[-- Attachment #3: ada patch --]
[-- Type: main patch, Size: 11745 bytes --]
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index e396596..a434333 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -5052,6 +5052,36 @@ done:
return ndefns;
}
+/* Implementation of the la_iterate_over_symbols method. */
+
+static void
+ada_iterate_over_symbols (const struct block *block,
+ const char *name, domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data)
+{
+ int ndefs, i;
+ struct ada_symbol_info *results;
+ char *canon;
+ int nlen = strlen (name);
+
+ if (name[0] == '<' && name[nlen - 1] == '>')
+ {
+ canon = alloca (nlen - 1);
+ memcpy (canon, name + 1, nlen - 2);
+ canon[nlen - 2] = '\0';
+ }
+ else
+ canon = ada_encode (ada_fold_name (name));
+
+ ndefs = ada_lookup_symbol_list (canon, block, domain, &results);
+ for (i = 0; i < ndefs; ++i)
+ {
+ if (! (*callback) (results[i].sym, data))
+ break;
+ }
+}
+
struct symbol *
ada_lookup_encoded_symbol (const char *name, const struct block *block0,
domain_enum namespace, struct block **block_found)
@@ -12282,6 +12312,7 @@ const struct language_defn ada_language_defn = {
ada_print_array_index,
default_pass_by_reference,
c_get_string,
+ ada_iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 3a35a78..81e7849 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -863,6 +863,7 @@ const struct language_defn c_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
@@ -984,6 +985,7 @@ const struct language_defn cplus_language_defn =
default_print_array_index,
cp_pass_by_reference,
c_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
@@ -1023,6 +1025,7 @@ const struct language_defn asm_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
@@ -1067,6 +1070,7 @@ const struct language_defn minimal_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index c0599a5..44ff68a 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -273,6 +273,7 @@ static const struct language_defn d_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ NULL,
LANG_MAGIC
};
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index f538eee..7a8516d 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -309,6 +309,7 @@ const struct language_defn f_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index 4eae356..ce65a2d 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1197,6 +1197,7 @@ const struct language_defn java_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/language.c b/gdb/language.c
index 825c02d..701c479 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -1200,6 +1200,7 @@ const struct language_defn unknown_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
@@ -1241,6 +1242,7 @@ const struct language_defn auto_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
@@ -1280,6 +1282,7 @@ const struct language_defn local_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
\f
diff --git a/gdb/language.h b/gdb/language.h
index 1ff575f..82e6a88 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -318,6 +318,26 @@ struct language_defn
void (*la_get_string) (struct value *value, gdb_byte **buffer, int *length,
struct type **chartype, const char **charset);
+ /* Find all symbols in the current program space matching NAME in
+ DOMAIN, according to this language's rules.
+
+ The search starts with BLOCK. This function iterates upward
+ through blocks. When the outermost block has been finished,
+ the function returns.
+
+ For each one, call CALLBACK with the symbol and the DATA
+ argument. If CALLBACK returns zero, the iteration ends at that
+ point.
+
+ This field can be NULL, meaning that this language doesn't need
+ any special code aside from ordinary searches of the symbol
+ table. */
+ void (*la_iterate_over_symbols) (const struct block *block,
+ const char *name,
+ domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data);
+
/* Add fields above this point, so the magic number is always last. */
/* Magic number for compat checking. */
@@ -422,6 +442,10 @@ extern enum language set_language (enum language);
#define LA_PRINT_ARRAY_INDEX(index_value, stream, options) \
(current_language->la_print_array_index(index_value, stream, options))
+#define LA_ITERATE_OVER_SYMBOLS(BLOCK, NAME, DOMAIN, CALLBACK, DATA) \
+ (current_language->la_iterate_over_symbols (BLOCK, NAME, DOMAIN, CALLBACK, \
+ DATA))
+
/* Test a character to decide whether it can be printed in literal form
or needs to be printed in another representation. For example,
in C the literal form of the character with octal value 141 is 'a'
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 6b391bc..445dbf1 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -373,8 +373,9 @@ iterate_over_all_matching_symtabs (const char *name,
if (symtab->primary)
{
struct block *block;
+
block = BLOCKVECTOR_BLOCK (BLOCKVECTOR (symtab), STATIC_BLOCK);
- iterate_over_symbols (block, name, domain, callback, data);
+ LA_ITERATE_OVER_SYMBOLS (block, name, domain, callback, data);
}
}
}
@@ -1852,10 +1853,10 @@ lookup_prefix_sym (char **argptr, char *p, VEC (symtab_p) *file_symtabs,
gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
set_current_program_space (SYMTAB_PSPACE (elt));
search_block = get_search_block (elt);
- iterate_over_symbols (search_block, copy, STRUCT_DOMAIN,
- collect_one_symbol, &collector);
- iterate_over_symbols (search_block, copy, VAR_DOMAIN,
- collect_one_symbol, &collector);
+ LA_ITERATE_OVER_SYMBOLS (search_block, copy, STRUCT_DOMAIN,
+ collect_one_symbol, &collector);
+ LA_ITERATE_OVER_SYMBOLS (search_block, copy, VAR_DOMAIN,
+ collect_one_symbol, &collector);
}
}
@@ -2207,28 +2208,6 @@ find_function_symbols (char **argptr, char *p, int is_quote_enclosed,
iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
collect_function_symbols, &result, NULL);
- /* If looking up the given name failed, try using the current
- language to look up a symbol. This may augment the search. If a
- symbol is found this way, repeat the iteration, but using the
- discovered name. */
- if (VEC_empty (symbolp, result)
- && current_language->la_language == language_ada)
- {
- struct symbol *function_symbol;
-
- function_symbol = lookup_symbol (copy, get_selected_block (0),
- VAR_DOMAIN, 0);
- if (function_symbol && SYMBOL_CLASS (function_symbol) == LOC_BLOCK)
- {
- xfree (copy);
- copy = xstrdup (SYMBOL_SEARCH_NAME (function_symbol));
- *user_function = copy;
- iterate_over_all_matching_symtabs (copy, VAR_DOMAIN,
- collect_function_symbols,
- &result, NULL);
- }
- }
-
if (VEC_empty (symbolp, result))
VEC_free (symbolp, result);
else
@@ -2823,9 +2802,9 @@ add_matching_symbols_to_info (const char *name,
been filtered out earlier. */
gdb_assert (!SYMTAB_PSPACE (elt)->executing_startup);
set_current_program_space (SYMTAB_PSPACE (elt));
- iterate_over_symbols (get_search_block (elt), name,
- VAR_DOMAIN, collect_symbols,
- info);
+ LA_ITERATE_OVER_SYMBOLS (get_search_block (elt), name,
+ VAR_DOMAIN, collect_symbols,
+ info);
}
}
}
@@ -2858,22 +2837,6 @@ decode_variable (struct linespec_state *self, char *copy)
add_matching_symbols_to_info (lookup_name, &info, NULL);
- /* If looking up the given name failed, try using the current
- language to look up a symbol. This may augment the search. If a
- symbol is found this way, repeat the iteration, but using the
- discovered name. */
- if (info.result.nelts == 0 && current_language->la_language == language_ada)
- {
- struct symbol *sym;
-
- sym = lookup_symbol (lookup_name, get_selected_block (0), VAR_DOMAIN, 0);
- if (sym)
- {
- copy = SYMBOL_SEARCH_NAME (sym);
- add_matching_symbols_to_info (copy, &info, NULL);
- }
- }
-
if (info.result.nelts > 0)
{
if (self->canonical)
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index f83c622..106dfcf 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -401,6 +401,7 @@ const struct language_defn m2_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index dcf9459..1da92a5 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -541,6 +541,7 @@ const struct language_defn objc_language_defn = {
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 05955b4..895a51c 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1024,6 +1024,7 @@ const struct language_defn opencl_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 655279b..30b890f 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -459,6 +459,7 @@ const struct language_defn pascal_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index cd3ca73..8c9ca90 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2011-11-22 Tom Tromey <tromey@redhat.com>
+
+ * gdb.ada/homonym.exp: Add three breakpoint tests.
+
2011-11-18 Tom Tromey <tromey@redhat.com>
* gdb.base/solib-weak.exp (do_test): Remove kfail.
diff --git a/gdb/testsuite/gdb.ada/homonym.exp b/gdb/testsuite/gdb.ada/homonym.exp
index b5dff1b..d568633 100644
--- a/gdb/testsuite/gdb.ada/homonym.exp
+++ b/gdb/testsuite/gdb.ada/homonym.exp
@@ -31,6 +31,24 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug]] != "" }
clean_restart ${testfile}
+
+# Do these tests before running, so we are operating in a known
+# environment.
+
+gdb_test "break Get_Value" \
+ "Breakpoint \[0-9\]+ at $hex: Get_Value. .2 locations." \
+ "set breakpoint at Get_Value"
+
+gdb_test "break homonym.adb:Get_Value" \
+ "Breakpoint \[0-9\]+ at $hex: homonym.adb:Get_Value. .2 locations." \
+ "set breakpoint at homonym.adb:Get_Value"
+
+gdb_test "break <homonym__get_value>" \
+ "Breakpoint \[0-9\]+ at $hex: <homonym__get_value>. .2 locations." \
+ "set breakpoint at <homonym__get_value>"
+
+delete_breakpoints
+
set bp_location [gdb_get_line_number "BREAK_1" ${testdir}/homonym.adb]
runto "homonym.adb:$bp_location"
@@ -86,6 +104,3 @@ gdb_test "ptype lcl" \
gdb_test "print lcl" \
"= 17" \
"print lcl at BREAK_2"
-
-
-
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: [RFA/commit/testcase] "info line" should not skip prologues
2011-11-29 15:03 ` [RFA/commit/testcase] "info line" should not skip prologues Tom Tromey
@ 2011-11-29 17:00 ` Joel Brobecker
0 siblings, 0 replies; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 17:00 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
> Joel> This is an issue that I discovered in your previous set of patches, but
> Joel> got fixed in this iteration :-). Nonetheless, I wrote a testcase,
> Joel> so I'm sending it here. I think I should commit it independenly
> Joel> of your series.
>
> I agree, thanks.
Cool. The testcase is now in.
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: set multiple-symbol ask/cancel not working
2011-11-29 16:57 ` Tom Tromey
@ 2011-11-29 17:06 ` Joel Brobecker
2011-11-30 16:41 ` Tom Tromey
0 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-29 17:06 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
> Tom> (gdb) b pck.adb:normal_Menu
> Tom> [0] cancel
> Tom> [1] all
> Tom> [2] pck.adb:pck.normal_menu:4
> Tom> [3] pck.adb:pck.normal_menu:8
>
> I am not at all sure about doing this. It means that the breakpoint
> will stop working if the line number changes.
This is what is already happening today. One of the future improvements
we discussed was transitioning to a canonical format that used the
argument types, much like C++ does. But this is a big project on its
own, and we're not sure yet whether the debug info is sufficient for
this, and how much code needs to be implemented in order to match
the relevant semantic rules of the Ada language.
> Maybe this is ok, since it is what the user asked for in
> multiple-symbols=ask mode -- not the default, so he essentially asked
> twice.
Just to be certain, I assume that if the user selects "all", then
we still get one multi-location breakpoint?
> Another option would be to only apply this treatment to Ada.
I am cool with that. Might be a little ugly, but I don't think
we should penalize the other languages just because we're not ready
to do so in Ada.
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: one-too-many location in breakpoint
2011-11-29 16:59 ` Tom Tromey
@ 2011-11-30 5:59 ` Joel Brobecker
2011-11-30 16:41 ` Tom Tromey
2011-12-05 12:04 ` Pedro Alves
2011-12-08 18:56 ` Maciej W. Rozycki
2 siblings, 1 reply; 42+ messages in thread
From: Joel Brobecker @ 2011-11-30 5:59 UTC (permalink / raw)
To: Tom Tromey; +Cc: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 1127 bytes --]
> Tom> I fixed all the other problems. I'm running a regression test to make
> Tom> sure I didn't make something else break while doing this. If all goes
> Tom> well I will send out refreshed patches.
As discussed on IRC, there was one problem that I missed in the
proposals I made earlier. Attached is a patch that I wrote
which should solve that problem. In hindsight, perhaps I should
have split it in 2 or 3 patches, for instance one patch for
the new language method, and one patch for the rest. And maybe
one patch on its own for the documentation update of
demangle_for_lookup. Anyways, that's fairly easy to do, but
for now, I think it's more important to get the patch out.
Note that this patch adds new tests.
With that patch, pretty much everything that I suggested, except
for the couple of issues I briefly mentioned (without describing
them), has been addressed. I'm not convinced yet that the remaining
issues have anything to do with the patch series but I will look
into that tomorrow.
For the record, it was testing on x86_64-linux, with the official
testsuite as well as AdaCore's testsuite.
--
Joel
[-- Attachment #2: 0001-new-la_symbol_name_compare-language-method.patch --]
[-- Type: text/x-diff, Size: 23020 bytes --]
From 908c8de2fe6bf9be3a2bee1ebc9858ec292ea6a2 Mon Sep 17 00:00:00 2001
From: Joel Brobecker <brobecker@adacore.com>
Date: Tue, 29 Nov 2011 10:35:27 -0800
Subject: [PATCH] new la_symbol_name_compare language method
The goal of this patch is to make sure that GDB is able to handle
Ada linespecs that's just a fully qualified function name with
some of the letters being uppercase characters. For instance:
(gdb) break Pck.Hello
The real issue is that the "natural" name "Pck.Hello" needs to be
encoded for the symbol lookup to be successful. That encoding
was currently only happening inside ada_iterate_over_symbols, which
means that it would only work if we specified a filename with
the function name. For instance:
(gdb) break pck.adb:Pck.Hello
But even there it is a little bit wasteful, because the
la_iterate_over_symbols language method is called for every
symbol table that seems to contain a matching symbol, sometimes
twice. It would be better to perform the name enconding once
at the beginning, and then not have to worry about it during
the symbol lookup.
The other issue is that symbol matching is currently hardcoded to
using strcmp_iw, which does not work for Ada.
So, this patch does the following:
1. It introduces a new language method called la_symbol_name_compare,
which is responsible for comparing two symbol names for a given
language.
This is something we want now because we want to be able to
use a different symbol matching routine for Ada, rather than
the default strcmp_iw.
But this is also something that would be useful to allow
language-specific sorting of partial symbols. Right now,
they are sorted using strcmp_iw_ordered, and the Ada-specific
comparison routine has to be "compatible" with that.
2. It exploits that new language method in the symbol matching
routine. For that, we added a language parameter to the profile
of the name_matcher function (which is passed as an argument to
the expand_symtabs_matching quick_symbol_functions routine).
3. It changes decode_variable so that, for Ada linespecs, function
name get encoded before the lookup starts. This allows us to
avoid doing it everytime ada_iterate_over_symbols is called.
gdb/ChangeLog:
* language.h (struct language_defn): Add new component
la_symbol_name_compare.
* symfile.h (struct quick_symbol_functions): Update the profile
of parameter "name_matcher" for the expand_symtabs_matching
method. Update the documentation accordingly.
* ada-lang.h (ada_name_for_lookup): Add declaration.
* ada-lang.c (ada_name_for_lookup): New function, extracted out
from ada_iterate_over_symbols.
(ada_iterate_over_symbols): Do not encode symbol name anymore.
(ada_expand_partial_symbol_name): Adjust profile.
(ada_language_defn): Add value for la_symbol_name_compare field.
* linespec.c: #include "ada-lang.h".
(iterate_name_matcher): Add language parameter. Replace call
to strcmp_iw by call to language->la_symbol_name_compare.
(decode_variable): Encode COPY if current language is Ada.
* dwarf2read.c (dw2_expand_symtabs_matching): Adjust profile
of name_matcher parameter. Adjust call to name_matcher.
* psymtab.c (expand_symtabs_matching_via_partial): Likewise.
(expand_partial_symbol_names): Update profile of parameter "fun".
* psymtab.h (expand_partial_symbol_names): Update profile of
parameter "fun".
* symtab.c (demangle_for_lookup): Update function documentation.
(search_symbols_name_matches): Add language parameter.
(expand_partial_symbol_name): Likewise.
* c-lang.c (c_language_defn, cplus_language_defn)
(asm_language_defn, minimal_language_defn): Add value for
la_symbol_name_compare field.
* d-lang.c (d_language_defn): Likewise.
* f-lang.c (f_language_defn): Ditto.
* jv-lang.c (java_language_defn): Ditto.
* m2-lang.c (m2_language_defn): Ditto.
* objc-lang.c (objc_language_defn): Ditto.
* opencl-lang.c (opencl_language_defn): Ditto.
* p-lang.c (pascal_language_defn): Ditto.
* language.c (unknown_language_defn, auto_language_defn)
(local_language_defn): Ditto.
gdb/testsuite/ChangeLog:
* gdb.ada/fullname_bp.exp: Add tests for other valid linespecs
involving a fully qualified function name.
---
gdb/ada-lang.c | 40 +++++++++++++++++++++++----------
gdb/ada-lang.h | 2 +
gdb/c-lang.c | 4 +++
gdb/d-lang.c | 1 +
gdb/dwarf2read.c | 13 +++++-----
gdb/f-lang.c | 1 +
gdb/jv-lang.c | 1 +
gdb/language.c | 3 ++
gdb/language.h | 14 +++++++++++
gdb/linespec.c | 13 +++++++++-
gdb/m2-lang.c | 1 +
gdb/objc-lang.c | 1 +
gdb/opencl-lang.c | 1 +
gdb/p-lang.c | 1 +
gdb/psymtab.c | 20 +++++++++-------
gdb/psymtab.h | 3 +-
gdb/symfile.h | 20 ++++++++++------
gdb/symtab.c | 22 +++++++++++++++--
gdb/testsuite/gdb.ada/fullname_bp.exp | 23 +++++++++++++++++++
19 files changed, 143 insertions(+), 41 deletions(-)
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 6d69199..db9de01 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -5052,29 +5052,43 @@ done:
return ndefns;
}
-/* Implementation of the la_iterate_over_symbols method. */
+/* If NAME is the name of an entity, return a string that should
+ be used to look that entity up in Ada units. This string should
+ be deallocated after use using xfree.
-static void
-ada_iterate_over_symbols (const struct block *block,
- const char *name, domain_enum domain,
- int (*callback) (struct symbol *, void *),
- void *data)
+ NAME can have any form that the "break" or "print" commands might
+ recognize. In other words, it does not have to be the "natural"
+ name, or the "encoded" name. */
+
+char *
+ada_name_for_lookup (const char *name)
{
- int ndefs, i;
- struct ada_symbol_info *results;
char *canon;
int nlen = strlen (name);
if (name[0] == '<' && name[nlen - 1] == '>')
{
- canon = alloca (nlen - 1);
+ canon = xmalloc (nlen - 1);
memcpy (canon, name + 1, nlen - 2);
canon[nlen - 2] = '\0';
}
else
- canon = ada_encode (ada_fold_name (name));
+ canon = xstrdup (ada_encode (ada_fold_name (name)));
+ return canon;
+}
+
+/* Implementation of the la_iterate_over_symbols method. */
+
+static void
+ada_iterate_over_symbols (const struct block *block,
+ const char *name, domain_enum domain,
+ int (*callback) (struct symbol *, void *),
+ void *data)
+{
+ int ndefs, i;
+ struct ada_symbol_info *results;
- ndefs = ada_lookup_symbol_list (canon, block, domain, &results);
+ ndefs = ada_lookup_symbol_list (name, block, domain, &results);
for (i = 0; i < ndefs; ++i)
{
if (! (*callback) (results[i].sym, data))
@@ -5663,7 +5677,8 @@ struct add_partial_datum
/* A callback for expand_partial_symbol_names. */
static int
-ada_expand_partial_symbol_name (const char *name, void *user_data)
+ada_expand_partial_symbol_name (const struct language_defn *language,
+ const char *name, void *user_data)
{
struct add_partial_datum *data = user_data;
@@ -12368,6 +12383,7 @@ const struct language_defn ada_language_defn = {
ada_print_array_index,
default_pass_by_reference,
c_get_string,
+ compare_names,
ada_iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/ada-lang.h b/gdb/ada-lang.h
index d6404ca..fa4bb51 100644
--- a/gdb/ada-lang.h
+++ b/gdb/ada-lang.h
@@ -365,6 +365,8 @@ extern char *ada_breakpoint_rewrite (char *, int *);
extern char *ada_main_name (void);
+extern char *ada_name_for_lookup (const char *name);
+
/* Tasking-related: ada-tasks.c */
extern int valid_task_id (int);
diff --git a/gdb/c-lang.c b/gdb/c-lang.c
index 81e7849..7be916c 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -863,6 +863,7 @@ const struct language_defn c_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
@@ -985,6 +986,7 @@ const struct language_defn cplus_language_defn =
default_print_array_index,
cp_pass_by_reference,
c_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
@@ -1025,6 +1027,7 @@ const struct language_defn asm_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
@@ -1070,6 +1073,7 @@ const struct language_defn minimal_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/d-lang.c b/gdb/d-lang.c
index 44ff68a..fb6bacd 100644
--- a/gdb/d-lang.c
+++ b/gdb/d-lang.c
@@ -273,6 +273,7 @@ static const struct language_defn d_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ strcmp_iw_ordered,
NULL,
LANG_MAGIC
};
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index ba56065..81c4af1 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2756,11 +2756,12 @@ dw2_map_matching_symbols (const char * name, domain_enum namespace,
}
static void
-dw2_expand_symtabs_matching (struct objfile *objfile,
- int (*file_matcher) (const char *, void *),
- int (*name_matcher) (const char *, void *),
- enum search_domain kind,
- void *data)
+dw2_expand_symtabs_matching
+ (struct objfile *objfile,
+ int (*file_matcher) (const char *, void *),
+ int (*name_matcher) (const struct language_defn *, const char *, void *),
+ enum search_domain kind,
+ void *data)
{
int i;
offset_type iter;
@@ -2812,7 +2813,7 @@ dw2_expand_symtabs_matching (struct objfile *objfile,
name = index->constant_pool + MAYBE_SWAP (index->symbol_table[idx]);
- if (! (*name_matcher) (name, data))
+ if (! (*name_matcher) (current_language, name, data))
continue;
/* The name was matched, now expand corresponding CUs that were
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 7a8516d..00926fb 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -309,6 +309,7 @@ const struct language_defn f_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index ce65a2d..80fe4a1 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -1197,6 +1197,7 @@ const struct language_defn java_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/language.c b/gdb/language.c
index 701c479..1bbbfba 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -1200,6 +1200,7 @@ const struct language_defn unknown_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
@@ -1242,6 +1243,7 @@ const struct language_defn auto_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
@@ -1282,6 +1284,7 @@ const struct language_defn local_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/language.h b/gdb/language.h
index 82e6a88..65d55db 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -318,6 +318,20 @@ struct language_defn
void (*la_get_string) (struct value *value, gdb_byte **buffer, int *length,
struct type **chartype, const char **charset);
+ /* Compare two symbol names according to language rules. For
+ instance, in C++, we might want to ignore whitespaces in
+ the symbol name. Or some case-insensitive language might
+ want to ignore casing during the match.
+
+ Both STR1 and STR2 are expected to be demangled name, except
+ for Ada, where STR1 and STR2 are expected to be encoded names.
+ The latter is because searches are performed using the encoded
+ name in Ada.
+
+ The return value follows the same spirit as strcmp. */
+
+ int (*la_symbol_name_compare) (const char *str1, const char *str2);
+
/* Find all symbols in the current program space matching NAME in
DOMAIN, according to this language's rules.
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 445dbf1..adbefff 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -44,6 +44,7 @@
#include <ctype.h>
#include "cli/cli-utils.h"
#include "filenames.h"
+#include "ada-lang.h"
typedef struct symtab *symtab_p;
DEF_VEC_P (symtab_p);
@@ -325,11 +326,12 @@ cplusplus_error (const char *name, const char *fmt, ...)
callback to the expand_symtabs_matching method. */
static int
-iterate_name_matcher (const char *name, void *d)
+iterate_name_matcher (const struct language_defn *language,
+ const char *name, void *d)
{
const char **dname = d;
- if (strcmp_iw (name, *dname) == 0)
+ if (language->la_symbol_name_compare (name, *dname) == 0)
return 1;
return 0;
}
@@ -2827,6 +2829,13 @@ decode_variable (struct linespec_state *self, char *copy)
cleanup = demangle_for_lookup (copy, current_language->la_language,
&lookup_name);
+ if (current_language->la_language == language_ada)
+ {
+ /* In Ada, the symbol lookups are performed using the encoded
+ name rather than the demangled name. */
+ lookup_name = ada_name_for_lookup (copy);
+ make_cleanup (xfree, (void *) lookup_name);
+ }
canon = cp_canonicalize_string_no_typedefs (copy);
if (canon != NULL)
diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
index 106dfcf..c850b1f 100644
--- a/gdb/m2-lang.c
+++ b/gdb/m2-lang.c
@@ -401,6 +401,7 @@ const struct language_defn m2_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/objc-lang.c b/gdb/objc-lang.c
index 1da92a5..cb7fa0e 100644
--- a/gdb/objc-lang.c
+++ b/gdb/objc-lang.c
@@ -541,6 +541,7 @@ const struct language_defn objc_language_defn = {
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/opencl-lang.c b/gdb/opencl-lang.c
index 895a51c..1deb9d8 100644
--- a/gdb/opencl-lang.c
+++ b/gdb/opencl-lang.c
@@ -1024,6 +1024,7 @@ const struct language_defn opencl_language_defn =
default_print_array_index,
default_pass_by_reference,
c_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 30b890f..f66d471 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -459,6 +459,7 @@ const struct language_defn pascal_language_defn =
default_print_array_index,
default_pass_by_reference,
default_get_string,
+ strcmp_iw_ordered,
iterate_over_symbols,
LANG_MAGIC
};
diff --git a/gdb/psymtab.c b/gdb/psymtab.c
index c20fd78..946a511 100644
--- a/gdb/psymtab.c
+++ b/gdb/psymtab.c
@@ -1244,13 +1244,12 @@ map_matching_symbols_psymtab (const char *name, domain_enum namespace,
}
static void
-expand_symtabs_matching_via_partial (struct objfile *objfile,
- int (*file_matcher) (const char *,
- void *),
- int (*name_matcher) (const char *,
- void *),
- enum search_domain kind,
- void *data)
+expand_symtabs_matching_via_partial
+ (struct objfile *objfile,
+ int (*file_matcher) (const char *, void *),
+ int (*name_matcher) (const struct language_defn *, const char *, void *),
+ enum search_domain kind,
+ void *data)
{
struct partial_symtab *ps;
@@ -1300,7 +1299,8 @@ expand_symtabs_matching_via_partial (struct objfile *objfile,
&& SYMBOL_CLASS (*psym) == LOC_BLOCK)
|| (kind == TYPES_DOMAIN
&& SYMBOL_CLASS (*psym) == LOC_TYPEDEF))
- && (*name_matcher) (SYMBOL_NATURAL_NAME (*psym), data))
+ && (*name_matcher) (current_language,
+ SYMBOL_NATURAL_NAME (*psym), data))
{
PSYMTAB_TO_SYMTAB (ps);
keep_going = 0;
@@ -1937,7 +1937,9 @@ maintenance_check_symtabs (char *ignore, int from_tty)
\f
void
-expand_partial_symbol_names (int (*fun) (const char *, void *), void *data)
+expand_partial_symbol_names (int (*fun) (const struct language_defn *,
+ const char *, void *),
+ void *data)
{
struct objfile *objfile;
diff --git a/gdb/psymtab.h b/gdb/psymtab.h
index de292c5..940b537 100644
--- a/gdb/psymtab.h
+++ b/gdb/psymtab.h
@@ -30,7 +30,8 @@ extern struct psymbol_bcache *psymbol_bcache_init (void);
extern void psymbol_bcache_free (struct psymbol_bcache *);
extern struct bcache *psymbol_bcache_get_bcache (struct psymbol_bcache *);
-void expand_partial_symbol_names (int (*fun) (const char *, void *),
+void expand_partial_symbol_names (int (*fun) (const struct language_defn *,
+ const char *, void *),
void *data);
void map_partial_symbol_filenames (symbol_filename_ftype *fun, void *data,
diff --git a/gdb/symfile.h b/gdb/symfile.h
index 8b3b705..44f0c01 100644
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -261,9 +261,12 @@ struct quick_symbol_functions
Otherwise, if KIND does not match this symbol is skipped.
- If even KIND matches, then NAME_MATCHER is called for each symbol defined
- in the file. The symbol's "natural" name and DATA are passed to
- NAME_MATCHER.
+ If even KIND matches, then NAME_MATCHER is called for each symbol
+ defined in the file. The current language, the symbol name and
+ DATA are passed to NAME_MATCHER. The symbol "natural" name should
+ be passed to NAME_MATCHER for all languages except Ada, where
+ the encoded name is passed instead (see la_symbol_name_compare in
+ struct language_defn for more details on this).
If NAME_MATCHER returns zero, then this symbol is skipped.
@@ -271,11 +274,12 @@ struct quick_symbol_functions
DATA is user data that is passed unmodified to the callback
functions. */
- void (*expand_symtabs_matching) (struct objfile *objfile,
- int (*file_matcher) (const char *, void *),
- int (*name_matcher) (const char *, void *),
- enum search_domain kind,
- void *data);
+ void (*expand_symtabs_matching)
+ (struct objfile *objfile,
+ int (*file_matcher) (const char *, void *),
+ int (*name_matcher) (const struct language_defn *, const char *, void *),
+ enum search_domain kind,
+ void *data);
/* Return the symbol table from OBJFILE that contains PC and
SECTION. Return NULL if there is no such symbol table. This
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 3ae5cf9..1ea4253 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1054,7 +1054,21 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
/* Compute the demangled form of NAME as used by the various symbol
lookup functions. The result is stored in *RESULT_NAME. Returns a
- cleanup which can be used to clean up the result. */
+ cleanup which can be used to clean up the result.
+
+ For Ada, this function just sets *RESULT_NAME to NAME, unmodified.
+ Normally, Ada symbol lookups are performed using the encoded name
+ rather than the demangled name, and so it might seem to make sense
+ for this function to return an encoded version of NAME.
+ Unfortunately, we cannot do this, because this function is used in
+ circumstances where it is not appropriate to try to encode NAME.
+ For instance, when displaying the frame info, we demangle the name
+ of each parameter, and then perform a symbol lookup inside our
+ function using that demangled name. In Ada, certain functions
+ have internally-generated parameters whose name contain uppercase
+ characters. Encoding those name would result in those uppercase
+ characters to become lowercase, and thus cause the symbol lookup
+ to fail. */
struct cleanup *
demangle_for_lookup (const char *name, enum language lang,
@@ -3152,7 +3166,8 @@ search_symbols_file_matches (const char *filename, void *user_data)
/* A callback for expand_symtabs_matching. */
static int
-search_symbols_name_matches (const char *symname, void *user_data)
+search_symbols_name_matches (const struct language_defn *language,
+ const char *symname, void *user_data)
{
struct search_symbols_data *data = user_data;
@@ -3960,7 +3975,8 @@ add_macro_name (const char *name, const struct macro_definition *ignore,
/* A callback for expand_partial_symbol_names. */
static int
-expand_partial_symbol_name (const char *name, void *user_data)
+expand_partial_symbol_name (const struct language_defn *language,
+ const char *name, void *user_data)
{
struct add_name_data *datum = (struct add_name_data *) user_data;
diff --git a/gdb/testsuite/gdb.ada/fullname_bp.exp b/gdb/testsuite/gdb.ada/fullname_bp.exp
index faf63b9..0e4d32f 100644
--- a/gdb/testsuite/gdb.ada/fullname_bp.exp
+++ b/gdb/testsuite/gdb.ada/fullname_bp.exp
@@ -25,6 +25,9 @@ if {[gdb_compile_ada "${srcfile}" "${binfile}" executable [list debug ]] != "" }
return -1
}
+# Note: We restart the debugger before setting each breakpoint, because
+# we want to test the situation where the symtab for our breakpoint
+# has not been created yet.
clean_restart ${testfile}
# Break on "pck.hello" rather than just "hello" to make sure we trigger
@@ -32,3 +35,23 @@ clean_restart ${testfile}
gdb_test "break pck.hello" \
"Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*pck.adb, line \[0-9\]+."
+# Do the same, but this time using a linespec where the user also
+# provided a filename.
+
+clean_restart ${testfile}
+
+gdb_test "break pck.adb:pck.hello" \
+ "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*pck.adb, line \[0-9\]+."
+
+# Same scenarios as above, but with a function name that is spelled
+# with upper-case letters.
+
+clean_restart ${testfile}
+
+gdb_test "break Pck.Hello" \
+ "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*pck.adb, line \[0-9\]+."
+
+clean_restart ${testfile}
+
+gdb_test "break pck.adb:Pck.Hello" \
+ "Breakpoint \[0-9\]+ at 0x\[0-9a-f\]+: file .*pck.adb, line \[0-9\]+."
--
1.7.1
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: set multiple-symbol ask/cancel not working
2011-11-29 17:06 ` Joel Brobecker
@ 2011-11-30 16:41 ` Tom Tromey
0 siblings, 0 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-30 16:41 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Tom> Another option would be to only apply this treatment to Ada.
Joel> I am cool with that. Might be a little ugly, but I don't think
Joel> we should penalize the other languages just because we're not ready
Joel> to do so in Ada.
I think I will do that.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: one-too-many location in breakpoint
2011-11-30 5:59 ` Joel Brobecker
@ 2011-11-30 16:41 ` Tom Tromey
0 siblings, 0 replies; 42+ messages in thread
From: Tom Tromey @ 2011-11-30 16:41 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
>>>>> "Joel" == Joel Brobecker <brobecker@adacore.com> writes:
Joel> As discussed on IRC, there was one problem that I missed in the
Joel> proposals I made earlier. Attached is a patch that I wrote
Joel> which should solve that problem. In hindsight, perhaps I should
Joel> have split it in 2 or 3 patches, for instance one patch for
Joel> the new language method, and one patch for the rest.
I think one patch is fine. It is still easy to read.
Joel> With that patch, pretty much everything that I suggested, except
Joel> for the couple of issues I briefly mentioned (without describing
Joel> them), has been addressed. I'm not convinced yet that the remaining
Joel> issues have anything to do with the patch series but I will look
Joel> into that tomorrow.
The patch seems reasonable to me.
Joel> + make_cleanup (xfree, (void *) lookup_name);
You don't need the cast here.
Tom
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: GDB 7.4 branching status? (2011-11-23)
2011-11-24 17:27 ` Joel Brobecker
@ 2011-12-03 1:19 ` Maciej W. Rozycki
0 siblings, 0 replies; 42+ messages in thread
From: Maciej W. Rozycki @ 2011-12-03 1:19 UTC (permalink / raw)
To: Joel Brobecker; +Cc: gdb-patches
On Thu, 24 Nov 2011, Joel Brobecker wrote:
> Thanks. Still, it would be nice if we could at least review them...
No worries, I've got plenty of stuff to submit, so we can pipeline.
Also I started with the easier bits -- the tougher parts will come as we
go. ;)
Maciej
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: one-too-many location in breakpoint
2011-11-29 16:59 ` Tom Tromey
2011-11-30 5:59 ` Joel Brobecker
@ 2011-12-05 12:04 ` Pedro Alves
2011-12-05 12:17 ` Pedro Alves
2011-12-08 18:56 ` Maciej W. Rozycki
2 siblings, 1 reply; 42+ messages in thread
From: Pedro Alves @ 2011-12-05 12:04 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey, Joel Brobecker, gdb-patches
On Tuesday 29 November 2011 16:58:38, Tom Tromey wrote:
> Tom> I fixed all the other problems. I'm running a regression test to make
> Tom> sure I didn't make something else break while doing this. If all goes
> Tom> well I will send out refreshed patches.
>
> I needed a couple of test suite changes to account for the different
> output. Otherwise all is well.
>
> This includes a test addition for the iterate_over_symbols change.
>
> I didn't write a new test for the "normal_menu" problem.
/me catches breath after reading the whole thing.
Can't say that was enough to completely grok it all, but nothing
jumped out at me. FWIW.
--
Pedro Alves
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: one-too-many location in breakpoint
2011-12-05 12:04 ` Pedro Alves
@ 2011-12-05 12:17 ` Pedro Alves
0 siblings, 0 replies; 42+ messages in thread
From: Pedro Alves @ 2011-12-05 12:17 UTC (permalink / raw)
To: gdb-patches; +Cc: Tom Tromey, Joel Brobecker, gdb-patches
On Tuesday 29 November 2011 16:58:38, Tom Tromey wrote:
> Tom> I fixed all the other problems. I'm running a regression test to make
> Tom> sure I didn't make something else break while doing this. If all goes
> Tom> well I will send out refreshed patches.
>
> I needed a couple of test suite changes to account for the different
> output. Otherwise all is well.
>
> This includes a test addition for the iterate_over_symbols change.
>
> I didn't write a new test for the "normal_menu" problem.
/me catches breath after reading the whole thing.
Can't say that was enough to completely grok it all, but nothing
jumped out at me. FWIW.
--
Pedro Alves
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: one-too-many location in breakpoint
2011-11-29 16:59 ` Tom Tromey
2011-11-30 5:59 ` Joel Brobecker
2011-12-05 12:04 ` Pedro Alves
@ 2011-12-08 18:56 ` Maciej W. Rozycki
2011-12-09 8:47 ` Joel Brobecker
2 siblings, 1 reply; 42+ messages in thread
From: Maciej W. Rozycki @ 2011-12-08 18:56 UTC (permalink / raw)
To: Tom Tromey; +Cc: Joel Brobecker, gdb-patches
On Tue, 29 Nov 2011, Tom Tromey wrote:
> Tom> I fixed all the other problems. I'm running a regression test to make
> Tom> sure I didn't make something else break while doing this. If all goes
> Tom> well I will send out refreshed patches.
>
> I needed a couple of test suite changes to account for the different
> output. Otherwise all is well.
>
> This includes a test addition for the iterate_over_symbols change.
>
> I didn't write a new test for the "normal_menu" problem.
Just as a heads-up, this has regressed on the mips-sde-elf target (both
MIPS32 and MIPS16 multilibs) as follows:
break A::outer::foo (char*) const if (a == 3)
No symbol "a" in current context.
(gdb) FAIL: gdb.cp/ovsrch.exp: break A::outer::foo (char*) const if (a == 3)
break 'A::outer::foo (char*) const' if (a == 3)
No symbol "a" in current context.
(gdb) FAIL: gdb.cp/ovsrch.exp: break 'A::outer::foo (char*) const' if (a == 3)
[...]
break A::outer::foo (int) const if (a == 3)
No symbol "a" in current context.
(gdb) FAIL: gdb.cp/ovsrch.exp: break A::outer::foo (int) const if (a == 3)
break 'A::outer::foo (int) const' if (a == 3)
No symbol "a" in current context.
(gdb) FAIL: gdb.cp/ovsrch.exp: break 'A::outer::foo (int) const' if (a == 3)
[...]
break A::B::inner::foo (char*) const if (a == 3)
No symbol "a" in current context.
(gdb) FAIL: gdb.cp/ovsrch.exp: break A::B::inner::foo (char*) const if (a == 3)
break 'A::B::inner::foo (char*) const' if (a == 3)
No symbol "a" in current context.
(gdb) FAIL: gdb.cp/ovsrch.exp: break 'A::B::inner::foo (char*) const' if (a == 3)
[...]
break A::B::inner::foo (int) const if (a == 3)
No symbol "a" in current context.
(gdb) FAIL: gdb.cp/ovsrch.exp: break A::B::inner::foo (int) const if (a == 3)
break 'A::B::inner::foo (int) const' if (a == 3)
No symbol "a" in current context.
(gdb) FAIL: gdb.cp/ovsrch.exp: break 'A::B::inner::foo (int) const' if (a == 3)
No regressions on mips-linux-gnu though.
This is SDE code:
800011e8 <A::stop_here()>:
800011e8: 27bdfff8 addiu sp,sp,-8
800011ec: afbe0004 sw s8,4(sp)
800011f0: 03a0f021 move s8,sp
800011f4: 03c0e821 move sp,s8
800011f8: 8fbe0004 lw s8,4(sp)
800011fc: 27bd0008 addiu sp,sp,8
80001200: 03e00008 jr ra
80001204: 00000000 nop
(breakpoint at 800011f4), and this is Linux code:
00400790 <A::stop_here()>:
400790: 27bdfff8 addiu sp,sp,-8
400794: afbe0004 sw s8,4(sp)
400798: 03a0f021 move s8,sp
40079c: 03c0e821 move sp,s8
4007a0: 8fbe0004 lw s8,4(sp)
4007a4: 27bd0008 addiu sp,sp,8
4007a8: 03e00008 jr ra
4007ac: 00000000 nop
(breakpoint at 40079c). And I fail to see "a" being defined anywhere
throughout gdb.cp/ovsrch*, so I am curious as to why it succeeds for any
target (including mips-linux-gnu) in the first place.
I can see you made this adjustment:
- gdb_test "break ${class}::foo if (a == 3)" "Breakpoint (\[0-9\]).*"
+ gdb_test "break ${class}::hibob if (a_param == 3)" "Breakpoint
but there's this definition elsewhere in this test case:
set conditional1 "if (a == 3)"
as well, that you have left intact. Should it be adjusted accordingly?
Why is this condition accepted for some targets and not for some others
anyway?
Thoughts?
Maciej
^ permalink raw reply [flat|nested] 42+ messages in thread
* Re: one-too-many location in breakpoint
2011-12-08 18:56 ` Maciej W. Rozycki
@ 2011-12-09 8:47 ` Joel Brobecker
0 siblings, 0 replies; 42+ messages in thread
From: Joel Brobecker @ 2011-12-09 8:47 UTC (permalink / raw)
To: Maciej W. Rozycki; +Cc: Tom Tromey, gdb-patches
> I can see you made this adjustment:
>
> - gdb_test "break ${class}::foo if (a == 3)" "Breakpoint (\[0-9\]).*"
> + gdb_test "break ${class}::hibob if (a_param == 3)" "Breakpoint
>
> but there's this definition elsewhere in this test case:
>
> set conditional1 "if (a == 3)"
>
> as well, that you have left intact. Should it be adjusted accordingly?
I think it did get adjusted yesterday.
> Why is this condition accepted for some targets and not for some
> others anyway?
Tom said:
> I missed a spot when changing the parameter names in ovsrch.exp, and
> didn't notice because I have the 64-bit glibc debuginfo installed, which
> provides a minsym named "a".
I've hit this sort of problem several times in the past, and that's why
I choose funky and unambiguous names for my global variables....
--
Joel
^ permalink raw reply [flat|nested] 42+ messages in thread
end of thread, other threads:[~2011-12-09 8:19 UTC | newest]
Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-11-23 16:39 GDB 7.4 branching status? (2011-11-23) Joel Brobecker
2011-11-23 16:56 ` Tristan Gingold
2011-11-23 18:47 ` Tom Tromey
2011-11-23 23:24 ` Joel Brobecker
2011-11-24 10:56 ` Jerome Guitton
2011-11-24 16:33 ` Joel Brobecker
2011-11-28 16:17 ` Tom Tromey
2011-11-28 21:29 ` Tom Tromey
2011-11-29 2:28 ` Joel Brobecker
2011-11-29 2:49 ` iterate_over_symbols should be a wrapper? (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
2011-11-29 15:27 ` iterate_over_symbols should be a wrapper? Tom Tromey
2011-11-29 3:07 ` partial-symtab symbol sorting (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
2011-11-29 8:41 ` Pierre Muller
2011-11-29 14:51 ` partial-symtab symbol sorting Tom Tromey
[not found] ` <47228.5772244961$1322556128@news.gmane.org>
2011-11-29 14:55 ` Tom Tromey
2011-11-29 3:11 ` multiple-location breakpoint output (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
2011-11-29 15:06 ` multiple-location breakpoint output Tom Tromey
2011-11-29 3:14 ` decode_digits_line_mode (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
2011-11-29 14:56 ` decode_digits_line_mode Tom Tromey
2011-11-29 3:19 ` [RFA/commit/testcase] "info line" should not skip prologues (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
2011-11-29 15:03 ` [RFA/commit/testcase] "info line" should not skip prologues Tom Tromey
2011-11-29 17:00 ` Joel Brobecker
2011-11-29 3:22 ` GDB 7.4 branching status? (2011-11-23) Joel Brobecker
2011-11-29 15:38 ` Tom Tromey
2011-11-29 3:29 ` set multiple-symbol ask/cancel not working (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
2011-11-29 16:14 ` set multiple-symbol ask/cancel not working Tom Tromey
2011-11-29 16:57 ` Tom Tromey
2011-11-29 17:06 ` Joel Brobecker
2011-11-30 16:41 ` Tom Tromey
2011-11-29 3:33 ` one-too-many location in breakpoint (was: "Re: GDB 7.4 branching status? (2011-11-23)") Joel Brobecker
2011-11-29 16:15 ` one-too-many location in breakpoint Tom Tromey
2011-11-29 16:59 ` Tom Tromey
2011-11-30 5:59 ` Joel Brobecker
2011-11-30 16:41 ` Tom Tromey
2011-12-05 12:04 ` Pedro Alves
2011-12-05 12:17 ` Pedro Alves
2011-12-08 18:56 ` Maciej W. Rozycki
2011-12-09 8:47 ` Joel Brobecker
2011-11-24 0:58 ` GDB 7.4 branching status? (2011-11-23) Yao Qi
2011-11-24 17:17 ` Maciej W. Rozycki
2011-11-24 17:27 ` Joel Brobecker
2011-12-03 1:19 ` Maciej W. Rozycki
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).