ada-lang.c has a "sort_choices" function that claims to sort the
symbol choices, but which does not really implement sorting. This
patch changes this code to really sort the result vector, sorting
first by filename, then line number, and finally by the symbol name.
The filename sorting is done first by comparing basenames. It turns
out that gnatmake and gprbuild invoke the compiler a bit differently,
so depending on which one you use, the results of a naive sort might
be different (due to the use of absolute or relative paths).
Add "doens't->doesn't" to gdb/contrib/common-misspellings.txt, and run
gdb/contrib/spellcheck.sh to fix this in a few files.
Tested on x86_64-linux.
Approved-by: Kevin Buettner <kevinb@redhat.com>
This patch started as an attempt to allow the 'Size attribute to be
applied to types, and not just objects.
However, that turns out to be difficult due to the Ada semantcs of
'Size. In particular, Ada requires 'Size to denote the size of the
representation of the value, so for example Boolean'Size must be 1.
Implementing this properly requires information not readily available
to gdb... and while we could synthesize this information in many
cases, it also seemed to me that this wasn't strictly very useful when
debugging.
So instead, this patch adds support for the 'Object_Size attribute,
which is somewhat closer to 'sizeof'.
Note also that while 'Object_Size is defined for some dynamic types, I
chose not to implement this here, as again this information is not
readily available -- and I think it's preferable to error than to
print something that might be incorrect.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
When running test-case gdb.ada/fixed_points.exp with system gcc 7, I run
into:
...
(gdb) PASS: gdb.ada/fixed_points.exp: scenario=all: print fp4_var / 1
get_compiler_info: gcc-7-5-0
p Float(Another_Fixed) = Float(Another_Delta * 5)^M
No definition of "another_delta" in current context.^M
(gdb) FAIL: gdb.ada/fixed_points.exp: scenario=all: value of another_fixed
...
This is a regression since commit 1411185a57 ("Introduce and use
gnat_version_compare"), which did:
...
# This failed before GCC 10.
- if {$scenario == "all" && [test_compiler_info {gcc-10-*}]} {
+ if {$scenario == "all" && [gnat_version_compare < 10]} {
gdb_test "p Float(Another_Fixed) = Float(Another_Delta * 5)" "true" \
"value of another_fixed"
}
...
Fix this by using gnat_version_compare >= 10 instead.
Tested on x86_64-linux, with gcc 7 - 13.
While testing a modified GNAT, I found that this test in
fun_renaming.exp was returning 0 for GCC 13:
if {[test_compiler_info {gcc-6*}]}
This patch introduces a new, more robust way to check the GNAT
compiler version, and changes the gda.ada tests to use it. A small
update to version_compare was also needed.
Note that, in its current form, this new code won't really interact
well with non-GCC compilers (specifically gnat-llvm). This doesn't
seem like a major issue at this point, though, because gnat-llvm
doesn't properly emit debuginfo yet, and when it does, more changes
will be needed in these tests anyway.
Reviewed-by: Keith Seitz <keiths@redhat.com>
When running test-case gdb.ada/tagged-lookup.exp with target board readnow and
make target check-read1:
...
$ ( cd build/gdb; \
make check-read1 \
RUNTESTFLAGS="--target_board=readnow gdb.ada/tagged-lookup.exp" )
...
I run into:
...
(gdb) PASS: gdb.ada/tagged-lookup.exp: set debug symtab-create 1
print *the_local_var^M
$1 = (n => 2)^M
(gdb) FAIL: gdb.ada/tagged-lookup.exp: only one CU expanded
...
The problem is that the corresponding gdb_test_multiple uses line-by-line
matching (using -lbl) which doesn't work well with the multiline pattern
matching both the prompt and the line before it:
...
-re -wrap ".* = \\\(n => $decimal\\\)" {
...
Fix this by making it a one-line pattern:
...
-re -wrap "" {
...
While we're at it, replace an if-then-pass-else-fail with a gdb_assert.
Tested on aarch64-linux.
I noticed that two tests in gdb.ada/complete.exp are testing the same
thing: the completion of "p pck.inne". The second such test has this
comment:
# A fully qualified package name
I believe the intent here was to test "p pck.inner" (note the trailing
"r"). This patch makes this change.
Test-case gdb.ada/call_pn.exp contains an unconditional xfail, which is only
necessary for gcc 8 and 9.
Fix this by limiting the xfail to those releases.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
With test-case gdb.ada/call_pn.exp and glibc debug info installed, I ran into
this timeout:
...
(gdb) maint expand-symtabs^M
FAIL: gdb.ada/call_pn.exp: maint expand-symtabs (timeout)
...
The timeout was related to running the cpu at base frequency of 400Mhz instead
of boost frequency of 3.5Ghz (efficiency core) or 4.7Ghz (performance core).
But when investigating the test-case I realized that the maint expand-symtabs
could be limited to the source files, so use that to speed up the test-case.
Tested on x86_64-linux.
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
PR testsuite/32177
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32177
The initial motivation for this commit was to allow thread or inferior
specific breakpoints to only be inserted within the appropriate
inferior's program-space. The benefit of this is that inferiors for
which the breakpoint does not apply will no longer need to stop, and
then resume, for such breakpoints. This commit does not make this
change, but is a refactor to allow this to happen in a later commit.
The problem we currently have is that when a thread-specific (or
inferior-specific) breakpoint is created, the thread (or inferior)
number is only parsed by calling find_condition_and_thread_for_sals.
This function is only called for non-pending breakpoints, and requires
that we know the locations at which the breakpoint will be placed (for
expression checking in case the breakpoint is also conditional).
A consequence of this is that by the time we figure out the breakpoint
is thread-specific we have already looked up locations in all program
spaces. This feels wasteful -- if we knew the thread-id earlier then
we could reduce the work GDB does by only looking up locations within
the program space for which the breakpoint applies.
Another consequence of how find_condition_and_thread_for_sals is
called is that pending breakpoints don't currently know they are
thread-specific, nor even that they are conditional! Additionally, by
delaying parsing the thread-id, pending breakpoints can be created for
non-existent threads, this is different to how non-pending
breakpoints are handled, so I can do this:
$ gdb -q ./gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp
Reading symbols from ./gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp...
(gdb) break foo thread 99
Function "foo" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (foo thread 99) pending.
(gdb) r
Starting program: /tmp/gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Error in re-setting breakpoint 1: Unknown thread 99.
[Inferior 1 (process 3329749) exited normally]
(gdb)
GDB only checked the validity of 'thread 99' at the point the 'foo'
location became non-pending. In contrast, if I try this:
$ gdb -q ./gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp
Reading symbols from ./gdb/testsuite/outputs/gdb.multi/pending-bp/pending-bp...
(gdb) break main thread 99
Unknown thread 99.
(gdb)
GDB immediately checks if 'thread 99' exists. I think inconsistencies
like this are confusing, and should be fixed if possible.
In this commit the create_breakpoint function is updated so that the
extra_string, which contains the thread, inferior, task, and/or
condition information, is parsed immediately, even for pending
breakpoints.
Obviously, the condition still can't be validated until the breakpoint
becomes non-pending, but the thread, inferior, and task information
can be pulled from the extra-string, and can be validated early on,
even for pending breakpoints. The -force-condition flag is also
parsed as part of this early parsing change.
There are a couple of benefits to doing this:
1. Printing of breakpoints is more consistent now. Consider creating
a conditional breakpoint before this commit:
(gdb) set breakpoint pending on
(gdb) break pendingfunc if (0)
Function "pendingfunc" not defined.
Breakpoint 1 (pendingfunc if (0)) pending.
(gdb) break main if (0)
Breakpoint 2 at 0x401198: file /tmp/hello.c, line 18.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <PENDING> pendingfunc if (0)
2 breakpoint keep y 0x0000000000401198 in main at /tmp/hello.c:18
stop only if (0)
(gdb)
And after this commit:
(gdb) set breakpoint pending on
(gdb) break pendingfunc if (0)
Function "pendingfunc" not defined.
Breakpoint 1 (pendingfunc) pending.
(gdb) break main if (0)
Breakpoint 2 at 0x401198: file /home/andrew/tmp/hello.c, line 18.
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y <PENDING> pendingfunc
stop only if (0)
2 breakpoint keep y 0x0000000000401198 in main at /home/andrew/tmp/hello.c:18
stop only if (0)
(gdb)
Notice that the display of the condition is now the same for the
pending and non-pending breakpoints.
The same is true for the thread, inferior, or task information in
thread, inferior, or task specific breakpoints; this information is
displayed on its own line rather than being part of the 'What'
field.
2. We can check that the thread exists as soon as the pending
breakpoint is created. Currently there is a weird difference
between pending and non-pending breakpoints when creating a
thread-specific breakpoint.
A pending thread-specific breakpoint only checks its thread when it
becomes non-pending, at which point the thread the breakpoint was
intended for might have exited. Here's the behaviour before this
commit:
(gdb) set breakpoint pending on
(gdb) break foo thread 2
Function "foo" not defined.
Breakpoint 2 (foo thread 2) pending.
(gdb) c
Continuing.
[Thread 0x7ffff7c56700 (LWP 2948835) exited]
Error in re-setting breakpoint 2: Unknown thread 2.
[Inferior 1 (process 2948832) exited normally]
(gdb)
Notice the 'Error in re-setting breakpoint 2: Unknown thread 2.'
line, this was triggered when GDB tried to make the breakpoint
non-pending, and GDB discovers that the thread no longer exists.
Compare that to the behaviour after this commit:
(gdb) set breakpoint pending on
(gdb) break foo thread 2
Function "foo" not defined.
Breakpoint 2 (foo) pending.
(gdb) c
Continuing.
[Thread 0x7ffff7c56700 (LWP 2949243) exited]
Thread-specific breakpoint 2 deleted - thread 2 no longer in the thread list.
[Inferior 1 (process 2949240) exited normally]
(gdb)
Now the behaviour for pending breakpoints is identical to
non-pending breakpoints, the thread specific breakpoint is removed
as soon as the thread the breakpoint is associated with exits.
There is an additional change; when the pending breakpoint is
created prior to this patch we see this line:
Breakpoint 2 (foo thread 2) pending.
While after this patch we get this line:
Breakpoint 2 (foo) pending.
Notice that 'thread 2' has disappeared. This might look like a
regression, but I don't think it is. That we said 'thread 2'
before was just a consequence of the lazy parsing of the breakpoint
specification, while with this patch GDB understands, and has
parsed away the 'thread 2' bit of the spec. If folk think the old
information was useful then this would be trivial to add back in
code_breakpoint::say_where.
As a result of this commit the breakpoints 'extra_string' field is now
only used by bp_dprintf type breakpoints to hold the printf format and
arguments. This string should always be empty for other breakpoint
types. This allows some cleanup in print_breakpoint_location.
In code_breakpoint::code_breakpoint I've changed an error case into an
assert. This is because the error is now handled earlier in
create_breakpoint. As a result we know that by this point, the
extra_string will always be nullptr for anything other than a
bp_dprintf style breakpoint.
The find_condition_and_thread_for_sals function is now no longer
needed, this was previously doing the delayed splitting of the extra
string into thread, task, and condition, but this is now all done in
create_breakpoint, so find_condition_and_thread_for_sals can be
deleted, and the code that calls this in
code_breakpoint::location_spec_to_sals can be removed. With this
update this code would only ever be reached for bp_dprintf style
breakpoints, and in these cases the extra_string should not contain
anything other than format and args.
The most interesting changes are all in create_breakpoint and in the
new file break-cond-parse.c. We have a new block of code early on in
create_breakpoint that is responsible for splitting the extra_string
into its component parts by calling create_breakpoint_parse_arg_string
a function in the new break-cond-parse.c file. This means that some
of the later code can be simplified a little.
The new break-cond-parse.c file implements the splitting up the
extra_string and finding all the parts, as well as some self-tests for
the new function.
Finally, now we know all the breakpoint details, these can be stored
within the breakpoint object if we end up creating a deferred
breakpoint. Additionally, if we are creating a deferred bp_dprintf we
can parse the extra_string to build the printf command.
The implementation here aims to maintain backwards compatibility as
much as possible, this means that:
1. We support abbreviations of 'thread', 'task', and 'inferior' in
some places on the breakpoint line. The handling of abbreviations
has (before this patch) been a little weird, so this works:
(gdb) break *main th 1
And creates a breakpoint at '*main' for thread 1 only, while this
does not work:
(gdb) break main th 1
In this case GDB will try to find the symbol 'main th 1'. This
weirdness exists before and after this patch.
2. The handling of '-force-condition' is odd, if this flag appears
immediately after a condition then it will be treated as part of the
condition, e.g.:
(gdb) break main if 0 -force-condition
No symbol "force" in current context.
But we are fine with these alternatives:
(gdb) break main if 0 thread 1 -force-condition
(gdb) break main -force-condition if 0
Again, this is just a quirk of how the breakpoint line used to be
parsed, but I've maintained this for backward compatibility. During
review it was suggested that -force-condition should become an
actual breakpoint flag (i.e. only valid after the 'break' command
but before the function name), and I don't think that would be a
terrible idea, however, that's not currently a trivial change, and I
think should be done as a separate piece of work. For now, this
patch just maintains the current behaviour.
The implementation works by first splitting the breakpoint condition
string (everything after the location specification) into a list of
tokens, each token has a type and a value. (e.g. we have a THREAD
token where the value is the thread-id string). The list of tokens is
validated, and in some cases, tokens are merged. Then the values are
extracted from the remaining token list.
Consider this breakpoint command:
(gdb) break main thread 1 if argc == 2
The condition string passed to create_breakpoint_parse_arg_string is
going to be 'thread 1 if argc == 2', which is then split into the
tokens:
{ THREAD: "1" } { CONDITION: "argc == 2" }
The thread-id (1) and the condition string 'argc == 2' are extracted
from these tokens and returns back to create_breakpoint.
Now consider this breakpoint command:
(gdb) break some_function if ( some_var == thread )
Here the user wants a breakpoint if 'some_var' is equal to the
variable 'thread'. However, when this is initially parsed we will
find these tokens:
{ CONDITION: "( some_var == " } { THREAD: ")" }
This is a consequence of how we have to try and figure out the
contents of the 'if' condition without actually parsing the
expression; parsing the expression requires that we know the location
in order to lookup the variables by name, and this can't be done for
pending breakpoints (their location isn't known yet), and one of the
points of this work is that we extract things like thread-id for
pending breakpoints.
And so, it is in this case that token merging takes place. We check
if the value of a token appearing immediately after the CONDITION
token looks valid. In this case, does ')' look like a valid
thread-id. Clearly, in this case ')' does not, and so me merge the
THREAD token into the condition token, giving:
{ CONDITION: "( some_var == thread )" }
Which is what we want.
I'm sure that we might still be able to come up with some edge cases
where the parser makes the wrong choice. I think long term the best
way to work around these would be to move the thread, inferior, task,
and -force-condition flags to be "real" command options for the break
command. I am looking into doing this, but can't guarantee if/when
that work would be completed, so this patch should be reviewed assume
that the work will never arrive (though I hope it will).
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
A user noticed that when an Ada program (including the runtime) is
compiled with -flto, then "catch exception" does not work -- even
though setting the equivalent breakpoint by hand does work.
Looking into this, it turns out that GCC puts the exception functions
from the Ada runtime into a CU that uses the C language, not Ada.
Then, when trying to look up the relevant symbol,
lookup_name_info::search_name_hash uses the "verbatim" form of the
symbol name (like "<__gnat_debug_raise_exception>") rather than the
"<>"-less form, causing the symbol not to be found.
This patch fixes the problem in two steps.
First, lookup_name_info::search_name_hash is changed to use the same
hack that language_defn::get_symbol_name_matcher uses. That is, when
the current language is Ada, verbatim-mode lookups are special-cased.
(This is a bit unfortunate; perhaps a better long term approach would
be to promote verbatim mode to a fundamental mode of
lookup_name_info.)
Second, although the above fixes the problem in the Ada language mode,
the code still fails in other languages. However, due to the way
these lookups are coded in ada-lang.c, I think it makes sense to
temporarily set the current language to Ada in
create_ada_exception_catchpoint.
Tested on x86-64 Fedora 38.
A new test case that mimics the -flto scenario is included.
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
While working on a longer series, I needed to make sure this
particular test kept working with -fgnat-encodings=all, so this patch
adds it to the test.
gnat-llvm does not support the -fgnat-encodings flag. This patch
prepares gdb's Ada tests to handle this situation by introducing a new
foreach_gnat_encoding. A subsequent patch may change this to support
gnat-llvm; meanwhile this is a little cleaner anyway.
I noticed that some gdb.ada tests used regular expressions like:
"Continuing\..*$inferior_exited_re.*" \
Here, the "\." should either be "." or "\\." -- "\." is not really
meaningful.
This patch fixes all the cases of this I could find in gdb.ada. In
one test (fun_renaming.exp), using "\\." would result in failures, and
here I rewrote the tests to use -wrap.
Approved-By: Andrew Burgess <aburgess@redhat.com>
gdb.ada/multiarray.exp has a loop that looks like it should run the
test in both 'all' and 'minimal' encodings mode. However, the body of
the loop doesn't actually use the 'flags' variable. This was an
oversight in the original commit.
When running test-case gdb.ada/mi_var_access.exp on arm-linux (debian trixie),
I run into:
...
Expecting: ^(-var-create A_String_Access \* A_String_Access[
]+)?((\^done,name="A_String_Access",numchild="[0-9]+",.*|\^error,msg="Value out of range.".*)[
]+[(]gdb[)]
[ ]*)
-var-create A_String_Access * A_String_Access
^error,msg="Cannot access memory at address 0x4"
(gdb)
FAIL: gdb.ada/mi_var_access.exp: Create varobj (unexpected output)
...
This is similar to the problem fixed by commit c5a72a8d1c ("[gdb/testsuite]
Fix regexp in gdb.ada/mi_var_access.exp").
The problem in both cases is that we're printing an uninitialized variable,
and consequently we can run into various error messages during printing.
Fix this as in the other commit, by accepting the error message.
Tested on arm-linux.
On arm-linux, I run into:
...
PASS: gdb.ada/mi_task_arg.exp: mi runto task_switch.break_me
Expecting: ^(-stack-list-arguments 1[^M
]+)?(\^done,stack-args=\[frame={level="0",args=\[\]},frame={level="1",args=\[{name="<_task>",value="0x[0-9A-Fa-f]+"}(,{name="<_taskL>",value="[0-9]+"})?\]},frame={level="2",args=\[({name="self_id",value="(0x[0-9A-Fa-f]+|<optimized out>)"})?\]},.*[^M
]+[(]gdb[)] ^M
[ ]*)
-stack-list-arguments 1^M
^done,stack-args=[frame={level="0",args=[]},frame={level="1",args=[{name="<_task>",value="0x40bc48"}]},frame={level="2",args=[]}]^M
(gdb) ^M
FAIL: gdb.ada/mi_task_arg.exp: -stack-list-arguments 1 (unexpected output)
...
The problem is that the test-case expects a level 3 frame, but there is none.
This can be reproduced using cli bt:
...
$ gdb -q -batch outputs/gdb.ada/mi_task_arg/task_switch \
-ex "b task_switch.break_me" \
-ex run \
-ex bt
Breakpoint 1 at 0x34b4: file task_switch.adb, line 57.
Thread 3 "my_caller" hit Breakpoint 1, task_switch.break_me () \
at task_switch.adb:57
57 null;
#0 task_switch.break_me () at task_switch.adb:57
#1 0x00403424 in task_switch.caller (<_task>=0x40bc48) at task_switch.adb:51
#2 0xf7f95a08 in ?? () from /lib/arm-linux-gnueabihf/libgnarl-12.so
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
...
The purpose of the test-case is printing the frame at level 1, so I don't
think we should bother about the presence of the frame at level 3.
Fix this by allowing the backtrace to stop at level 2.
Tested on arm-linux.
Approved-By: Luis Machado <luis.machado@arm.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
More of a DWARF-generation non-regression test; fixed on the GCC side
with 2024-06-03 "Implement wrap-around arithmetics in DWARF
expressions" (f3d6d60d2ae).
Approved-By: Tom Tromey <tom@tromey.com>
Some compiler changes I'm working on cause a regression in
gdb.ada/limited-length.exp -- with the changes, the array type is
nameless and so is not mentioned in the max-value-size error message.
Because the array type is nameless in the source code, this seems like
an improvement to me, and so this patch changes the test to accept
either form.
Ada 2022 includes iterated assignment for array initialization. This
patch implements a subset of this for gdb. In particular, only arrays
with integer index types really work -- currently there's no decent
way to get the index type in EVAL_AVOID_SIDE_EFFECTS mode during
parsing. Fixing this probably requires the Ada parser to take a
somewhat more sophisticated approach to type resolution; and while
this would help fix another bug in this area, this patch is already
useful without it.
In an aarch32-linux chroot on an aarch64-linux system, I run into:
...
(gdb) print x^M
$1 = 9223372036854775807^M
(gdb) FAIL: gdb.ada/verylong.exp: print x
...
A passing version on aarch64-linux looks like:
...
(gdb) print x^M
$1 = 170141183460469231731687303715884105727^M
(gdb) PASS: gdb.ada/verylong.exp: print x
...
The difference is caused by the size of the type Long_Long_Long_Integer, which
is:
- a 128-bit signed on 64-bit targets, and
- a 64-bit signed on 32-bit target.
Fix this by detecting the size of the Long_Long_Long_Integer type, and
handling it.
Tested on aarch64-linux and aarch32-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR testsuite/31574
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31574
[1] https://gcc.gnu.org/onlinedocs/gnat_rm/Implementation-Defined-Characteristics.html
With gcc 13, test-case gdb.ada/tagged-lookup.exp passes for me, but with gcc
12, I get:
...
(gdb) set debug symtab-create 1^M
(gdb) print *the_local_var^M
...
$1 = (n => 2)^M
(gdb) FAIL: gdb.ada/tagged-lookup.exp: only one CU expanded
...
The problem is that this fails:
...
-re -wrap ".* = \\\(n => $decimal\\\)" {
if {$found_pck + $found_pck2 == 1} {
pass $gdb_test_name
} else {
fail $gdb_test_name
}
...
because $found_pck == 0 and $found_pck2 == 0.
Indeed, with gcc 13 we have:
...
$ grep "start_subfile: name = .*/tagged-lookup/" gdb.log | sed 's%.*/%%'
b~foo.adb
b~foo.adb
b~foo.adb
b~foo.ads
pck2.adb
pck2.adb
pck2.ads
pck2.adb
pck2.ads
...
and with gcc 12:
...
$ grep "start_subfile: name = .*/tagged-lookup/" gdb.log | sed 's%.*/%%'
b~foo.adb
b~foo.adb
b~foo.adb
b~foo.ads
...
Fix this by checking for "$found_pck + $found_pck2 <= 1" instead.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR testsuite/31514
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31514
I noticed that "info locals" on a certain large Ada program was very
slow. I tracked this down to ada_get_tsd_type expanding nearly every
CU in the program.
This patch fixes the problem by changing this code to use the more
efficient lookup_transparent_type which, unlike the Ada-specific
lookup functions, does not try to find all matching instances.
Note that I first tried fixing this by changing ada_find_any_type, but
this did not work -- I may revisit this approach at some later date.
Also note that the copyright dates on the test files are set that way
because I copied them from another test.
New in v2: the new test failed on the Linaro regression tester.
Looking at the logs, it seems that gdb was picking up a 'value' from
libgnat:
$1 = {<text variable, no debug info>} 0xf7e227a4 <ada.calendar.formatting.value>
This version renames the local variable in an attempt to work around
this.
v3: In v2, while trying to reproduce the problem locally, I
accidentally forgot to commit one of the changes.
ptype is a bit funny, in that it accepts both expressions and type
names. It also evaluates the resulting expression using
EVAL_AVOID_SIDE_EFFECTS -- which both seems sensible (as a user would
you expect ptype to possibly cause inferior execution?), but is also a
historical artifact of how expressions are implemented (there's no
EVAL_FOR_TYPE).
In Ada, calling a function with an array will sometimes result in a
"thick pointer" array descriptor being made. This is essentially a
structure holding a pointer and bounds information.
Currently, in such a callee, printing the type of the array will yield
funny results:
(gdb) print str.all
$1 = "Hello World"
(gdb) ptype str
type = array (<>) of character
(gdb) ptype str.all
type = array (1 .. 0) of character
That "1 .. 0" is the result of an EVAL_AVOID_SIDE_EFFECTS branch
trying to do "something" with an array descriptor, without doing too
much.
I tried briefly to make this code really dereference the array
descriptor and get the correct runtime type. However, that proved to
be tricky; it certainly can't be done for all access types, because
that will cause dynamic type resolution and end up printing just the
runtime type -- which with variants may be pretty far from what the
user may expect.
Instead, this patch arranges to just leave such types alone in this
situation. I don't think this should have an extra effects, because
things like array subscripting still work on thick pointers.
This patch also touches arrayptr.exp, because in that case the access
type is a "thin pointer", and this ensures that the output does not
change in that scenario.
commit f18fc7e5 ("gdb, types: Resolve pointer types dynamically")
caused a regression on a test case in the AdaCore internal test suite.
The issue here is that gdb would try to resolve the type of a dynamic
pointer that happened to be NULL. In this case, the "Location address
is not set." error would end up being thrown from the DWARF expression
evaluator.
I think it makes more sense to special-case NULL pointers and not try
to resolve their target type, as that type can't really be accessed
anyway.
This patch implements this idea, and also adds the missing Ada test
case.
The "python" command (and the Python implementation of the gdb
"source" command) does not handle Python exceptions in the same way as
other gdb-facing Python code. In particular, exceptions are turned
into a generic error rather than being routed through
gdbpy_handle_exception, which takes care of converting to 'quit' as
appropriate.
I think this was done this way because PyRun_SimpleFile and friends do
not propagate the Python exception -- they simply indicate that one
occurred.
This patch reimplements these functions to respect the general gdb
convention here. As a bonus, some Windows-specific code can be
removed, as can the _execute_file function.
The bulk of this change is tweaking the test suite to match the new
way that exceptions are displayed. These changes are largely
uninteresting. However, it's worth pointing out the py-error.exp
change. Here, the failure changes because the test changes the host
charset to something that isn't supported by Python. This then
results in a weird error in the new setup.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31354
Acked-By: Tom de Vries <tdevries@suse.de>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
When building gdb with -O0 -fsanitize=address, and running test-case
gdb.ada/uninitialized_vars.exp, I run into:
...
(gdb) info locals
a = 0
z = (a => 1, b => false, c => 2.0)
=================================================================
==66372==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x602000097f58 at pc 0xffff52c0da1c bp 0xffffc90a1d40 sp 0xffffc90a1d80
READ of size 4 at 0x602000097f58 thread T0
#0 0xffff52c0da18 in memmove (/lib64/libasan.so.8+0x6da18)
#1 0xbcab24 in unsigned char* std::__copy_move_backward<false, true, std::random_access_iterator_tag>::__copy_move_b<unsigned char const, unsigned char>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:748
#2 0xbc9bf4 in unsigned char* std::__copy_move_backward_a2<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:769
#3 0xbc898c in unsigned char* std::__copy_move_backward_a1<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:778
#4 0xbc715c in unsigned char* std::__copy_move_backward_a<false, unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:807
#5 0xbc4e6c in unsigned char* std::copy_backward<unsigned char const*, unsigned char*>(unsigned char const*, unsigned char const*, unsigned char*) /usr/include/c++/13/bits/stl_algobase.h:867
#6 0xbc2934 in void gdb::copy<unsigned char const, unsigned char>(gdb::array_view<unsigned char const>, gdb::array_view<unsigned char>) gdb/../gdbsupport/array-view.h:223
#7 0x20e0100 in value::contents_copy_raw(value*, long, long, long) gdb/value.c:1239
#8 0x20e9830 in value::primitive_field(long, int, type*) gdb/value.c:3078
#9 0x20e98f8 in value_field(value*, int) gdb/value.c:3095
#10 0xcafd64 in print_field_values gdb/ada-valprint.c:658
#11 0xcb0fa0 in ada_val_print_struct_union gdb/ada-valprint.c:857
#12 0xcb1bb4 in ada_value_print_inner(value*, ui_file*, int, value_print_options const*) gdb/ada-valprint.c:1042
#13 0xc66e04 in ada_language::value_print_inner(value*, ui_file*, int, value_print_options const*) const (/home/vries/gdb/build/gdb/gdb+0xc66e04)
#14 0x20ca1e8 in common_val_print(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1092
#15 0x20caabc in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1184
#16 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
#17 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
#18 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
#19 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
#20 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
#21 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
#22 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
#23 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
#24 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
#25 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
#26 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
#27 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
#28 0x1384080 in command_handler(char const*) gdb/event-top.c:566
#29 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
#30 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
#31 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
#32 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
#33 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
#34 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
#35 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
#36 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
#37 0x35ff9d8 in gdb_wait_for_event gdbsupport/event-loop.cc:694
#38 0x35fd284 in gdb_do_one_event(int) gdbsupport/event-loop.cc:264
#39 0x1768080 in start_event_loop gdb/main.c:408
#40 0x17684c4 in captured_command_loop gdb/main.c:472
#41 0x176cfc8 in captured_main gdb/main.c:1342
#42 0x176d088 in gdb_main(captured_main_args*) gdb/main.c:1361
#43 0xb73edc in main gdb/gdb.c:39
#44 0xffff519b09d8 in __libc_start_call_main (/lib64/libc.so.6+0x309d8)
#45 0xffff519b0aac in __libc_start_main@@GLIBC_2.34 (/lib64/libc.so.6+0x30aac)
#46 0xb73c2c in _start (/home/vries/gdb/build/gdb/gdb+0xb73c2c)
0x602000097f58 is located 0 bytes after 8-byte region [0x602000097f50,0x602000097f58)
allocated by thread T0 here:
#0 0xffff52c65218 in calloc (/lib64/libasan.so.8+0xc5218)
#1 0xcbc278 in xcalloc gdb/alloc.c:97
#2 0x35f21e8 in xzalloc(unsigned long) gdbsupport/common-utils.cc:29
#3 0x20de270 in value::allocate_contents(bool) gdb/value.c:937
#4 0x20edc08 in value::fetch_lazy() gdb/value.c:4033
#5 0x20dadc0 in value::entirely_covered_by_range_vector(std::vector<range, std::allocator<range> > const&) gdb/value.c:229
#6 0xcb2298 in value::entirely_optimized_out() gdb/value.h:560
#7 0x20ca6fc in value_check_printable gdb/valprint.c:1133
#8 0x20caa8c in common_val_print_checked(value*, ui_file*, int, value_print_options const*, language_defn const*) gdb/valprint.c:1182
#9 0x196c524 in print_variable_and_value(char const*, symbol*, frame_info_ptr, ui_file*, int) gdb/printcmd.c:2355
#10 0x1d99ca0 in print_variable_and_value_data::operator()(char const*, symbol*) gdb/stack.c:2308
#11 0x1dabca0 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::operator()(gdb::fv_detail::erased_callable, char const*, symbol*) const gdb/../gdbsupport/function-view.h:305
#12 0x1dabd14 in gdb::function_view<void (char const*, symbol*)>::bind<print_variable_and_value_data>(print_variable_and_value_data&)::{lambda(gdb::fv_detail::erased_callable, char const*, symbol*)#1}::_FUN(gdb::fv_detail::erased_callable, char const*, symbol*) gdb/../gdbsupport/function-view.h:299
#13 0x1dab34c in gdb::function_view<void (char const*, symbol*)>::operator()(char const*, symbol*) const gdb/../gdbsupport/function-view.h:289
#14 0x1d9963c in iterate_over_block_locals gdb/stack.c:2240
#15 0x1d99790 in iterate_over_block_local_vars(block const*, gdb::function_view<void (char const*, symbol*)>) gdb/stack.c:2259
#16 0x1d9a598 in print_frame_local_vars gdb/stack.c:2380
#17 0x1d9afac in info_locals_command(char const*, int) gdb/stack.c:2458
#18 0xfd7b30 in do_simple_func gdb/cli/cli-decode.c:95
#19 0xfe5a2c in cmd_func(cmd_list_element*, char const*, int) gdb/cli/cli-decode.c:2735
#20 0x1f03790 in execute_command(char const*, int) gdb/top.c:575
#21 0x1384080 in command_handler(char const*) gdb/event-top.c:566
#22 0x1384e2c in command_line_handler(std::unique_ptr<char, gdb::xfree_deleter<char> >&&) gdb/event-top.c:802
#23 0x1f731e4 in tui_command_line_handler gdb/tui/tui-interp.c:104
#24 0x1382a58 in gdb_rl_callback_handler gdb/event-top.c:259
#25 0x21dbb80 in rl_callback_read_char readline/readline/callback.c:290
#26 0x1382510 in gdb_rl_callback_read_char_wrapper_noexcept gdb/event-top.c:195
#27 0x138277c in gdb_rl_callback_read_char_wrapper gdb/event-top.c:234
#28 0x1fe9b40 in stdin_event_handler gdb/ui.c:155
#29 0x35ff1bc in handle_file_event gdbsupport/event-loop.cc:573
SUMMARY: AddressSanitizer: heap-buffer-overflow (/lib64/libasan.so.8+0x6da18) in memmove
...
The error happens when trying to print either variable y or y2:
...
type Variable_Record (A : Boolean := True) is record
case A is
when True =>
B : Integer;
when False =>
C : Float;
D : Integer;
end case;
end record;
Y : Variable_Record := (A => True, B => 1);
Y2 : Variable_Record := (A => False, C => 1.0, D => 2);
...
when the variables are uninitialized.
The error happens only when printing the entire variable:
...
(gdb) p y.a
$2 = 216
(gdb) p y.b
There is no member named b.
(gdb) p y.c
$3 = 9.18340949e-41
(gdb) p y.d
$4 = 1
(gdb) p y
<AddressSanitizer: heap-buffer-overflow>
...
The error happens as follows:
- field a functions as discriminant, choosing either the b, or c+d variant.
- when y.a happens to be set to 216, as above, gdb interprets this as the
variable having the c+d variant (which is why trying to print y.b fails).
- when printing y, gdb allocates a value, copies the bytes into it from the
target, and then prints the value.
- gdb allocates the value using the type size, which is 8. It's 8 because
that's what the DW_AT_byte_size indicates. Note that for valid values of a,
it gives correct results: if a is 0 (c+d variant), size is 12, if a is 1
(b variant), size is 8.
- gdb tries to print field d, which is at an 8 byte offset, and that results
in a out-of-bounds access for the allocated 8-byte value.
Fix this by handling this case in value::contents_copy_raw, such that we have:
...
(gdb) p y
$1 = (a => 24, c => 9.18340949e-41,
d => <error reading variable: access outside bounds of object>)
...
An alternative (additional) fix could be this: in compute_variant_fields_inner
gdb reads the discriminant y.a to decide which variant is active. It would be
nice to detect that the value (y.a == 24) is not a valid Boolean, and give up
on choosing a variant altoghether. However, the situation regarding the
internal type CODE_TYPE_BOOL is currently ambiguous (see PR31282) and it's not
possible to reliably decide what valid values are.
The test-case source file gdb.ada/uninitialized-variable-record/parse.adb is
a reduced version of gdb.ada/uninitialized_vars/parse.adb, so it copies the
copyright years.
Note that the test-case needs gcc-12 or newer, it's unsupported for older gcc
versions. [ So, it would be nice to rewrite it into a dwarf assembly
test-case. ]
The test-case loops over all languages. This is inherited from an earlier
attempt to fix this, which had language-specific fixes (in print_field_values,
cp_print_value_fields, pascal_object_print_value_fields and
f_language::value_print_inner). I've left this in, but I suppose it's not
strictly necessary anymore.
Tested on x86_64-linux.
PR exp/31258
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31258
This patch changes the DWARF reader to use the new symbol domains. It
also adjusts many bits of associated code to adapt to this change.
The non-DWARF readers are updated on a best-effort basis. This is
somewhat simpler since most of them only support C and C++. I have no
way to test a few of these.
I went back and forth a few times on how to handle the "tag"
situation. The basic problem is that C has a special namespace for
tags, which is separate from the type namespace. Other languages
don't do this. So, the question is, should a DW_TAG_structure_type
end up in the tag domain, or the type domain, or should it be
language-dependent?
I settled on making it language-dependent using a thought experiment.
Suppose there was a Rust compiler that only emitted nameless
DW_TAG_structure_type objects, and specified all structure type names
using DW_TAG_typedef. This DWARF would be correct, in that it
faithfully represents the source language -- but would not work with a
purely struct-domain implementation in gdb. Therefore gdb would be
wrong.
Now, this approach is a little tricky for C++, which uses tags but
also enters a typedef for them. I notice that some other readers --
like stabsread -- actually emit a typedef symbol as well. And, I
think this is a reasonable approach. It uses more memory, but it
makes the internals simpler. However, DWARF never did this for
whatever reason, and so in the interest of keeping the series slightly
shorter, I've left some C++-specific hacks in place here.
Note that this patch includes language_minimal as a language that uses
tags. I did this to avoid regressing gdb.dwarf2/debug-names-tu.exp,
which doesn't specify the language for a type unit. Arguably this
test case is wrong.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30164
A user found that gdb would not correctly print a field from an Ada
record using the scalar storage order feature. We tracked this down
to a combination of problems.
First, GCC did not emit DW_AT_endianity on the enumeration type.
DWARF does not specify this, but it is an obvious and harmless
extension. This was fixed in GCC recently:
https://gcc.gnu.org/pipermail/gcc-patches/2024-January/642347.htmlhttps://gcc.gnu.org/git/?p=gcc.git;a=commit;h=5d8b60effc7268448a94fbbbad923ab6871252cd
Second, GDB did not handle this attribute on enumeration types. This
patch makes this change and adds a test case that will pass with the
patched GCC.
So far, the GCC patch isn't on the gcc-13 branch; but if it ever goes
in, the test case in this patch can be updated to reflect that.
Reviewed-By: Keith Seitz <keiths@redhat.com>
This commit is the result of the following actions:
- Running gdb/copyright.py to update all of the copyright headers to
include 2024,
- Manually updating a few files the copyright.py script told me to
update, these files had copyright headers embedded within the
file,
- Regenerating gdbsupport/Makefile.in to refresh it's copyright
date,
- Using grep to find other files that still mentioned 2023. If
these files were updated last year from 2022 to 2023 then I've
updated them this year to 2024.
I'm sure I've probably missed some dates. Feel free to fix them up as
you spot them.
Currently, the overload handling in Ada assumes that any two array
types are compatible. However, this is obviously untrue, and a user
reported an oddity where comparing two Ada strings resulted in a call
to the "=" function for packed boolean arrays.
This patch improves the situation somewhat, by requiring that the two
arrays have the same arity and compatible base element types. This is
still over-broad, but it seems safe and is better than the status quo.
Commit cff7135813 ("gdb/testsuite: tighten up some end-of-line patterns") replaced:
...
set eol "\[\r\n\]+"
...
with the more strict:
...
set eol "\r\n"
...
in a few test-cases, but didn't update all uses of eol accordingly.
Fix this in three gdb.ada test-cases.
Tested on x86_64-linux.
Approved-By: Andrew Burgess <aburgess@redhat.com>
Following on from the previous commit, I searched the testsuite for
places where we did:
set eol "<some pattern>"
in most cases the <some pattern> could be replaced with "\r\n" though
in the stabs test I've switched to using the multi_line proc as that
seemed like a better choice.
In gdb.ada/info_types.exp I did need to add an extra use of $eol as
the previous pattern would match multiple newlines, and in this one
place we were actually expecting to match multiple newlines. The
tighter pattern only matches a single newline, so we now need to be
explicit when multiple newlines are expected -- I think this is a good
thing.
All the tests are still passing for me after these changes.
Approved-By: Tom Tromey <tom@tromey.com>
While reviewing another patch I spotted a timeout in
gdb.ada/complete.exp when testing in READ1 mode, e.g.:
$ make check-read1 TESTS="gdb.ada/complete.exp"
...
FAIL: gdb.ada/complete.exp: complete break ada (timeout)
...
The problem is an attempt to match the entire output from GDB within a
single gdb_test_multiple pattern, for a completion command that
returns a large number of completions.
This commit changes the gdb_test_multiple to process the output line
by line. I don't use the gdb_test_multiple -lbl option, as I've
always found that option backward -- it checks for the \r\n at the
start of each line rather than the end, I think it's much clearer to
use '^' at the start of each pattern, and '\r\n' at the end, so that's
what I've done here.
.... Or I would, if this test didn't already define $eol as the end of
line regexp ... except that $eol was set to '[\r\n]*', which isn't
that helpful, so I've updated $eol to be just '\r\n' the actual end of
line regexp.
And now, the test passes without a timeout when using READ1.
There should be no change in what is tested after this commit.
Approved-By: Tom Tromey <tom@tromey.com>
Function Create_large returns a large data structure. On PowerPC, register
r3 contains the address of where the data structure to be returned is to
be stored. However, on exit the ABI does not guarantee that r3 has not
been changed. The GDB finish command prints the return value of the
function at the end of the function. GDB needs to use the
DW_TAG_call_site information to determine the value of r3 on entry to
the function to correctly print the return value at the end of the
function. The test must be compiled with -fvar-tracking for the
DW_TAG_call_site information to be included in the executable file.
This patch adds the -fvar-tracking option to the compile line if the
option is supported.
The patch fixes the one regression error for the test on PowerPC.
The patch has been tested on Power 10 and X86-64 with no regressions.
The original intention of the test appears to be checking to make sure
setting a breakpoint in an inlined function didn't set multiple
breakpoints where one of them was at address 0.
The gdb.ada/inline-section-gc.exp test may pass or fail depending on the
version of gnat. Per the discussion on IRC, the ada inlining appears to
have some target dependencies. In this test there are two functions,
callee and caller. Function calee is inlined into caller. The test sets
a breakpoint in function callee. The reported location where the
breakpoint is set may be at the requested location in callee or the
location in caller after callee has been inlined. The test needs to
accept either location as correct provided the breakpoint address is not
zero.
This patch checks to see if the reported breakpoint is in function callee
or function caller and fails if the breakpoint address is 0x0. The line
number where the breakpoint is set will match the requested line if the
breakpoint location is reported is callee.adb. If the breakpoint is
reported in caller.adb, the line number in caller is the breakpoint
location in callee where it is inlined into caller.
This patch fixes the single regression failure for the test on PowerPC.
It does not introduce any failures on X86-64.
Simon pointed out that the new file-then-restart.exp test fails with
the extended-remote target board.
The problem is that the test suite doesn't use gdb_file_cmd -- which
handles things like "set remote exec-file". This patch changes
gdb_file_cmd to make the "kill" command optional, and then switches
the test case to use it.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30933
Approved-By: Simon Marchi <simon.marchi@efficios.com>
Following on Tom de Vries' work in the other array-printers, this
patch changes val_print_packed_array_elements to also avoid allocating
too many values when printing an Ada packed array.
When running test-case gdb.ada/import.exp with gcc 7, most test fail:
...
FAIL: gdb.ada/import.exp: print imported_var_ada
FAIL: gdb.ada/import.exp: print local_imported_var
FAIL: gdb.ada/import.exp: print pkg.imported_var_ada
FAIL: gdb.ada/import.exp: print pkg.exported_var_ada
FAIL: gdb.ada/import.exp: print exported_var_ada
FAIL: gdb.ada/import.exp: gdb_breakpoint: set breakpoint at pkg.imported_func_ada
FAIL: gdb.ada/import.exp: gdb_breakpoint: set breakpoint at imported_func_ada
FAIL: gdb.ada/import.exp: gdb_breakpoint: set breakpoint at local_imported_func
...
When running with gcc 8 or 9, only 2 tests fail:
...
FAIL: gdb.ada/import.exp: gdb_breakpoint: set breakpoint at pkg.imported_func_ada
FAIL: gdb.ada/import.exp: gdb_breakpoint: set breakpoint at imported_func_ada
...
The test-case passes fully with gcc 10, 11, 12 and 13.
Debug info for pragma import seems to not have been supported before gcc 8, so
require that version.
The two FAILs with gcc 8 and 9 seem to be due to problems in debug info. Add
an xfail for these.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
With gcc 13.2.1, I run into a cluster of fails:
...
FAIL: gdb.ada/str_binop_equal.exp: print my_str = "ABCD"
FAIL: gdb.ada/widewide.exp: print my_wws = " helo"
FAIL: gdb.ada/widewide.exp: print my_ws = "wide"
...
The problem is that the debug info contains information about function
ada.strings.maps."=", and gdb uses it to implement the comparison.
The function is supposed to compare two char sets, not strings, so gdb
shouldn't use it. This is PR ada/30908.
I don't see the same problem with gcc 7.5.0, because the exec doesn't contain
the debug info for the function, because the corresponding object is not
linked in. Adter adding "with Ada.Strings.Maps; use Ada.Strings.Maps;" to
gdb.ada/widewide/foo.adb I run into the same problem with gcc 7.5.0.
Add KFAILs for the PR.
Tested on x86_64-linux:
- openSUSE Leap 15.4 (using gcc 7.5.0), and
- openSUSE Tumbleweed (using gcc 13.2.1).
Approved-By: Tom Tromey <tom@tromey.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30908
When running test-case gdb.ada/mi_task_arg.exp on openSUSE Tumbleweed using
gcc 13.2.1, I run into (layout adapted for readability):
...
-stack-list-arguments 1^M
^done,stack-args=[
frame={level="0",args=[]},
frame={level="1",args=[{name="<_task>",value="0x464820"},
{name="<_taskL>",value="129"}]},
frame={level="2",args=[{name="self_id",value="0x464840"}]},
frame={level="3",args=[]},
frame={level="4",args=[]}
]^M
(gdb) ^M
FAIL: gdb.ada/mi_task_arg.exp: -stack-list-arguments 1 (unexpected output)
...
On openSUSE Leap 15.4 with gcc 7.5.0 I get instead:
...
-stack-list-arguments 1^M
^done,stack-args=[
frame={level="0",args=[]},
frame={level="1",args=[{name="<_task>",value="0x444830"}]},
frame={level="2",args=[{name="self_id",value="0x444850"}]},
frame={level="3",args=[]},
frame={level="4",args=[]}]^M
(gdb) ^M
PASS: gdb.ada/mi_task_arg.exp: -stack-list-arguments 1
...
The difference in gdb output is due to difference in the dwarf generated by
the compiler, so I don't see a problem with gdb here.
Fix this by updating the test-case to accept this output.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
I've been running the test-suite on an i686-linux laptop with 1GB of memory,
and 1 GB of swap, and noticed problems after running gdb.base/huge.exp: gdb
not being able to spawn for a large number of test-cases afterwards.
So I investigated the memory usage, on my usual x86_64-linux development
platform.
The test-case is compiled with -DCRASH_GDB=2097152, so this:
...
static int a[CRASH_GDB], b[CRASH_GDB];
...
with sizeof (int) == 4 represents two arrays of 8MB each.
Say we add a loop around the "print a" command and print space usage
statistics:
...
gdb_test "maint set per-command space on"
for {set i 0} {$i < 100} {incr i} {
gdb_test "print a"
}
...
This gets us:
...
(gdb) print a^M
$1 = {0 <repeats 2097152 times>}^M
Space used: 478248960 (+469356544 for this command)^M
(gdb) print a^M
$2 = {0 <repeats 2097152 times>}^M
Space used: 486629376 (+8380416 for this command)^M
(gdb) print a^M
$3 = {0 <repeats 2097152 times>}^M
Space used: 495009792 (+8380416 for this command)^M
...
(gdb) print a^M
$100 = {0 <repeats 2097152 times>}^M
Space used: 1308721152 (+8380416 for this command)^M
...
In other words, we start out at 8MB, and the first print costs us about 469MB,
and subsequent prints 8MB, which accumulates to 1.3 GB usage. [ On the
i686-linux laptop, the first print costs us 335MB. ]
The subsequent 8MBs are consistent with the values being saved into the value
history, but the usage for the initial print seems somewhat excessive.
There is a PR open about needing sparse representation of large arrays
(PR8819), but this memory usage points to an independent problem.
The function value_print_array_elements contains a scoped_value_mark to free
allocated values in the outer loop, but it doesn't prevent the inner loop from
allocating a lot of values.
Fix this by adding a scoped_value_mark in the inner loop, after which we have:
...
(gdb) print a^M
$1 = {0 <repeats 2097152 times>}^M
Space used: 8892416 (+0 for this command)^M
(gdb) print a^M
$2 = {0 <repeats 2097152 times>}^M
Space used: 8892416 (+0 for this command)^M
(gdb) print a^M
$3 = {0 <repeats 2097152 times>}^M
Space used: 8892416 (+0 for this command)^M
...
(gdb) print a^M
$100 = {0 <repeats 2097152 times>}^M
Space used: 8892416 (+0 for this command)^M
...
Note that the +0 here just means that the mallocs did not trigger an sbrk.
This is dependent on malloc (which can use either mmap or sbrk or some
pre-allocated memory) and will likely vary between different tunings, versions
and implementations, so this does not give us a reliable way detect the
problem in a minimal way.
A more reliable way of detecting the problem is:
...
void
value_free_to_mark (const struct value *mark)
{
+ size_t before = all_values.size ();
auto iter = std::find (all_values.begin (), all_values.end (), mark);
if (iter == all_values.end ())
all_values.clear ();
else
all_values.erase (iter + 1, all_values.end ());
+ size_t after = all_values.size ();
+ if (before - after >= 1024)
+ fprintf (stderr, "value_free_to_mark freed %zu items\n", before - after);
...
which without the fix tells us:
...
+print a
value_free_to_mark freed 2097152 items
$1 = {0 <repeats 2097152 times>}
...
Fix a similar problem for Fortran:
...
+print array1
value_free_to_mark freed 4194303 items
$1 = (0, <repeats 2097152 times>)
...
in fortran_array_printer_impl::process_element.
The problem also exists for Ada:
...
+print Arr
value_free_to_mark freed 2097152 items
$1 = (0 <repeats 2097152 times>)
...
but is fixed by the fix for C.
Add Fortran and Ada variants of the test-case. The *.exp files are similar
enough to the original to keep the copyright years range.
While writing the Fortran test-case, I ran into needing an additional print
setting to print the entire array in repeat form, filed as PR exp/30817.
I managed to apply the compilation loop for the Ada variant as well, but with
a cumbersome repetition style. I noticed no other test-case uses gnateD, so
perhaps there's a better way of implementing this.
The regression test included in the patch is formulated in its weakest
form, to avoid false positive FAILs, which also means that smaller regressions
may not get detected.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
When running test-case gdb.ada/arr_acc_idx_w_gap.exp with target board
cc-with-dwz, I run into:
...
(gdb) print enum_with_gaps'enum_rep(lit3)^M
'Enum_Rep requires argument to have same type as enum^M
(gdb) FAIL: gdb.ada/arr_acc_idx_w_gap.exp: enum_rep
...
With target_board unix, we have instead:
...
(gdb) print enum_with_gaps'enum_rep(lit3)^M
$16 = 13^M
(gdb) PASS: gdb.ada/arr_acc_idx_w_gap.exp: enum_rep
...
Conversely, when I add this test to the test-case:
...
gdb_test "print enum_with_gaps'enum_rep(lit3)" " = 13" \
"enum_rep"
+ gdb_test "print enum_subrange'enum_rep(lit3)" " = 13" \
+ "other enum_rep"
...
the extra test passes with target board cc-with-dwz, but fails with target
board unix.
The problem is here in remove_extra_symbols:
...
if (symbols_are_identical_enums (syms))
syms.resize (1);
...
where one of the two identical enums is picked before the enum_rep handling
can resolve lit3 to one of the two.
Fix this by moving the code to ada_resolve_variable.
Tested on x86_64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR ada/30726
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=30726
Test-case gdb.ada/same_enum.exp is supposed to be a regression test for this
bit of code in remove_extra_symbols:
...
if (symbols_are_identical_enums (syms))
syms.resize (1);
...
The test-case does "print red" and expects one of these two choices to be
picked by remove_extra_symbols:
...
type Color is (Black, Red, Green, Blue, White);
type RGB_Color is new Color range Red .. Blue;
...
but because only the type Color is used:
...
FC : Color := Red;
SC : Color := Green;
...
the RGB_Color type is eliminated from the debug info, and consequently
remove_extra_symbols has no effect for the test-case.
In other words, we have:
...
(gdb) ptype Color ^M
type = (black, red, green, blue, white)^M
(gdb) ptype RGB_Color^M
No definition of "rgb_color" in current context.^M
...
Fix this by changing the type of SC to RGB_Color, and add prints of the two
types to check that they're both available.
With the test-case fixed, if we disable the bit of code in
remove_extra_symbols we get:
...
(gdb) print red^M
Multiple matches for red^M
[0] cancel^M
[1] pck.color'(pck.red) (enumeral)^M
[2] pck.rgb_colorB'(pck.red) (enumeral)^M
> FAIL: gdb.ada/same_enum.exp: print red (timeout)
...
in other words, the test-case now properly functions as a regression test.
Tested on x86_64-linux.
An upstream bug report points out this bug: if the user switches from
one Ada executable to another without "kill"ing the inferior, then the
"start" command will fail.
What happens here is that the Ada "main" name is found in a constant
string in the executable. But, if the inferior is running, then the
process_stratum target reads from the inferior memory.
This patch fixes the problem by changing the main name code to set
trust-readonly-sections, causing the target stack to read from the
executable instead.
I looked briefly at changing GNAT to emit DW_AT_main_subprogram
instead, but this looks to be pretty involved.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=25811