GDB deprecated the commands "show/set mpx bound" in GDB 15.1, as Intel
listed Intel(R) Memory Protection Extensions (MPX) as removed in 2019.
MPX is also deprecated in gcc (since v9.1), the linux kernel (since v5.6)
and glibc (since v2.35). Let's now remove MPX support in GDB completely.
This includes the removal of:
- MPX functionality including register support
- deprecated mpx commands
- i386 and amd64 implementation of the hooks report_signal_info and
get_siginfo_type
- tests
- and pretty printer.
We keep MPX register numbers to not break compatibility with old gdbservers.
Approved-By: Felix Willgerodt <felix.willgerodt@intel.com>
Removing the pretty printer (bound_registers.py) in the next commit
leads to failures due to a missing import of 'gdb.printing':
"AttributeError: module 'gdb' has no attribute 'printing'".
Add this import to each file requiring it, as it's not imported by the
pretty-printer anymore.
Approved-By: Andrew Burgess <aburgess@redhat.com>
PR python/32163 points out that various types provided by gdb are not
added to the gdb module, so they aren't available for interactive
inspection. I think this is just an oversight.
This patch fixes the problem by introducing a new helper function that
both readies the type and then adds it to the appropriate module. The
patch also poisons PyType_Ready, the idea being to avoid this bug in
the future.
v2:
* Fixed a bug in original patch in gdb.Architecture registration
* Added regression test for the types mentioned in the bug
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32163
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
On a system with python 3.6, module gdb.missing_debug imports module curses,
so when running test-case gdb.python/py-missing-debug.exp on a system without
that module installed, we run into:
...
(gdb) source py-missing-debug.py^M
Python Exception <class 'ImportError'>: Module 'curses' is not installed.^M
Use:^M
sudo zypper install python36-curses^M
to install it.^M
Error occurred in Python: Module 'curses' is not installed.^M
Use:^M
sudo zypper install python36-curses^M
to install it.^M
(gdb) FAIL: gdb.python/py-missing-debug.exp: source python script
...
Fix this by issuing UNSUPPORTED instead, and bailing out.
Tested on x86_64-linux.
Approved-by: Kevin Buettner <kevinb@redhat.com>
PR testsuite/31576
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31576
When debugging ROCm code, you might have something like this:
__global__ void kernel ()
{
...
// break here
...
}
int main ()
{
// Code to call `kernel`
}
... where kernel is a function compiled to execute on the GPU. It does
not exist in the host x86-64 program that runs the main function, and
GDB doesn't know about that function until it is called, at which point
the runtime loads the corresponding code object and GDB learns about the
code of the "kernel" function. Before the GPU code object is loaded,
from the point of view of GDB, you might as well have blank lines
instead of the "kernel" function. The DWARF in the host program doesn't
describe anything at these lines.
So, a common problem that users face is:
- Start GDB with the host binary
- Place a breakpoint by line number at the "break here" line
- At this point, GDB only knows about the host code, the lines of the
`kernel` function are a big void.
- GDB finds no code mapped to the "break here" line and searches for
the first following line that has code mapped to it.
- GDB finds that the line with the opening bracket of the `main`
function (or around there) has code mapped to it, places breakpoint
there.
- User runs the program.
- The programs hits the breakpoint at the start of main.
- User is confused, because they didn't ask for a breakpoint in main.
If they continue, the code object eventually gets loaded, GDB reads the
debug info from it, re-evaluates the breakpoint locations, and at this
point the breakpoint is placed at the expected location.
The goal of this patch is to get rid of this annoyance.
A case similar to the one shown above can actually be simulated without
GPU-specific code: using a single source file to generate a library and
an executable loading that library (see the new test
gdb.linespec/line-breakpoint-outside-function.c for an example). Before
the library is loaded, trying to place a breakpoint in the library code
results in the breakpoint "drifting" down to the main function.
To address this problem, make it so that when a user requests a
breakpoint outside a function, GDB makes a pending breakpoint, rather
than placing a breakpoint at the next line with code, which happens to
be in the next function. When the GPU kernel or shared library gets
loaded, the breakpoint resolves to a location in the kernel or library.
Note that we still want breakpoints placed inside a function to
"drift" down to the next line with code. For example, here:
9
10 void foo()
11 {
12 int x;
13
14 x++;
There is probably no code associated to lines 10, 12 and 13, but the
user can still reasonably expect to be able to put a breakpoint there.
In my experience, GCC maps the function prologue to the line with the
opening curly bracket, so the user will be able to place a breakpoint
there anyway (line 11 in the example). But I don't really see a use
case to put a breakpoint above line 10 and expect to get a breakpoint in
foo. So I think that is a reasonable behavior change for GDB.
This is implemented using the following heuristic:
- If a breakpoint is requested at line L but there is no code mapped to
L, search for a following line with associated code (this already
exists today).
- However, if:
1. the found location falls in a function symbol's block
2. the found location's address is equal the entry PC of that
function
3. the found location's line is greater that the requested line
... then we don't place a breakpoint at the found location, we will
end up with a pending breakpoint.
Change the message "No line X in file..." to "No compiled code for line
X in file...". There is clearly a line 9 in the example above, so it
would be weird to say "No line 9 in file...". What we mean is that
there is no code associated to line 9.
All the regressions that I found this patch to cause were:
1. tests specifically this behavior where placing a breakpoint before
a function results in a breakpoint on that function, in which case I
removed the tests or changed them to expect a pending breakpoint
2. linespec tests expecting things like "break -line N garbage" to
error out because of the following garbage, but we now got a
different error because line N now doesn't resolve to something
anymore. For example, before:
(gdb) break -line 3 if foofoofoo == 1
No symbol "foofoofoo" in current context.
became
(gdb) break -line 3 if foofoofoo == 1
No line 3 in the current file.
These tests were modified to refer to a valid line with code, so
that we can still test what we intended to test.
Notes:
- The CUDA compiler "solves" this problem by adding dummy function
symbols between functions, that are never called. So when you try to
insert a breakpoint in the not-yet-loaded kernel, the breakpoint
still drifts, but is placed on some dummy symbol. For reasons that
would be too long to explain here, the ROCm compiler does not do
that, and it is not a desirable option.
- You can have constructs like this:
void host_function()
{
struct foo
{
static void __global__ kernel ()
{
// Place breakpoint here
}
};
// Host code that calls `kernel`
}
The heuristic won't work then, as the breakpoint will drift somewhere
inside the enclosing function, but won't be at the start of that
function. So a bogus breakpoint location will be created on the host
side. I don't think that people are going to use this kind of
construct often though, so we can probably ignore it (or at least it
shouldn't prevent making the more common case better).
ROCm doesn't support passing a lambda kernel function to
hipLaunchKernelGGL (the function used to launch kernels on the
device), but if it eventually does, there will be the same
problem.
I think that to properly support this, we will need some DWARF
improvements to be able to say "there is really nothing at these
lines" in the line table.
Co-Authored-By: Simon Marchi <simon.marchi@efficios.com>
Change-Id: I3cc12cfa823dc7d8e24dd4d35bced8e8baf7f9b6
When running test-case gdb.python/py-mi-cmd.exp with python 3.13, I run into:
...
Expecting: ^(-pycmd exp[^M
]+)?(.*&"Traceback \(most recent call last\):.."^M
&"[^^M
]+py-mi-cmd.py[^^M
]+"^M
&"[^^M
]+raise gdb.GdbError\(\).."^M
&"gdb.GdbError.."^M
\^error,msg="Error occurred in Python\."[^M
]+[(]gdb[)] ^M
[ ]*)
-pycmd exp^M
&"Traceback (most recent call last):\n"^M
&" File \"py-mi-cmd.py\", line 76, in invoke\n raise gdb.GdbError()\n"^M
&"gdb.GdbError\n"^M
^error,msg="Error occurred in Python."^M
(gdb) ^M
FAIL: gdb.python/py-mi-cmd.exp: -pycmd exp (unexpected output)
...
In contrast, with python 3.12 I have:
...
Expecting: ^(-pycmd exp[^M
]+)?(.*&"Traceback \(most recent call last\):.."^M
&"[^^M
]+py-mi-cmd.py[^^M
]+"^M
&"[^^M
]+raise gdb.GdbError\(\).."^M
&"gdb.GdbError.."^M
\^error,msg="Error occurred in Python\."[^M
]+[(]gdb[)] ^M
[ ]*)
-pycmd exp^M
&"Traceback (most recent call last):\n"^M
&" File \"py-mi-cmd.py\", line 76, in invoke\n"^M
&" raise gdb.GdbError()\n"^M
&"gdb.GdbError\n"^M
^error,msg="Error occurred in Python."^M
(gdb) ^M
PASS: gdb.python/py-mi-cmd.exp: -pycmd exp
...
To make it easier to understand what we're looking at, let's take this out of
the mi interpreter context and use the cli interpreter:
...
$ gdb -q -batch -ex "set trace-commands on" -x gdb.in
+set python print-stack full
+source py-mi-cmd.py
+python pycmd1('-pycmd')
+python pycmd1.invoke (pycmd1, ["exp"])
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "py-mi-cmd.py", line 76, in invoke
raise gdb.GdbError()
gdb.GdbError
gdb.in:4: Error in sourced command file:
Error occurred in Python.
...
Interestingly, this is what we're seeing with both python 3.12 and 3.13.
The difference between the python versions is that:
- with python 3.12 each line is printed by itself, and
- with python 3.13 two particular lines are printed toghether.
With the cli interpreter, that makes no difference, because the '\n' is
interpreted.
But with the mi interpreter, that causes a difference in output because the
'\n' is not interpreted, but rather printed literally.
Fix this by accepting the new output in addition to the old one.
Tested on aarch64-linux.
Reviewed-by: Thiago Jung Bauermann <thiago.bauermann@linaro.org>
PR testsuite/31913
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31913
Usually with test-case gdb.python/py-progspace-events.exp I get:
...
(gdb) inferior 1^M
[Switching to inferior 1 [process 4116] (py-progspace-events)]^M
[Switching to thread 1.1 (Thread 0xf77d0ce0 (LWP 4116))]^M
28 { /* Nothing. */ }^M
(gdb) PASS: gdb.python/py-progspace-events.exp: inferior 1
step^M
FreeProgspaceEvent: <gdb.Progspace object at 0xabf4f850>^M
do_parent_stuff () at py-progspace-events.c:41^M
41 ++global_var;^M
(gdb) PASS: gdb.python/py-progspace-events.exp: step
...
But occasionally I run into the following FAIL:
...
(gdb) inferior 1^M
[Switching to inferior 1 [process 5199] (py-progspace-events)]^M
[Switching to thread 1.1 (Thread 0xf77d0ce0 (LWP 5199))]^M
28 { /* Nothing. */ }^M
(gdb) FreeProgspaceEvent: <gdb.Progspace object at 0xabaf03a0>^M
FAIL: gdb.python/py-progspace-events.exp: inferior 1 (timeout)
...
This is caused by a race between the handling of an event, and the
"inferior 1" command.
In the passing case, the event is handled first. During which prune_inferiors
is called, but it can't remove inferior 2, because it's still the current one.
In the failing case, the "inferior 1" command is handled first. Then during
handling of the event, prune_inferiors is called, and it can remove inferior 2
because it's no longer the current one.
This looks like a test-case issue to me, but ISTM that we can do better: by
calling prune_inferiors asap, at the end of the "inferior 1" command, we
stabilize the moment when the inferior is removed:
...
(gdb) inferior 1^M
[Switching to inferior 1 [process 5199] (py-progspace-events)]^M
[Switching to thread 1.1 (Thread 0xf77d0ce0 (LWP 5199))]^M
28 { /* Nothing. */ }^M
FreeProgspaceEvent: <gdb.Progspace object at 0xabaf03a0>^M
(gdb) PASS: gdb.python/py-progspace-events.exp: inferior 1
...
This also allows us to simplify the test-case by removing the step command,
which is no longer required to trigger the pruning of the inferior.
Tested on x86_64-linux.
Approved-by: Kevin Buettner <kevinb@redhat.com>
PR gdb/31440
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31440
My previous patch
commit 8958aefd34 (HEAD)
Author: Felix Willgerodt <felix.willgerodt@intel.com>
Date: Mon Feb 25 15:30:29 2019 +0100
python: Add clear() to gdb.Record.
exposed a clear function for btrace data in python and added some tests
for it. That caused a regression (PR 32086) when recording with bts.
This is reproducible even without my patch, when adding
"maintenance btrace clear" to the test.
When comparing the instructions that get recorded in both cases, the traces
are almost identical, just that the first 3 instructions are missing.
Before clear:
(gdb) record instruction-history 1,100
1 0x0000555555555163 <main+12>: movl $0x0,-0x4(%rbp)
2 0x000055555555516a <main+19>: movl $0x0,-0x8(%rbp)
3 0x0000555555555171 <main+26>: jmp 0x555555555184 <main+45>
4 0x0000555555555184 <main+45>: cmpl $0x63,-0x4(%rbp)
5 0x0000555555555188 <main+49>: jle 0x555555555173 <main+28>
6 0x0000555555555173 <main+28>: mov -0x8(%rbp),%eax
7 0x0000555555555176 <main+31>: mov %eax,%edi
...
After clear:
(gdb) record instruction-history 1,100
1 0x0000555555555184 <main+45>: cmpl $0x63,-0x4(%rbp)
2 0x0000555555555188 <main+49>: jle 0x555555555173 <main+28>
3 0x0000555555555173 <main+28>: mov -0x8(%rbp),%eax
4 0x0000555555555176 <main+31>: mov %eax,%edi
...
The GDB manual describes this behaviour already:
maint btrace clear
Discard the branch trace data. The data will be fetched anew and
the branch trace will be recomputed when needed.
This implicitly truncates the branch trace to a single branch trace
buffer. When updating branch trace incrementally, the branch trace
available to GDB may be bigger than a single branch trace buffer.
The test with BTS is updating the recorded trace incrementally. After the
clear, the buffer of raw trace data available is not enough to recompute the
whole trace as it was before the clear(), and the first 3 instructions are
missing.
As increasing the buffer size for BTS didn't help, I propose to fix the test
by moving the testing of clear to the end of the test.
Approved-By: Tom de Vries <tdevries@suse.de>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32086
This function allows to clear the trace data from python, forcing to
re-decode the trace for successive commands.
This will be used in future ptwrite patches, to trigger re-decoding when
the ptwrite filter changes.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Markus Metzger <markus.t.metzger@intel.com>
The final test of gdb.python/py-framefilter-invalidarg.exp expected that
the the backtrace only printed the source file name. However, when using
clang, gdb will always print the full path to the file, which would
cause the test to fail. This commit introduces a regexp that optionally
matches paths, preprended to the file name, which fixes the clang
failure without introducing gcc failures.
Approved-By: Andrew Burgess <aburgess@redhat.com>
Clang doesn't add build-id information by default, unlike gcc. This
means that tests that rely on build-id being available and don't
explicitly add it to the compilation options will fail with clang.
This commit fixes the fails in gdb.python/py-missing-debug.exp,
gdb.server/remote-read-msgs.exp, gdb.base/coredump-filter-build-id.exp
and gdb.server/solib-list.exp
Approved-By: Andrew Burgess <aburgess@redhat.com>
On fedora rawhide, with python 3.13, I run into:
...
(gdb) python print (gdb.parse_and_eval ('a_point_t').format_string (invalid=True))^M
Python Exception <class 'TypeError'>: \
this function got an unexpected keyword argument 'invalid'^M
Error occurred in Python: \
this function got an unexpected keyword argument 'invalid'^M
(gdb) FAIL: $exp: format_string: lang_c: test_all_common: test_invalid_args: \
a_point_t with option invalid=True
...
A passing version with an older python version looks like:
...
(gdb) python print (gdb.parse_and_eval ('a_point_t').format_string (invalid=True))^M
Python Exception <class 'TypeError'>: \
'invalid' is an invalid keyword argument for this function^M
Error occurred in Python: \
'invalid' is an invalid keyword argument for this function^M
(gdb) PASS: $exp: format_string: lang_c: test_all_common: test_invalid_args: \
a_point_t with option invalid=True
...
Fix this by accepting the updated error message.
Tested on aarch64-linux.
PR testsuite/31912
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31912
I tried to reproduce a problem in test-case gdb.python/py-disasm.exp on a
s390x machine, but when running with target board unix/-m31 I saw that the
required libraries were missing, so I couldn't generate an executable.
However, I realized that I did have an object file, and the test-case should
mostly also work with an object file.
I've renamed gdb.python/py-disasm.exp to gdb.python/py-disasm.exp.tcl and
included it from two new minimal test-case wrappers:
- gdb.python/py-disasm-exec.exp, and
- gdb.python/py-disasm-obj.exp
where the former uses an executable as before, and the latter uses an object
file.
Using an object file required changing the info.read_memory calls in
gdb.python/py-disasm.py:
...
- info.read_memory(1, -info.address + 2)
+ info.read_memory(1, -info.address - 1)
...
because reading from address 2 succeeds. Using address -1 instead does
generate the expected gdb.MemoryError.
Tested on x86_64-linux.
Looking for a type defined locally in a function doesn't work
any more since the introduction of TYPE_DOMAIN:
```
(gdb) python print (gdb.lookup_type ('main()::Local'))
Python Exception <class 'gdb.error'>: No type named main()::Local.
Error occurred in Python: No type named main()::Local.
```
cp_search_static_and_baseclasses was simply missing a check for
SEARCH_TYPE_DOMAIN, now it works again:
```
(gdb) python print (gdb.lookup_type ('main()::Local'))
Local
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31922
Approved-By: Tom Tromey <tom@tromey.com>
When running test-case gdb.python/py-format-address.exp on arm-linux, I get:
...
(gdb) python print("Got: " + gdb.format_address(0x103dd))^M
Got: 0x103dd <main at py-format-address.c:30>^M
(gdb) FAIL: $exp: symbol_filename=on: gdb.format_address, \
result should have an offset
...
What is expected here is:
...
Got: 0x103dd <main+1 at py-format-address.c:30>^M
...
Main starts at main_addr:
...
(gdb) print /x &main^M
$1 = 0x103dc^M
...
and we obtained next_addr 0x103dd by adding 1 to it:
...
set next_addr [format 0x%x [expr $main_addr + 1]]
...
Adding 1 to $main_addr results in an address for a thumb function starting at
address 0x103dc, which is incorrect because main is an arm function (because
I'm running with target board unix/-marm).
At some point during the call to format_addr, arm_addr_bits_remove removes
the thumb bit, which causes the +1 offset to be dropped, causing the FAIL.
Fix this by using the address of the breakpoint on main, provided it's not at
the very start of main.
Tested on arm-linux.
PR testsuite/31452
Bug: https://www.sourceware.org/bugzilla/show_bug.cgi?id=31452
After fixing test-case gdb.python/py-disasm.exp to recognize the arm nop:
...
nop {0}
...
we run into:
...
disassemble test^M
Dump of assembler code for function test:^M
0x004004d8 <+0>: push {r11} @ (str r11, [sp, #-4]!)^M
0x004004dc <+4>: add r11, sp, #0^M
0x004004e0 <+8>: nop {0}^M
=> 0x004004e4 <+12>: Python Exception <class 'ValueError'>: Buffer \
returned from read_memory is sized 0 instead of the expected 4^M
^M
unknown disassembler error (error = -1)^M
(gdb) FAIL: $exp: global_disassembler=ShowInfoRepr: disassemble test
...
This is caused by this code in gdbpy_disassembler::read_memory_func:
...
gdbpy_ref<> result_obj (PyObject_CallMethod ((PyObject *) obj,
"read_memory",
"KL", len, offset));
...
where len has type "unsigned int", while "K" means "unsigned long long" [1].
Fix this by using "I" instead, meaning "unsigned int".
Also, offset has type LONGEST, which is typedef'ed to int64_t, while "L" means
"long long".
Fix this by using type gdb_py_longest for offset, in combination with format
character "GDB_PY_LL_ARG". Likewise in disasmpy_info_read_memory.
Tested on arm-linux.
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
Approved-By: Tom Tromey <tom@tromey.com>
PR python/31845
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31845
[1] https://docs.python.org/3/c-api/arg.html
In subsequent patches, it's handy if gdb.Block is hashable, so it can
be stored in a set or a dictionary. However, doing this in a
straightforward way is not really possible, because a block isn't
truly immutable -- it can be invalidated. And, while this isn't a
real problem for my use case (in DAP the maps are only used during a
single stop), it seemed error-prone.
This patch instead takes the approach of using the gdb.Block's own
object identity to allow hashing. This seems fine because the
contents don't affect the hashing. In order for this to work, though,
the blocks have to be memoized -- two requests for the same block must
return the same object.
This also allows (actually, requires) the simplification of the
rich-compare method for blocks.
Reviewed-By: Alexandra Petlanova Hajkova <ahajkova@redhat.com>
If you try to use the overloaded subscript operator of a class
in python, it fails like this:
(gdb) py print(gdb.parse_and_eval('b')[5])
Traceback (most recent call last):
File "<string>", line 1, in <module>
gdb.error: Cannot subscript requested type.
Error while executing Python code.
This simply checks if such an operator exists, and calls it
instead, making this possible:
(gdb) py print(gdb.parse_and_eval('b')[5])
102 'f'
Approved-By: Tom Tromey <tom@tromey.com>
As mentioned in PR13326, currently when you try to call a
convenience function with python, you get this error:
(gdb) py print(gdb.convenience_variable("_isvoid")(3))
Traceback (most recent call last):
File "<string>", line 1, in <module>
RuntimeError: Value is not callable (not TYPE_CODE_FUNC or TYPE_CODE_METHOD).
Error while executing Python code.
So this extends valpy_call to handle TYPE_CODE_INTERNAL_FUNCTION as
well, making this possible:
(gdb) py print(gdb.convenience_variable("_isvoid")(3))
0
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=13326
Approved-By: Tom Tromey <tom@tromey.com>
There's a pattern of using:
...
set saved_gdbflags $GDBFLAGS
set GDBFLAGS "$GDBFLAGS ..."
<do something with GDBFLAGS>
set GDBFLAGS $saved_gdbflags
...
Simplify this by using save_vars:
...
save_vars { GDBFLAGS } {
set GDBFLAGS "$GDBFLAGS ..."
<do something with GDBFLAGS>
}
...
Tested on x86_64-linux.
INTERNAL_GDBFLAGS contains:
- -quiet
- -iex "set width 0"
- -iex "set height 0"
There are test-cases that add these once more.
Clean this up.
Tested on x86_64-linux.
PR testsuite/31649
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31649
This is similar to the previous patch, but for gdb_protocol_is_remote.
gdb_is_target_remote and its MI cousin mi_is_target_remote, use "maint
print target-stack", which is unnecessary when checking whether
gdb_protocol is "remote" or "extended-remote" would do. Checking
gdb_protocol is more efficient, and can be done before starting GDB
and running to main, unlike gdb_is_target_remote/mi_is_target_remote.
This adds a new gdb_protocol_is_remote procedure, and uses it in place
of gdb_is_target_remote/mi_is_target_remote throughout.
There are no uses of gdb_is_target_remote/mi_is_target_remote left
after this. Those will be eliminated in a following patch.
In some spots, we no longer need to defer the check until after
starting GDB, so the patch adjusts accordingly.
Change-Id: I90267c132f942f63426f46dbca0b77dbfdf9d2ef
Approved-By: Tom Tromey <tom@tromey.com>
gdb_is_target_native uses "maint print target-stack", which is
unnecessary when checking whether gdb_protocol is empty would do.
Checking gdb_protocol is more efficient, and can be done before
starting GDB and running to main, unlike gdb_is_target_native.
This adds a new gdb_protocol_is_native procedure, and uses it in place
of gdb_is_target_native.
At first, I thought that we'd end up with a few testcases needing to
use gdb_is_target_native still, especially multi-target tests that
connect to targets different from the default board target, but no,
actually all uses of gdb_is_target_native could be converted.
gdb_is_target_native will be eliminated in a following patch.
In some spots, we no longer need to defer the check until after
starting GDB, so the patch adjusts accordingly.
Change-Id: Ia706232dbffac70f9d9740bcb89c609dbee5cee3
Approved-By: Tom Tromey <tom@tromey.com>
Simon reported [1] that recent commit 06e967dbc9 ("[gdb/python] Throw
MemoryError in inferior.read_memory if malloc fails") introduced
AddressSanitizer allocation-size-too-big errors in the two test-cases
affected by this commit.
Fix this by suppressing the error in the two test-cases using
allocator_may_return_null=1.
Tested on aarch64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
[1] https://sourceware.org/pipermail/gdb-patches/2024-April/208171.html
PR python/31631 reports a gdb internal error when doing:
...
(gdb) python gdb.selected_inferior().read_memory (0, 0xffffffffffffffff)
utils.c:709: internal-error: virtual memory exhausted.
A problem internal to GDB has been detected,
further debugging may prove unreliable.
...
Fix this by throwing a python MemoryError, such that we have instead:
...
(gdb) python gdb.selected_inferior().read_memory (0, 0xffffffffffffffff)
Python Exception <class 'MemoryError'>:
Error occurred in Python.
(gdb)
...
Likewise for DAP.
Tested on x86_64-linux.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31631
The gdb.python/py-cmd-prompt.exp script includes a test that has a
gdbserver port number within a test name. As port numbers can change
from one test run to the next (depending on what else is running on
the machine at the time), this can make it hard to compare test
results between runs.
Give the test a specific name to avoid including the port number.
There is no change in what is tested after this commit.
Several tests assume that the first word after a thread ID in 'info
threads' output is "Thread". However, several targets use "LWP"
instead such as the FreeBSD and NetBSD native targets. The Linux
native target also uses "LWP" if libthread_db is not being used.
Targets that do not support threads use "process" as the first word
via normal_pid_to_str.
Add a tdlabel_re global variable as a regular-expression for a thread
label in `info threads' that matches either "process", "Thread", or
"LWP".
Some other tests in the tree don't require a specific word, and
some targets may use other first words (e.g. OpenBSD uses "thread"
and Ravenscar threads use "Ravenscar Thread").
The gdb.solib_name() and Progspace.solib_name() functions can throw an
exception if the address argument is not a valid address, but this is
not currently tested.
This commit adds a couple of tests to check that exceptions are thrown
correctly.
An early version of this commit updated the documentation, but it was
pointed out that lots of functions throw an exception if passed an
argument of the wrong type, and we don't document all of these, it's
kind-of assumed that passing an object of the incorrect type might
result in an exception, so this updated version leaves the docs alone,
but I do think adding the extra tests has value.
There's no changes to GDB itself in this commit.
Approved-By: Tom Tromey <tom@tromey.com>
symtab-> linetable () is set to null in
buildsym_compunit::end_compunit_symtab_with_blockvector () if the symtab
has no linetable. Attempting to iterate over this linetable using the
Python API caused GDB to segfault.
Approved-By: Tom Tromey <tom@tromey.com>
This patch arranges to set __file__ when source'ing a Python script.
This fixes a problem that was introduced by the "source" rewrite, and
then pointed out by Lancelot Six.
Reviewed-by: Lancelot Six <lancelot.six@amd.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
With python 3.12, I run into:
...
(gdb) PASS: gdb.python/py-block.exp: check variable access
python print (block['nonexistent'])^M
Python Exception <class 'KeyError'>: 'nonexistent'^M
Error occurred in Python: 'nonexistent'^M
(gdb) FAIL: gdb.python/py-block.exp: check nonexistent variable
...
The problem is that that PyErr_Fetch returns a normalized exception, while the
test-case matches the output for an unnormalized exception.
With python 3.6, PyErr_Fetch returns an unnormalized exception, and the
test passes.
Fix this by:
- updating the test-case to match the output for a normalized exception, and
- lazily forcing normalized exceptions using PyErr_NormalizeException.
Tested on aarch64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
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>
With test-case gdb.python/py-finish-breakpoint.exp, we run into:
...
(gdb) python print (finishbp_default.hit_count)
Traceback (most recent call last):
File "<string>", line 1, in <module>
RuntimeError: Breakpoint 3 is invalid.
Error while executing Python code.
(gdb) PASS: gdb.python/py-finish-breakpoint.exp: normal conditions: \
check finishBP on default frame has been hit
...
The test producing the pass is:
...
gdb_test "python print (finishbp_default.hit_count)" "1.*" \
"check finishBP on default frame has been hit"
...
so the pass is produced because the 1 in "line 1" matches "1.*".
Temporary breakpoints are removed when hit, and consequently accessing the
hit_count attribute of a temporary python breakpoint (gdb.Breakpoint class) is
not possible, and as per spec we get a RuntimeError.
So the RuntimeError is correct, and not specific to finish breakpoints.
The test presumably attempts to match:
...
(gdb) python print (finishbp_default.hit_count)
1
...
but most likely this output was never produced by any gdb version.
Fix this by checking whether the finishbp_default breakpoint has hit by
checking that finishbp_default.is_valid() is False.
Tested on aarch64-linux.
Approved-By: Tom Tromey <tom@tromey.com>
PR testsuite/31391
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31391
The output of "info breakpoints" includes breakpoint, watchpoint,
tracepoint, and catchpoint if they are created, so it should show
all the four types are deleted in the output of "info breakpoints"
to report empty list after "delete breakpoints".
It should also change the output of "delete breakpoints" to make it
clear that watchpoints, tracepoints, and catchpoints are also being
deleted. This is suggested by Guinevere Larsen, thank you.
$ make check-gdb TESTS="gdb.base/access-mem-running.exp"
$ gdb/gdb gdb/testsuite/outputs/gdb.base/access-mem-running/access-mem-running
[...]
(gdb) break main
Breakpoint 1 at 0x12000073c: file /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c, line 32.
(gdb) watch global_counter
Hardware watchpoint 2: global_counter
(gdb) trace maybe_stop_here
Tracepoint 3 at 0x12000071c: file /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c, line 27.
(gdb) catch fork
Catchpoint 4 (fork)
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000012000073c in main at /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c:32
2 hw watchpoint keep y global_counter
3 tracepoint keep y 0x000000012000071c in maybe_stop_here at /home/loongson/gdb.git/gdb/testsuite/gdb.base/access-mem-running.c:27
not installed on target
4 catchpoint keep y fork
Without this patch:
(gdb) delete breakpoints
Delete all breakpoints? (y or n) y
(gdb) info breakpoints
No breakpoints or watchpoints.
(gdb) info breakpoints 3
No breakpoint or watchpoint matching '3'.
With this patch:
(gdb) delete breakpoints
Delete all breakpoints, watchpoints, tracepoints, and catchpoints? (y or n) y
(gdb) info breakpoints
No breakpoints, watchpoints, tracepoints, or catchpoints.
(gdb) info breakpoints 3
No breakpoint, watchpoint, tracepoint, or catchpoint matching '3'.
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
Approved-by: Kevin Buettner <kevinb@redhat.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
From the Python API, we can execute GDB commands via gdb.execute. If
the command gives an exception, however, we need to recover the GDB
prompt and enable stdin, because the exception does not reach
top-level GDB or normal_stop. This was done in commit
commit 1ba1ac8801
Author: Andrew Burgess <andrew.burgess@embecosm.com>
Date: Tue Nov 19 11:17:20 2019 +0000
gdb: Enable stdin on exception in execute_gdb_command
with the following code:
catch (const gdb_exception &except)
{
/* If an exception occurred then we won't hit normal_stop (), or have
an exception reach the top level of the event loop, which are the
two usual places in which stdin would be re-enabled. So, before we
convert the exception and continue back in Python, we should
re-enable stdin here. */
async_enable_stdin ();
GDB_PY_HANDLE_EXCEPTION (except);
}
In this patch, we explain what happens when we run a GDB command in
the context of a synchronous command, e.g. via Python observer
notifications.
As an example, suppose we have the following objfile event listener,
specified in a file named file.py:
~~~
import gdb
class MyListener:
def __init__(self):
gdb.events.new_objfile.connect(self.handle_new_objfile_event)
self.processed_objfile = False
def handle_new_objfile_event(self, event):
if self.processed_objfile:
return
print("loading " + event.new_objfile.filename)
self.processed_objfile = True
gdb.execute('add-inferior -no-connection')
gdb.execute('inferior 2')
gdb.execute('target remote | gdbserver - /tmp/a.out')
gdb.execute('inferior 1')
the_listener = MyListener()
~~~
Using this Python file, we see the behavior below:
$ gdb -q -ex "source file.py" -ex "run" --args a.out
Reading symbols from a.out...
Starting program: /tmp/a.out
loading /lib64/ld-linux-x86-64.so.2
[New inferior 2]
Added inferior 2
[Switching to inferior 2 [<null>] (<noexec>)]
stdin/stdout redirected
Process /tmp/a.out created; pid = 3075406
Remote debugging using stdio
Reading /tmp/a.out from remote target...
...
[Switching to inferior 1 [process 3075400] (/tmp/a.out)]
[Switching to thread 1.1 (process 3075400)]
#0 0x00007ffff7fe3290 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) [Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Inferior 1 (process 3075400) exited normally]
Note how the GDB prompt comes in-between the debugger output. We have this
obscure behavior, because the executed command, "target remote", triggers
an invocation of `normal_stop` that enables stdin. After that, however,
the Python notification context completes and GDB continues with its normal
flow of executing the 'run' command. This can be seen in the call stack
below:
(top-gdb) bt
#0 async_enable_stdin () at src/gdb/event-top.c:523
#1 0x00005555561c3acd in normal_stop () at src/gdb/infrun.c:9432
#2 0x00005555561b328e in start_remote (from_tty=0) at src/gdb/infrun.c:3801
#3 0x0000555556441224 in remote_target::start_remote_1 (this=0x5555587882e0, from_tty=0, extended_p=0) at src/gdb/remote.c:5225
#4 0x000055555644166c in remote_target::start_remote (this=0x5555587882e0, from_tty=0, extended_p=0) at src/gdb/remote.c:5316
#5 0x00005555564430cf in remote_target::open_1 (name=0x55555878525e "| gdbserver - /tmp/a.out", from_tty=0, extended_p=0) at src/gdb/remote.c:6175
#6 0x0000555556441707 in remote_target::open (name=0x55555878525e "| gdbserver - /tmp/a.out", from_tty=0) at src/gdb/remote.c:5338
#7 0x00005555565ea63f in open_target (args=0x55555878525e "| gdbserver - /tmp/a.out", from_tty=0, command=0x555558589280) at src/gdb/target.c:824
#8 0x0000555555f0d89a in cmd_func (cmd=0x555558589280, args=0x55555878525e "| gdbserver - /tmp/a.out", from_tty=0) at src/gdb/cli/cli-decode.c:2735
#9 0x000055555661fb42 in execute_command (p=0x55555878529e "t", from_tty=0) at src/gdb/top.c:575
#10 0x0000555555f1a506 in execute_control_command_1 (cmd=0x555558756f00, from_tty=0) at src/gdb/cli/cli-script.c:529
#11 0x0000555555f1abea in execute_control_command (cmd=0x555558756f00, from_tty=0) at src/gdb/cli/cli-script.c:701
#12 0x0000555555f19fc7 in execute_control_commands (cmdlines=0x555558756f00, from_tty=0) at src/gdb/cli/cli-script.c:411
#13 0x0000555556400d91 in execute_gdb_command (self=0x7ffff43b5d00, args=0x7ffff440ab60, kw=0x0) at src/gdb/python/python.c:700
#14 0x00007ffff7a96023 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#15 0x00007ffff7a4dadc in _PyObject_MakeTpCall () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#16 0x00007ffff79e9a1c in _PyEval_EvalFrameDefault () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#17 0x00007ffff7b303af in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#18 0x00007ffff7a50358 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#19 0x00007ffff7a4f3f4 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#20 0x00007ffff7a4f883 in PyObject_CallFunctionObjArgs () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#21 0x00005555563a9758 in evpy_emit_event (event=0x7ffff42b5430, registry=0x7ffff42b4690) at src/gdb/python/py-event.c:104
#22 0x00005555563cb874 in emit_new_objfile_event (objfile=0x555558761700) at src/gdb/python/py-newobjfileevent.c:52
#23 0x00005555563b53bc in python_new_objfile (objfile=0x555558761700) at src/gdb/python/py-inferior.c:195
#24 0x0000555555d6dff0 in std::__invoke_impl<void, void (*&)(objfile*), objfile*> (__f=@0x5555585b5860: 0x5555563b5360 <python_new_objfile(objfile*)>) at /usr/include/c++/11/bits/invoke.h:61
#25 0x0000555555d6be18 in std::__invoke_r<void, void (*&)(objfile*), objfile*> (__fn=@0x5555585b5860: 0x5555563b5360 <python_new_objfile(objfile*)>) at /usr/include/c++/11/bits/invoke.h:111
#26 0x0000555555d69661 in std::_Function_handler<void (objfile*), void (*)(objfile*)>::_M_invoke(std::_Any_data const&, objfile*&&) (__functor=..., __args#0=@0x7fffffffd080: 0x555558761700) at /usr/include/c++/11/bits/std_function.h:290
#27 0x0000555556314caf in std::function<void (objfile*)>::operator()(objfile*) const (this=0x5555585b5860, __args#0=0x555558761700) at /usr/include/c++/11/bits/std_function.h:590
#28 0x000055555631444e in gdb::observers::observable<objfile*>::notify (this=0x55555836eea0 <gdb::observers::new_objfile>, args#0=0x555558761700) at src/gdb/../gdbsupport/observable.h:166
#29 0x0000555556599b3f in symbol_file_add_with_addrs (abfd=..., name=0x55555875d310 "/lib64/ld-linux-x86-64.so.2", add_flags=..., addrs=0x7fffffffd2f0, flags=..., parent=0x0) at src/gdb/symfile.c:1125
#30 0x0000555556599ca4 in symbol_file_add_from_bfd (abfd=..., name=0x55555875d310 "/lib64/ld-linux-x86-64.so.2", add_flags=..., addrs=0x7fffffffd2f0, flags=..., parent=0x0) at src/gdb/symfile.c:1160
#31 0x0000555556546371 in solib_read_symbols (so=..., flags=...) at src/gdb/solib.c:692
#32 0x0000555556546f0f in solib_add (pattern=0x0, from_tty=0, readsyms=1) at src/gdb/solib.c:1015
#33 0x0000555556539891 in enable_break (info=0x55555874e180, from_tty=0) at src/gdb/solib-svr4.c:2416
#34 0x000055555653b305 in svr4_solib_create_inferior_hook (from_tty=0) at src/gdb/solib-svr4.c:3058
#35 0x0000555556547cee in solib_create_inferior_hook (from_tty=0) at src/gdb/solib.c:1217
#36 0x0000555556196f6a in post_create_inferior (from_tty=0) at src/gdb/infcmd.c:275
#37 0x0000555556197670 in run_command_1 (args=0x0, from_tty=1, run_how=RUN_NORMAL) at src/gdb/infcmd.c:486
#38 0x000055555619783f in run_command (args=0x0, from_tty=1) at src/gdb/infcmd.c:512
#39 0x0000555555f0798d in do_simple_func (args=0x0, from_tty=1, c=0x555558567510) at src/gdb/cli/cli-decode.c:95
#40 0x0000555555f0d89a in cmd_func (cmd=0x555558567510, args=0x0, from_tty=1) at src/gdb/cli/cli-decode.c:2735
#41 0x000055555661fb42 in execute_command (p=0x7fffffffe2c4 "", from_tty=1) at src/gdb/top.c:575
#42 0x000055555626303b in catch_command_errors (command=0x55555661f4ab <execute_command(char const*, int)>, arg=0x7fffffffe2c1 "run", from_tty=1, do_bp_actions=true) at src/gdb/main.c:513
#43 0x000055555626328a in execute_cmdargs (cmdarg_vec=0x7fffffffdaf0, file_type=CMDARG_FILE, cmd_type=CMDARG_COMMAND, ret=0x7fffffffda3c) at src/gdb/main.c:612
#44 0x0000555556264849 in captured_main_1 (context=0x7fffffffdd40) at src/gdb/main.c:1293
#45 0x0000555556264a7f in captured_main (data=0x7fffffffdd40) at src/gdb/main.c:1314
#46 0x0000555556264b2e in gdb_main (args=0x7fffffffdd40) at src/gdb/main.c:1343
#47 0x0000555555ceccab in main (argc=9, argv=0x7fffffffde78) at src/gdb/gdb.c:39
(top-gdb)
The use of the "target remote" command here is just an example. In
principle, we would reproduce the problem with any command that
triggers an invocation of `normal_stop`.
To omit enabling the stdin in `normal_stop`, we would have to check the
context we are in. Since we cannot do that, we add a new field to
`struct ui` to track whether the prompt was already blocked, and set
the tracker flag in the Python context before executing a GDB command.
After applying this patch, the output becomes
...
Reading symbols from a.out...
Starting program: /tmp/a.out
loading /lib64/ld-linux-x86-64.so.2
[New inferior 2]
Added inferior 2
[Switching to inferior 2 [<null>] (<noexec>)]
stdin/stdout redirected
Process /tmp/a.out created; pid = 3032261
Remote debugging using stdio
Reading /tmp/a.out from remote target...
...
[Switching to inferior 1 [process 3032255] (/tmp/a.out)]
[Switching to thread 1.1 (process 3032255)]
#0 0x00007ffff7fe3290 in ?? () from /lib64/ld-linux-x86-64.so.2
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[Inferior 1 (process 3032255) exited normally]
(gdb)
Let's now consider a secondary scenario, where the command executed from
the Python raises an error. As an example, suppose we have the Python
file below:
def handle_new_objfile_event(self, event):
...
print("loading " + event.new_objfile.filename)
self.processed_objfile = True
gdb.execute('print a')
The executed command, "print a", gives an error because "a" is not
defined. Without this patch, we see the behavior below, where the
prompt is again placed incorrectly:
...
Reading symbols from /tmp/a.out...
Starting program: /tmp/a.out
loading /lib64/ld-linux-x86-64.so.2
Python Exception <class 'gdb.error'>: No symbol "a" in current context.
(gdb) [Inferior 1 (process 3980401) exited normally]
This time, `async_enable_stdin` is called from the 'catch' block in
`execute_gdb_command`:
(top-gdb) bt
#0 async_enable_stdin () at src/gdb/event-top.c:523
#1 0x0000555556400f0a in execute_gdb_command (self=0x7ffff43b5d00, args=0x7ffff440ab60, kw=0x0) at src/gdb/python/python.c:713
#2 0x00007ffff7a96023 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#3 0x00007ffff7a4dadc in _PyObject_MakeTpCall () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#4 0x00007ffff79e9a1c in _PyEval_EvalFrameDefault () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#5 0x00007ffff7b303af in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#6 0x00007ffff7a50358 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#7 0x00007ffff7a4f3f4 in ?? () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#8 0x00007ffff7a4f883 in PyObject_CallFunctionObjArgs () from /lib/x86_64-linux-gnu/libpython3.10.so.1.0
#9 0x00005555563a9758 in evpy_emit_event (event=0x7ffff42b5430, registry=0x7ffff42b4690) at src/gdb/python/py-event.c:104
#10 0x00005555563cb874 in emit_new_objfile_event (objfile=0x555558761410) at src/gdb/python/py-newobjfileevent.c:52
#11 0x00005555563b53bc in python_new_objfile (objfile=0x555558761410) at src/gdb/python/py-inferior.c:195
#12 0x0000555555d6dff0 in std::__invoke_impl<void, void (*&)(objfile*), objfile*> (__f=@0x5555585b5860: 0x5555563b5360 <python_new_objfile(objfile*)>) at /usr/include/c++/11/bits/invoke.h:61
#13 0x0000555555d6be18 in std::__invoke_r<void, void (*&)(objfile*), objfile*> (__fn=@0x5555585b5860: 0x5555563b5360 <python_new_objfile(objfile*)>) at /usr/include/c++/11/bits/invoke.h:111
#14 0x0000555555d69661 in std::_Function_handler<void (objfile*), void (*)(objfile*)>::_M_invoke(std::_Any_data const&, objfile*&&) (__functor=..., __args#0=@0x7fffffffd080: 0x555558761410) at /usr/include/c++/11/bits/std_function.h:290
#15 0x0000555556314caf in std::function<void (objfile*)>::operator()(objfile*) const (this=0x5555585b5860, __args#0=0x555558761410) at /usr/include/c++/11/bits/std_function.h:590
#16 0x000055555631444e in gdb::observers::observable<objfile*>::notify (this=0x55555836eea0 <gdb::observers::new_objfile>, args#0=0x555558761410) at src/gdb/../gdbsupport/observable.h:166
#17 0x0000555556599b3f in symbol_file_add_with_addrs (abfd=..., name=0x55555875d020 "/lib64/ld-linux-x86-64.so.2", add_flags=..., addrs=0x7fffffffd2f0, flags=..., parent=0x0) at src/gdb/symfile.c:1125
#18 0x0000555556599ca4 in symbol_file_add_from_bfd (abfd=..., name=0x55555875d020 "/lib64/ld-linux-x86-64.so.2", add_flags=..., addrs=0x7fffffffd2f0, flags=..., parent=0x0) at src/gdb/symfile.c:1160
#19 0x0000555556546371 in solib_read_symbols (so=..., flags=...) at src/gdb/solib.c:692
#20 0x0000555556546f0f in solib_add (pattern=0x0, from_tty=0, readsyms=1) at src/gdb/solib.c:1015
#21 0x0000555556539891 in enable_break (info=0x55555874a670, from_tty=0) at src/gdb/solib-svr4.c:2416
#22 0x000055555653b305 in svr4_solib_create_inferior_hook (from_tty=0) at src/gdb/solib-svr4.c:3058
#23 0x0000555556547cee in solib_create_inferior_hook (from_tty=0) at src/gdb/solib.c:1217
#24 0x0000555556196f6a in post_create_inferior (from_tty=0) at src/gdb/infcmd.c:275
#25 0x0000555556197670 in run_command_1 (args=0x0, from_tty=1, run_how=RUN_NORMAL) at src/gdb/infcmd.c:486
#26 0x000055555619783f in run_command (args=0x0, from_tty=1) at src/gdb/infcmd.c:512
#27 0x0000555555f0798d in do_simple_func (args=0x0, from_tty=1, c=0x555558567510) at src/gdb/cli/cli-decode.c:95
#28 0x0000555555f0d89a in cmd_func (cmd=0x555558567510, args=0x0, from_tty=1) at src/gdb/cli/cli-decode.c:2735
#29 0x000055555661fb42 in execute_command (p=0x7fffffffe2c4 "", from_tty=1) at src/gdb/top.c:575
#30 0x000055555626303b in catch_command_errors (command=0x55555661f4ab <execute_command(char const*, int)>, arg=0x7fffffffe2c1 "run", from_tty=1, do_bp_actions=true) at src/gdb/main.c:513
#31 0x000055555626328a in execute_cmdargs (cmdarg_vec=0x7fffffffdaf0, file_type=CMDARG_FILE, cmd_type=CMDARG_COMMAND, ret=0x7fffffffda3c) at src/gdb/main.c:612
#32 0x0000555556264849 in captured_main_1 (context=0x7fffffffdd40) at src/gdb/main.c:1293
#33 0x0000555556264a7f in captured_main (data=0x7fffffffdd40) at src/gdb/main.c:1314
#34 0x0000555556264b2e in gdb_main (args=0x7fffffffdd40) at src/gdb/main.c:1343
#35 0x0000555555ceccab in main (argc=9, argv=0x7fffffffde78) at src/gdb/gdb.c:39
(top-gdb)
Again, after we enable stdin, GDB continues with its normal flow
of the 'run' command and receives the inferior's exit event, where
it would have enabled stdin, if we had not done it prematurely.
(top-gdb) bt
#0 async_enable_stdin () at src/gdb/event-top.c:523
#1 0x00005555561c3acd in normal_stop () at src/gdb/infrun.c:9432
#2 0x00005555561b5bf1 in fetch_inferior_event () at src/gdb/infrun.c:4700
#3 0x000055555618d6a7 in inferior_event_handler (event_type=INF_REG_EVENT) at src/gdb/inf-loop.c:42
#4 0x000055555620ecdb in handle_target_event (error=0, client_data=0x0) at src/gdb/linux-nat.c:4316
#5 0x0000555556f33035 in handle_file_event (file_ptr=0x5555587024e0, ready_mask=1) at src/gdbsupport/event-loop.cc:573
#6 0x0000555556f3362f in gdb_wait_for_event (block=0) at src/gdbsupport/event-loop.cc:694
#7 0x0000555556f322cd in gdb_do_one_event (mstimeout=-1) at src/gdbsupport/event-loop.cc:217
#8 0x0000555556262df8 in start_event_loop () at src/gdb/main.c:407
#9 0x0000555556262f85 in captured_command_loop () at src/gdb/main.c:471
#10 0x0000555556264a84 in captured_main (data=0x7fffffffdd40) at src/gdb/main.c:1324
#11 0x0000555556264b2e in gdb_main (args=0x7fffffffdd40) at src/gdb/main.c:1343
#12 0x0000555555ceccab in main (argc=9, argv=0x7fffffffde78) at src/gdb/gdb.c:39
(top-gdb)
The solution implemented by this patch addresses the problem. After
applying the patch, the output becomes
$ gdb -q -ex "source file.py" -ex "run" --args a.out
Reading symbols from /tmp/a.out...
Starting program: /tmp/a.out
loading /lib64/ld-linux-x86-64.so.2
Python Exception <class 'gdb.error'>: No symbol "a" in current context.
[Inferior 1 (process 3984511) exited normally]
(gdb)
Regression-tested on X86_64 Linux using the default board file (i.e. unix).
Co-Authored-By: Oguzhan Karakaya <oguzhan.karakaya@intel.com>
Reviewed-By: Guinevere Larsen <blarsen@redhat.com>
Approved-By: Tom Tromey <tom@tromey.com>
If you try to call Frame.static_link for a frame without debug info,
gdb crashes:
```
Temporary breakpoint 1, 0x000000013f821650 in main ()
(gdb) py print(gdb.selected_frame().static_link())
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
```
The problem was a missing check if get_frame_block returns nullptr
inside frame_follow_static_link.
With this, it works:
```
Temporary breakpoint 1, 0x000000013f941650 in main ()
(gdb) py print(gdb.selected_frame().static_link())
None
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31366
Approved-By: Tom Tromey <tom@tromey.com>
Currently it's not possible to call C++ methods from python.
Using this example:
```
class B
{
static int static_func ();
int arg0_func ();
int arg1_func (int arg1);
int arg2_func (int arg1, int arg2);
};
B *b_obj = new B;
```
Trying to call B::static_func gives this error:
```
(gdb) py b_obj = gdb.parse_and_eval('b_obj')
(gdb) py print(b_obj['static_func']())
Traceback (most recent call last):
File "<string>", line 1, in <module>
RuntimeError: Value is not callable (not TYPE_CODE_FUNC).
Error while executing Python code.
```
TYPE_CODE_METHOD was simply missing as a possible type in
valpy_call, now the same is possible:
```
(gdb) py b_obj = gdb.parse_and_eval('b_obj')
(gdb) py print(b_obj['static_func']())
1111
```
Note that it's necessary to explicitely add the this pointer
as the first argument in a call of non-static methods:
```
(gdb) py print(b_obj['arg0_func']())
Traceback (most recent call last):
File "<string>", line 1, in <module>
gdb.error: Too few arguments in function call.
Error while executing Python code.
(gdb) py print(b_obj['arg0_func'](b_obj))
198
```
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=13326
Approved-By: Tom Tromey <tom@tromey.com>
Currently gdb.parameter doesn't raise an exception if an
ambiguous name is used, it instead returns the value of the
last partly matching parameter:
```
(gdb) show print sym
Ambiguous show print command "sym": symbol, symbol-filename, symbol-loading.
(gdb) show print symbol-loading
Printing of symbol loading messages is "full".
(gdb) py print(gdb.parameter("print sym"))
full
```
It's because lookup_cmd_composition_1 tries to detect
ambigous names by checking the return value of find_cmd
for CMD_LIST_AMBIGUOUS, which never happens, since only
lookup_cmd_1 returns CMD_LIST_AMBIGUOUS.
Instead the nfound argument contains the number of found
matches.
By using it instead, and by setting *CMD to the special value
CMD_LIST_AMBIGUOUS in this case, gdbpy_parameter can now show
the appropriate error message:
```
(gdb) py print(gdb.parameter("print sym"))
Traceback (most recent call last):
File "<string>", line 1, in <module>
RuntimeError: Parameter `print sym' is ambiguous.
Error while executing Python code.
(gdb) py print(gdb.parameter("print symbol"))
True
(gdb) py print(gdb.parameter("print symbol-"))
Traceback (most recent call last):
File "<string>", line 1, in <module>
RuntimeError: Parameter `print symbol-' is ambiguous.
Error while executing Python code.
(gdb) py print(gdb.parameter("print symbol-load"))
full
```
Since the document command also uses lookup_cmd_composition, it needed
to check for CMD_LIST_AMBIGUOUS as well, so it now also shows an
"Ambiguous command" error message in this case.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=14639
Approved-By: Tom Tromey <tom@tromey.com>
Currently, if frame-filters are active, raw-values is used instead of
raw-frame-arguments to decide if a pretty-printer should be invoked for
frame arguments in a backtrace.
In this example, "super struct" is the output of the pretty-printer:
(gdb) disable frame-filter global BasicFrameFilter
(gdb) bt
#0 foo (x=42, ss=super struct = {...}) at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:47
#1 0x004016aa in main () at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:57
If no frame-filter is active, then the raw-values print option does not
affect the backtrace output:
(gdb) set print raw-values on
(gdb) bt
#0 foo (x=42, ss=super struct = {...}) at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:47
#1 0x004016aa in main () at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:57
(gdb) set print raw-values off
Instead, the raw-frame-arguments option disables the pretty-printer in the
backtrace:
(gdb) bt -raw-frame-arguments on
#0 foo (x=42, ss=...) at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:47
#1 0x004016aa in main () at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:57
But if a frame-filter is active, the same rules don't apply.
The option raw-frame-arguments is ignored, but raw-values decides if the
pretty-printer is used:
(gdb) enable frame-filter global BasicFrameFilter
(gdb) bt
#0 foo (x=42, ss=super struct = {...}) at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:47
#1 0x004016aa in main () at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:57
(gdb) set print raw-values on
(gdb) bt
#0 foo (x=42, ss=...) at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:47
#1 0x004016aa in main () at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:57
(gdb) set print raw-values off
(gdb) bt -raw-frame-arguments on
#0 foo (x=42, ss=super struct = {...}) at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:47
#1 0x004016aa in main () at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:57
So this adds the PRINT_RAW_FRAME_ARGUMENTS flag to frame_filter_flag, which
is then used in the frame-filter to override the raw flag in enumerate_args.
Then the output is the same if a frame-filter is active, the pretty-printer
for backtraces is only disabled with the raw-frame-arguments option:
(gdb) enable frame-filter global BasicFrameFilter
(gdb) bt
#0 foo (x=42, ss=super struct = {...}) at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:47
#1 0x004016aa in main () at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:57
(gdb) set print raw-values on
(gdb) bt
#0 foo (x=42, ss=super struct = {...}) at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:47
#1 0x004016aa in main () at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:57
(gdb) set print raw-values off
(gdb) bt -raw-frame-arguments on
#0 foo (x=42, ss=...) at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:47
#1 0x004016aa in main () at C:/src/repos/gdb-testsuite/gdb/testsuite/gdb.python/py-frame-args.c:57
Co-Authored-By: Andrew Burgess <aburgess@redhat.com>
Approved-By: Tom Tromey <tom@tromey.com>
After this commit:
commit 1925bba80e
Date: Thu Jan 4 10:01:24 2024 +0000
gdb/python: add gdb.InferiorThread.__repr__() method
failures were reported for gdb.python/py-inferior.exp.
The test grabs a gdb.InferiorThread object representing an inferior
thread, and then, later in the test, expects this Python object to
become invalid when the inferior thread has exited.
The gdb.InferiorThread object was obtained from the list returned by
calling gdb.Inferior.threads().
The mistake I made in the original commit was to assume that the order
of the threads returned from gdb.Inferior.threads() somehow reflected
the thread creation order. Specifically, I was expecting the main
thread to be first in the list, and "other" threads to appear ... not
first.
However, the gdb.Inferior.threads() function creates a list and
populates it from a map. The order of the threads in the returned
list has no obvious relationship to the thread creation order, and can
vary from host to host.
On my machine the ordering was as I expected, so the test passed for
me. For others the ordering was not as expected, and it just happened
that we ended up recording the gdb.InferiorThread for the main thread.
As the main thread doesn't exit (until the test is over), the
gdb.InferiorThread object never became invalid, and the test failed.
Fixed in this commit by taking more care to correctly find a non-main
thread. I do this by recording the main thread early on (when there
is only one inferior thread), and then finding any thread that is not
this main thread.
Then, once all of the secondary threads have exited, I know that the
second InferiorThread object I found should now be invalid.
The test still passes for me, and I believe this should fix the issue
for everyone else too.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31238
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.
The gdb.Objfile, gdb.Progspace, gdb.Type, and gdb.Inferior Python
types already have a __dict__ attribute, which allows users to create
user defined attributes within the objects. This is useful if the
user wants to cache information within an object.
This commit adds the same functionality to the gdb.InferiorThread
type.
After this commit there is a new gdb.InferiorThread.__dict__
attribute, which is a dictionary. A user can, for example, do this:
(gdb) pi
>>> t = gdb.selected_thread()
>>> t._user_attribute = 123
>>> t._user_attribute
123
>>>
There's a new test included.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
The gdb.Objfile, gdb.Progspace, and gdb.Type Python types already have
a __dict__ attribute, which allows users to create user defined
attributes within the objects. This is useful if the user wants to
cache information within an object.
This commit adds the same functionality to the gdb.Inferior type.
After this commit there is a new gdb.Inferior.__dict__ attribute,
which is a dictionary. A user can, for example, do this:
(gdb) pi
>>> i = gdb.selected_inferior()
>>> i._user_attribute = 123
>>> i._user_attribute
123
>>>
There's a new test included.
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>