Commit Graph

1644 Commits

Author SHA1 Message Date
Andrei Pikas
6447969d0a Add an option with a color type.
Colors can be specified as "none" for terminal's default color, as a name of
one of the eight standard colors of ISO/IEC 6429 "black", "red", "green", etc.,
as an RGB hexadecimal tripplet #RRGGBB for 24-bit TrueColor, or as an
integer from 0 to 255.  Integers 0 to 7 are the synonyms for the standard
colors.  Integers 8-15 are used for the so-called bright colors from the
aixterm extended 16-color palette.  Integers 16-255 are the indexes into xterm
extended 256-color palette (usually 6x6x6 cube plus gray ramp).  In
general, 256-color palette is terminal dependent and sometimes can be
changed with OSC 4 sequences, e.g. "\033]4;1;rgb:00/FF/00\033\\".

It is the responsibility of the user to verify that the terminal supports
the specified colors.

PATCH v5 changes: documentation fixed.
PATCH v6 changes: documentation fixed.
PATCH v7 changes: rebase onto master and fixes after review.
PATCH v8 changes: fixes after review.
2025-01-12 13:30:43 -07:00
Thiago Jung Bauermann
ad59259604 GDB: trad-frame: Store length of value_bytes in trad_frame_saved_reg
The goal is to ensure that it is available in frame_unwind_got_bytes () to
make sure that the provided buf isn't larger than the size of the register
being provisioned.

In the process, regcache's cached_reg_t::data also needed to be
converted to a gdb::byte_vector, so that the register contents' size can
be tracked.

Approved-By: Simon Marchi <simon.marchi@efficios.com>
2025-01-09 22:47:21 -03:00
Tom Tromey
8ac42dbf50 Handle linesStartAt1 in DAP
The DAP initialize request has a "linesStartAt1" option, where the
client can indicate that it prefers whether line numbers be 0-based or
1-based.

This patch implements this.  I audited all the line-related code in
the DAP implementation.

Note that while a similar option exists for column numbers, gdb
doesn't handle these yet, so nothing is done here.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32468
2025-01-06 07:32:11 -07:00
Tom Tromey
1c7d9f96cb Use 'flags' when expanding symtabs in gdbpy_lookup_static_symbols
This changes gdbpy_lookup_static_symbols to pass the 'flags' parameter
to expand_symtabs_matching.  This should refine the search somewhat.
Note this is "just" a performance improvement, as the loop over
symtabs already checks 'flags'.

v2 also removes 'SEARCH_GLOBAL_BLOCK' and updates py-symbol.exp to
verify that this works properly.  Thanks to Tom for this insight.

Co-Authored-By: Tom de Vries <tdevries@suse.de>
2024-12-31 13:35:38 -07:00
Tom Tromey
cd676397e5 Fix latent bug in gdbpy_lookup_static_symbols
gdbpy_lookup_static_symbols is missing an error check for the case
where symbol_to_symbol_object returns NULL.

Approved-By: Tom de Vries <tdevries@suse.de>
2024-12-20 10:00:13 -07:00
Tom Tromey
cc70964032 Run check-include-guards.py
This patch is the result of running check-include-guards.py on the
current tree.  Running it a second time causes no changes.

Reviewed-By: Tom de Vries <tdevries@suse.de>
2024-12-18 10:00:44 -07:00
Tom Tromey
72491a6a7e Re-run isort
I noticed that an earlier commit caused a change in the isort output.
This patch repairs the problem.
2024-12-16 10:46:40 -07:00
Tom de Vries
fff601fb30 [gdb/dap] Fix regressions with python 3.6
With test-case gdb.dap/ada-arrays.exp, on Leap openSUSE 15.6 with python 3.6,
I run into:
...
Python Exception <class 'TypeError'>: 'type' object is not subscriptable
Error occurred in Python: 'type' object is not subscriptable
ERROR: tcl error sourcing ada-arrays.exp.
...

This is due to using a python 3.9 construct:
...
thread_ids: dict[int, int] = {}
...

Fix this by using typing.Dict instead.

Tested on x86_64-linux.
2024-12-14 09:36:37 +01:00
oltolm
7336a8977d gdb/dap: allow some requests when the process is running
It is impossible to set a breakpoint when the process is running,
which I find annoying. LLDB does not have this restriction. I made
`setBreakpoints` and `breakpointLocations` work when the process is
running. Probably more requests can be changed, but I only need these
two at the moment.

Approved-By: Tom Tromey <tom@tromey.com>
2024-12-13 09:48:00 -07:00
Oleg Tolmatcev
83c1269833 gdb-dap: fix gdb.error: Frame is invalid.
When you try to use a frame on one thread and it was created on
another you get an error. I fixed it by creating a map from a frame ID
to a thread ID. When a frame is created it is added to the map. When
you try to find a frame for an id it checks if it is on the correct
thread and if not switches to that thread. I had to store the frame id
instead of the frame itself in a "_ScopeReference".

Signed-off-by: Oleg Tolmatcev <oleg.tolmatcev@gmail.com>
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32133
Approved-By: Tom Tromey <tom@tromey.com>
2024-12-13 09:46:15 -07:00
Tom Tromey
4c2d19e3cd Introduce NoOpStringPrinter
We discovered that attempting to print a very large string-like array
would succeed on the CLI, but in DAP would cause the "variables"
request to fail with:

  value requires 67038491 bytes, which is more than max-value-size

This turns out to be a limitation in Value.format_string, which
de-lazy-ifies the value.

This patch fixes this problem by introducing a new NoOpStringPrinter
class, and then using it for string-like values.  This printer returns
a lazy string, which solves the problem.

Note there are some special cases where we do not want to return a
lazy string.  I've documented these in the code.  I considered making
gdb.Value.lazy_string handle these cases -- for example it could
return 'self' rather than a lazy string in some situations -- but this
approach was simpler.
2024-12-09 14:26:23 -07:00
Tom Tromey
c286bfe1e5 Clean up 0-length handling in gdbpy_create_lazy_string_object
gdbpy_create_lazy_string_object will throw an exception if you pass it
a NULL pointer without also setting length=0 -- the default,
length==-1, will fail.  This seems bizarre.  Furthermore, it doesn't
make sense to do this check for array types, as an array can have a
zero length.  This patch cleans up the check and makes it specific to
TYPE_CODE_PTR.
2024-12-09 14:17:23 -07:00
Tom Tromey
2134b0b4a5 Reject non-string types in gdb.Value.lazy_string
Currently, gdb.Value.lazy_string will allow the conversion of any
object to a "lazy string".  However, this was never the intent and is
weird besides.  This patch changes this code to correctly throw an
exception in the non-matching cases.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=20769
2024-12-09 14:17:21 -07:00
Tom Tromey
9ba5ef4bf1 Omit artificial symbols from DAP variables response
While testing DAP, we found a situation where a compiler-generated
variable caused the "variables" request to fail -- the variable in
question being an apparent 67-megabyte string.

It seems to me that artificial variables like this aren't interesting
to DAP users, and the gdb CLI omits these as well.

This patch changes DAP to omit these variables, adding a new
gdb.Symbol.is_artificial attribute to make this possible.
2024-12-09 14:05:02 -07:00
Tom Tromey
6b9efd5c1a Defer DAP launch command until after configurationDone
PR dap/32090 points out that gdb's DAP "launch" sequencing is
incorrect.  The current approach (which is itself a 2nd
implementation...) was based on a misreading of the spec.  The spec
has since been clarified here:

    https://github.com/microsoft/debug-adapter-protocol/issues/497

The clarification here is that a client is free to send the "launch"
(or "attach") request at any point after the "initialized" event has
been sent by gdb.  However, the "launch" does not cause any action to
be taken -- and does not send a response -- until after
"configurationDone" has been seen.

This patch implements this by arranging for the launch and attach
commands to return a DeferredRequest object.

All the tests needed updates.  I've also added a new test that checks
that the deferred "launch" request can be cancelled.  (Note that the
cancellation is lazy -- it also waits until configurationDone is seen.
This could be fixed, but I was not sure whether it is important to do
so.)

Finally, the "launch" command has a somewhat funny sequencing now.
Simply sending the command and waiting for a response yielded strange
results if the inferior did not stop -- in this case, the repsonse was
never sent.  So now, the command is split into two parts, with some
setup being done synchronously (for better error propagation) and the
actual "run" being done async.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32090
Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
2024-12-09 13:52:54 -07:00
Tom Tromey
4baa278955 Add DAP deferred requests
This adds a new "deferred request" capability to DAP.  The idea here
is that if a request returns a DeferredRequest object, then no
response is sent immediately to the client.  Instead, the request is
pending until the deferred request is rescheduled.

Some minor refactorings, particularly in cancellation, were needed to
make this work.

There's no use of this in the tree yet -- that is the next patch.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
2024-12-09 13:52:54 -07:00
Tom Tromey
55980c88d4 Allow cancellation of DAP-thread requests
This patch started as an attempt to fix the comment in
CancellationHandler.cancel, but while working on it I found that the
code could be improved as well.

The current DAP cancellation code only handles the case where work is
done on the gdb thread -- by checking for cancellation in
interruptable_region.  This means that if a request is handled
completely in tthe DAP thread, then cancellation will never work.

Now, this isn't a bug per se.  DAP doesn't actually require that
cancellation succeed.  In fact, I think it can't, because cancellation
is inherently racy.

However, a coming patch will add a sort of "pending" request, and it
would be nice if that were cancellable before any commands are sent to
the gdb thread.

No test in this patch, but one will arrive at the end of the series.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
2024-12-09 13:52:54 -07:00
Tom Tromey
d8e96210c0 Refactor CancellationHandler in DAP
This refactors the DAP CancellationHandler to be a context manager,
and reorganizes the caller to use this.  This is a bit more robust and
also simplifies a subsequent patch in this series.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
2024-12-09 13:52:54 -07:00
Tom Tromey
278b1d211d Add call_function_later to DAP
This adds a new call_function_later API to DAP.  This arranges to run
a function after the current request has completed.  This isn't used
yet, but will be at the end of this series.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
2024-12-09 13:52:54 -07:00
Tom Tromey
00ce087f83 Reimplement DAP delayed events
This patch changes how delayed events are implemented in DAP.  The new
implementation makes it simpler to add a delayed function call, which
will be needed by the final patch in this series.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
2024-12-09 13:52:54 -07:00
Tom Tromey
d50cf1cea8 Reimplement DAP's stopAtBeginningOfMainSubprogram
Right now, stopAtBeginningOfMainSubprogram is implemented "by hand",
but then later the launch function uses "starti" to implement
stopOnEntry.  This patch unifies this code and rewrites it to use
"start" when appropriate.

Reviewed-by: Kévin Le Gouguec <legouguec@adacore.com>
2024-12-09 13:52:54 -07:00
Tom de Vries
6a02aa77d8 [gdb/python] Issue warning if python fails to initialize
A common problem is that python may fail to initialize if PYTHONHOME is
set incorrectly, or points to incompatible default libraries.

Likewise if PYTHONPATH points to incompatible modules.

For instance, say PYTHONHOME is foo, then we get:
...
$ gdb -q
Python path configuration:
  PYTHONHOME = 'foo'
  PYTHONPATH = (not set)
  program name = '/usr/bin/python'
  isolated = 0
  environment = 1
  user site = 1
  safe_path = 0
  import site = 1
  is in build tree = 0
  stdlib dir = 'foo/lib64/python3.12'
  sys._base_executable = '/usr/bin/python'
  sys.base_prefix = 'foo'
  sys.base_exec_prefix = 'foo'
  sys.platlibdir = 'lib64'
  sys.executable = '/usr/bin/python'
  sys.prefix = 'foo'
  sys.exec_prefix = 'foo'
  sys.path = [
    'foo/lib64/python312.zip',
    'foo/lib64/python3.12',
    'foo/lib64/python3.12/lib-dynload',
  ]
Python Exception <class 'ModuleNotFoundError'>: No module named 'encodings'
Python not initialized
$
...

In this case, it might be easy to figure out what went wrong because of the
obviously incorrect pathnames, but that might not be the case if PYTHONHOME
points to an incompatible python installation.

Fix this by adding a warning with a description of the possible cause and what
to do about it:
...
Python initialization failed: \
  failed to get the Python codec of the filesystem encoding
gdb: warning: Python failed to initialize with PYTHONHOME set.  Maybe because \
  it is set incorrectly? Maybe because it points to incompatible standard \
  libraries? Consider changing or unsetting it, or ignoring it using "set \
  python ignore-environment on" at early initialization.
...

Likewise for PYTHONPATH:
...
Python initialization failed: \
  failed to get the Python codec of the filesystem encoding
gdb: warning: Python failed to initialize with PYTHONPATH set.  Maybe because \
  it points to incompatible modules? Consider changing or unsetting it, or \
  ignoring it using "set python ignore-environment on" at early \
  initialization.
...

Tested on aarch64-linux.

Approved-By: Tom Tromey <tom@tromey.com>

PR python/32379
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32379
2024-12-03 22:58:47 +01:00
Tom de Vries
922ab963e1 [gdb/python] Handle empty PYTHONDONTWRITEBYTECODE
When using PYTHONDONTWRITEBYTECODE with an empty string we get:
...
$ PYTHONDONTWRITEBYTECODE= gdb -q -batch -ex "show python dont-write-bytecode"
Python's dont-write-bytecode setting is auto (currently on).
...

This is incorrect, it should be off.

The actual setting is correct, that was already fixed in commit 24d2cbc42c
("set/show python dont-write-bytecode fixes"), in function
python_write_bytecode.

Fix this by:
- factoring out new function env_python_dont_write_bytecode out of
  python_write_bytecode, and
- using it in show_python_dont_write_bytecode.

Tested on x86_64-linux, using test-case gdb.python/py-startup-opt.exp and:
- PYTHONDONTWRITEBYTECODE=
- PYTHONDONTWRITEBYTECODE=1
- unset PYTHONDONTWRITEBYTECODE

Approved-By: Tom Tromey <tom@tromey.com>

PR python/32389
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32389
2024-12-03 22:54:23 +01:00
Tom de Vries
348290c7ef [gdb/python] Warn and ignore ineffective python settings
Configuration flags "python dont-write-bytecode" and
"python ignore-environment" have effect only at Python initialization.

For instance, setting "python dont-write-bytecode" here has no effect:
...
$ gdb -q
(gdb) show python dont-write-bytecode
Python's dont-write-bytecode setting is auto (currently off).
(gdb) python import sys
(gdb) python print (sys.dont_write_bytecode)
False
(gdb) set python dont-write-bytecode on
(gdb) python print (sys.dont_write_bytecode)
False
...

This is not clear in the code: we set Py_DontWriteBytecodeFlag and
Py_IgnoreEnvironmentFlag in set_python_ignore_environment and
set_python_dont_write_bytecode.  Fix this by moving the setting of those
variables to py_initialization.

Furthermore, this is not clear to the user: after Python initialization, the
user can still modify the configuration flags, and observe the changed setting:
...
$ gdb -q
(gdb) show python ignore-environment
Python's ignore-environment setting is off.
(gdb) set python ignore-environment on
(gdb) show python ignore-environment
Python's ignore-environment setting is on.
(gdb)
...

Fix this by emitting a warning when trying to set these configuration flags
after Python initialization:
...
$ gdb -q
(gdb) set python ignore-environment on
warning: Setting python ignore-environment after Python initialization has \
  no effect, try setting this during early initialization
(gdb) set python dont-write-bytecode on
warning: Setting python dont-write-bytecode after Python initialization has \
  no effect, try setting this during early initialization, or try setting \
  sys.dont_write_bytecode
...
and by keeping the values constant after Python initialization.

Since the auto setting for python dont-write-bytecode depends on the current
value of environment variable PYTHONDONTWRITEBYTECODE, we simply avoid it
after Python initialization:
...
$ gdb -q -batch \
    -eiex "show python dont-write-bytecode" \
    -iex "show python dont-write-bytecode"
Python's dont-write-bytecode setting is auto (currently off).
Python's dont-write-bytecode setting is off.
...

Tested on aarch64-linux.

Approved-By: Tom Tromey <tom@tromey.com>

PR python/32388
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32388
2024-12-03 22:49:40 +01:00
Tom de Vries
c9b37bc997 [gdb/python] Drop ATTRIBUTE_UNUSED on py_initialize_catch_abort
I added ATTRIBUTE_UNUSED to py_initialize_catch_abort as a quick fix to deal
with it being unused for PY_VERSION_HEX >= 0x030a0000, but forgot to fix this
before committing.

Fix this now, by removing the attribute and using
'#if PY_VERSION_HEX < 0x030a0000' instead.

Tested on aarch64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-12-03 22:49:40 +01:00
Tom de Vries
125f702105 [gdb/python] Factor out and refactor py_initialize
Function do_start_initialization has a large part dedicated to initializing
the python interpreter, as opposed to the rest of the function where
gdb-specific python support is initialized.

Factor out this part, as new function py_initialize, and rename the existing
py_initialize to py_initialize_catch_abort.

Refactor the new function py_initialize by getting rid of the nested:
...
 #ifdef WITH_PYTHON_PATH
 #if PY_VERSION_HEX < 0x030a0000
 #else
 #endif
 #else
 #endif
...

In particular, this changes behaviour for the "!defined (WITH_PYTHON_PATH)"
case.

For the "defined (WITH_PYTHON_PATH)" case, we've started using
Py_InitializeFromConfig () for PY_VERSION_HEX >= 0x030a0000 to deal with the
deprecation of Py_SetProgramName in 3.11.

For the "!defined (WITH_PYTHON_PATH)" case, we don't use Py_SetProgramName so
we stuck with Py_Initialize ().

However, in 3.12 Py_DontWriteBytecodeFlag and Py_IgnoreEnvironmentFlag got
deprecated and also here we need Py_InitializeFromConfig () to deal with this,
but the "!defined (WITH_PYTHON_PATH)" case didn't get updated.

This should be taken care of, now that we have this behavior:
- for PY_VERSION_HEX < 0x030a0000 we use Py_Initialize
- for PY_VERSION_HEX >= 0x030a0000 we use Py_InitializeFromConfig

I'm not sure how to test the "!defined (WITH_PYTHON_PATH)" though.

Tested on aarch64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-12-03 22:49:40 +01:00
Simon Marchi
112f6d85fb Convert type copying to new hash table
This converts the type copying code to use the new hash map.

Change-Id: I35f0a4946dcc5c5eb84820126cf716b600f3302f
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
2024-11-25 22:07:04 -05:00
Simon Marchi
52dedd71c8 Convert py-framefilter.c to new hash table
This converts py-framefilter.c to use the new hash table.

Change-Id: I38f4eaa8ebbcd4fd6e5e8ddc462502a92bf62f5e
Co-Authored-By: Tom Tromey <tom@tromey.com>
Approved-By: Tom Tromey <tom@tromey.com>
2024-11-25 22:07:04 -05:00
Tom de Vries
ac51afb51c [gdb/contrib] Add two rules in common-misspellings.txt
Eli mentioned [1] that given that we use US English spelling in our
documentation, we should use "behavior" instead of "behaviour".

In wikipedia-common-misspellings.txt there's a rule:
...
behavour->behavior, behaviour
...
which leaves this as a choice.

Add an overriding rule to hardcode the choice to common-misspellings.txt:
...
behavour->behavior
...
and add a rule to rewrite behaviour into behavior:
...
behaviour->behavior
...
and re-run spellcheck.sh on gdb*.

Tested on x86_64-linux.

[1] https://sourceware.org/pipermail/gdb-patches/2024-November/213371.html
2024-11-23 12:20:34 +01:00
Tom de Vries
372d0a4c96 [gdb/python] Handle failure to initialize without exiting
I tried out making python initialization fail by passing an incorrect
PYTHONHOME, and got:
...
$ PYTHONHOME=foo ./gdb.sh -q
Python path configuration:
  PYTHONHOME = 'foo'
  ...
Python initialization failed: \
  failed to get the Python codec of the filesystem encoding
Python not initialized
$
...

The relevant part of the code is:
...
static void
gdbpy_initialize (const struct extension_language_defn *extlang)
{
  if (!do_start_initialization () && py_isinitialized && PyErr_Occurred ())
    gdbpy_print_stack ();

   gdbpy_enter enter_py;
...

What happens is:
- gdbpy_enter::gdbpy_enter () is called, where we run into:
  'if (!gdb_python_initialized) error (_("Python not initialized"));'
- the error propagates to gdb's toplevel
- gdb print the error and exits.

It seems unnecesssary that we exit gdb.  We could continue the
session without python support.

Fix this by:
- bailing out of gdbpy_initialize if !do_start_initialization
- bailing out of finalize_python if !gdb_python_initialized

This gets us instead:
...
$ PYTHONHOME=foo gdb -q
Python path configuration:
  PYTHONHOME = 'foo'
  ...
Python initialization failed: \
  failed to get the Python codec of the filesystem encoding
(gdb) python print (1)
Python not initialized
(gdb)
...

Tested on aarch64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-11-22 19:34:24 +01:00
Tom de Vries
9d3785a8ac [gdb/python] Fix abort on Py_Initialize
I tried out making python initialization fail by passing an incorrect
PYTHONHOME with python 3.6, and got:
...
$ PYTHONHOME=foo gdb -q
Fatal Python error: Py_Initialize: Unable to get the locale encoding
ModuleNotFoundError: No module named 'encodings'

Current thread 0x0000ffff89269c80 (most recent call first):

Fatal signal: Aborted
  ...
Aborted (core dumped)
$
...

This is as per spec: when Py_Initialize () fails, a fatal error is raised
using Py_FatalError.

This can be worked around using:
...
$ PYTHONHOME=foo gdb -q -eiex "set python ignore-environment on"
(gdb)
...
but it would be better if gdb didn't abort.

I found an article [1] describing two solutions:
- try out Py_Initialize in a separate process, and
- catch the abort using a signal handler.

This patch implements the latter solution.

Obviously we cannot call into python anymore after the abort, so we avoid
calling Py_IsInitialized (), and instead use a new variable py_isinitialized.

This gets us instead:
...
$ PYTHONHOME=foo gdb -q
Fatal Python error: Py_Initialize: Unable to get the locale encoding
ModuleNotFoundError: No module named 'encodings'

Current thread 0x0000fffecfd49c80 (most recent call first):
Python not initialized
$
...

Tested on aarch64-linux.

Approved-By: Tom Tromey <tom@tromey.com>

PR python/32379
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32379

[1] https://stackoverflow.com/questions/7688374/how-to-i-catch-and-handle-a-fatal-error-when-py-initialize-fails
2024-11-22 19:34:24 +01:00
Tom de Vries
e5eca01155 [gdb/python] Handle !Py_IsInitialized () in gdbpy_initialize
I tried out making python initialization fail by passing an incorrect
PYTHONHOME, and got:
...
$ PYTHONHOME=foo gdb -q
Python path configuration:
  PYTHONHOME = 'foo'
  ...
Python Exception <class 'ModuleNotFoundError'>: No module named 'encodings'
Python not initialized
$
...

The relevant part of the code is:
...
static void
gdbpy_initialize (const struct extension_language_defn *extlang)
{
  if (!do_start_initialization () && PyErr_Occurred ())
    gdbpy_print_stack ();

   gdbpy_enter enter_py;
...

What happens is that:
- do_start_initialization returns false because Py_InitializeFromConfig fails,
  leaving us in the !Py_IsInitialized () state
- PyErr_Occurred () returns true
- gdbpy_print_stack is called, which prints
  "Python Exception <class 'ModuleNotFoundError'>: No module named 'encodings"

The problem is that in the Py_IsInitialized () == false state, very few
functions can be called, and PyErr_Occurred is not one of them [1], and
likewise functions in gdbpy_print_stack.

Fix this by:
- guarding the PyErr_Occurred / gdbpy_print_stack part with Py_IsInitialized ().
- handling the !Py_IsInitialized () case by printing the failure PyStatus
  in do_start_initialization

This gets us instead:
...
$ PYTHONHOME=foo ./gdb.sh -q
Python path configuration:
  PYTHONHOME = 'foo'
  ...
Python initialization failed: failed to get the Python codec of the filesystem encoding
Python not initialized
$
...

Tested on aarch64-linux.

Approved-By: Tom Tromey <tom@tromey.com>

[1] https://docs.python.org/3/c-api/init.html#before-python-initialization
2024-11-22 19:34:24 +01:00
Tom de Vries
8a7f13063a [gdb/python] Ensure locale is restored in do_start_initialization
I noticed in do_start_initialization:
...
  std::string oldloc = setlocale (LC_ALL, NULL);
  setlocale (LC_ALL, "");
  ...
  if (count == (size_t) -1)
    {
      fprintf (stderr, "Could not convert python path to string\n");
      return false;
    }
  setlocale (LC_ALL, oldloc.c_str ());
...
that the old locale is not restored if the "return false" is triggered.

Fix this by using SCOPE_EXIT.

Tested on aarch64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-11-22 17:34:50 +01:00
Andrew Burgess
661611b9d7 gdb/python: fix reference leak in gdb.BreakpointLocation.thread_groups
While reviewing another patch which uses PyList_Append I took a look
at our other uses of PyList_Append in GDB.  I spotted something odd
about the use in bplocpy_get_thread_groups.

We do:

    gdbpy_ref<> num = gdb_py_object_from_ulongest (inf->num);

At which point `num` will own a reference to the `int` object.  But
when we add the object to the result list we do:

    if (PyList_Append (list.get (), num.release ()) != 0)
      return nullptr;

By calling `release` we pass ownership of the reference to
PyList_Append, however, PyList_Append acquires its own reference, it
doesn't take ownership of an existing reference.

The consequence of this is that we leak the reference held in `num`.

This mostly isn't a problem though.  For small (< 257) integers Python
keeps a single instance of each and just hands out new references.  By
leaking the references, these small integers will not be cleaned up as
the Python interpreter shuts down, but that is only done when GDB
exits, so hardly a disaster.  As we're dealing with GDB's internal
inferior number here, unless the user has 257+ inferiors, we'll not
actually be leaking memory.

Still, lets do things right.  Switch to using `num.get ()`.  Now when
`num` goes out of scope it will decrement the reference count as
needed.

Approved-By: Tom Tromey <tom@tromey.com>
2024-11-20 09:33:17 +00:00
Andrew Burgess
8518ce5fc2 gdb/python: missing PyObject_IsTrue error check in bppy_init
As with the previous two commits, this commit fixes a location where
we called PyObject_IsTrue without including an error check, this time
in bppy_init.

The 'qualified' argument is supposed to be a bool, the docs say:

  The optional QUALIFIED argument is a boolean that allows
  interpreting the function passed in 'spec' as a fully-qualified
  name.  It is equivalent to 'break''s '-qualified' flag (*note
  Linespec Locations:: and *note Explicit Locations::).

It's not totally clear that the only valid values are True or False,
but I'm choosing to interpret the docs that way, and so I've added a
PyBool_Type check during argument parsing.  Now, if a non-bool is
passed the user will get a TypeError during argument parsing.  I've
added a test to cover this case.

This is a potentially breaking change to the Python API, but hopefully
this will not impact too many people.  I've added a NEWS entry to
highlight this change.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
2024-11-14 19:34:44 +00:00
Andrew Burgess
ad39b4aae8 gdb/python: missing PyObject_IsTrue error check in micmdpy_set_installed
Like the previous commit, I discovered that in micmdpy_set_installed
we were calling PyObject_IsTrue, but not checking for a possible error
value being returned.

The micmdpy_set_installed function implements the
gdb.MICommand.installed attribute, and the documentation indicates that
this attribute should only be assigned a bool:

  This attribute is read-write, setting this attribute to 'False'
  will uninstall the command, removing it from the set of available
  commands.  Setting this attribute to 'True' will install the
  command for use.

So I propose that instead of using PyObject_IsTrue we use
PyBool_Check, and if the new value fails this check we raise an
error.  We can then compare the new value to Py_True directly instead
of calling PyObject_IsTrue.

This is a potentially breaking change to the Python API, but hopefully
this will not impact too many people, and the fix is pretty
easy (switch to using a bool).  I've added a NEWS entry to draw
attention to this change.

Approved-By: Tom Tromey <tom@tromey.com>
2024-11-14 19:34:44 +00:00
Andrew Burgess
5209b83f53 gdb/python: missing PyObject_IsTrue error check in py-arch.c
Building on the previous two commits, I was auditing our uses of
PyObject_IsTrue looking for places where we were missing an error
check.

The gdb.Architecture.integer_type() function takes a 'signed' argument
which should be a 'bool', and the docs do say:

  If SIGNED is not specified, it defaults to 'True'.  If SIGNED is
  'False', the returned type will be unsigned.

Currently we use PyObject_IsTrue, but we are missing an error check.

To fix this I've tightened the code to enforce the bool requirement at
the point that the arguments are parsed.  With that done I can remove
the call to PyObject_IsTrue and instead compare to Py_True directly,
the object in question will always be a PyBool_Type.

However, we were testing that passing a non-bool argument for 'signed'
is treated as Py_False, this was added with this commit:

  commit 90fe61ced1
  Date:   Mon Nov 29 13:53:06 2021 +0000

      gdb/python: don't use the 'p' format for parsing args

which is when the PyObject_IsTrue call was added.  Given that the docs
do seem pretty clear that only True or False are suitable argument
values, my proposal is that we just remove these tests and instead
test that any non-bool argument value for 'signed' gives a TypeError.

This is a breaking change to the Python API, however, my hope is that
this is such a edge case that it will not cause too many problem.
I've added a NEWS entry to highlight this change though.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Approved-By: Tom Tromey <tom@tromey.com>
2024-11-14 19:34:43 +00:00
Andrew Burgess
d8a2c719da gdb/python: remove some additional PyObject_IsTrue calls
After the previous commit I audited all our uses of PyObject_IsTrue
looking for places where we were missing an error check.  I did find
some that are missing error checks in places where we really should
have error checks, and I'll fix those in later commits.

This commit however, focuses on those locations where PyObject_IsTrue
is called, there is no error check, and the error check isn't really
necessary because we already know that the object we are dealing with
is of type PyBool_Type.

Inline with the previous commit, in these cases I have removed the
PyObject_IsTrue call, and replaced it with a comparison against
Py_True.  In one location where it is not obvious that the object we
have is PyBool_Type I've added an assert, but in the other cases the
comparison to Py_True immediately follows a PyBool_Check call, so an
assert would be redundant.

I've added a test for the gdb.Value.format_string styling argument
being passed a non-bool value as this wasn't previously being tested,
though this new test will pass before and after this commit.

There should be no functional change after this commit.

Approved-By: Tom Tromey <tom@tromey.com>
2024-11-14 19:34:43 +00:00
Andrew Burgess
dcf4c48453 gdb/python: remove PyObject_IsTrue call in gdbpy_handle_missing_debuginfo
In this review:

  https://inbox.sourceware.org/gdb-patches/87wmirfzih.fsf@tromey.com

Tom pointed out that using PyObject_IsTrue as I was doing, though
technically fine, at least appears to be missing an error check, and
that it would be better to compare to Py_True directly.  I made that
change in the patch Tom was commenting on, but I'd actually copied
that code from elsewhere in python/python.c, so this commit updates
the original code inline with Tom's review feedback.

There should be no functional change after this commit.

Approved-By: Tom Tromey <tom@tromey.com>
2024-11-14 19:34:43 +00:00
Tom Tromey
bf0a217775 Call gdbpy_fix_doc_string_indentation for function help
If you invoke "help function _caller_is", you'll see that the help
text is indented strangely.  The fix for this is to add a call to
gdbpy_fix_doc_string_indentation in the appropriate spot, as is
already done for Python commands and parameters.
2024-11-11 07:44:27 -07:00
Pedro Silva
272eacf34f gdb: fix missing operator % on xmethod matcher output
Fixed missing operator % on xmethod matcher registration output and, as
suggested on bug 32532, converted both uses of operator % to str.format.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32352
Change-Id: Ic471516292c2f1d6d1284aaeaea3ec14421decb8
2024-11-11 08:49:13 -05:00
Andrew Burgess
5cabc8098e gdb/python: implement Python find_exec_by_build_id hook
Implement extension_language_ops::find_objfile_from_buildid within
GDB's Python API.  Doing this allows users to write Python extensions
that can help locate missing objfiles when GDB opens a core file.  A
handler might perform some project- or site-specific actions to find a
missing objfile.  Or might provide some project- or site-specific
advice to the user on how they can obtain the missing objfile.

The implementation is very similar to the approach taken in:

  commit 8f6c452b5a
  Date:   Sun Oct 15 22:48:42 2023 +0100

      gdb: implement missing debug handler hook for Python

The following new commands are added as commands implemented in
Python, this is similar to how the Python missing debug and unwinder
commands are implemented:

  info missing-objfile-handlers
  enable missing-objfile-handler LOCUS HANDLER
  disable missing-objfile-handler LOCUS HANDLER

To make use of this extension hook a user will create missing objfile
handler objects, and registers these handlers with GDB.  When GDB
opens a core file and encounters a missing objfile each handler is
called in turn until one is able to help.  Here is a minimal handler
that does nothing useful:

  import gdb
  import gdb.missing_objfile

  class MyFirstHandler(gdb.missing_objfile.MissingObjfileHandler):
      def __init__(self):
          super().__init__("my_first_handler")

      def __call__(self, pspace, build_id, filename):
          # This handler does nothing useful.
          return None

  gdb.missing_objfile.register_handler(None, MyFirstHandler())

Returning None from the __call__ method tells GDB that this handler
was unable to find the missing objfile, and GDB should ask any other
registered handlers.

Possible return values from a handler:

  - None: This means the handler couldn't help.  GDB will call other
          registered handlers to see if they can help instead.

  - False: The handler has done all it can, but the objfile couldn't
            be found.  GDB will not call any other handlers, and will
	    continue without the objfile.

  - True: The handler has installed the objfile into a location where
          GDB would normally expect to find it.  GDB should repeat its
	  normal lookup process and the objfile should now be found.

  - A string: The handler can return a filename, which is the missing
              objfile.  GDB will load this file.

Handlers can be registered globally, or per program space.  GDB checks
the handlers for the current program space first, and then all of the
global handles.  The first handler that returns a value that is not
None, has "handled" the missing objfile, at which point GDB continues.

The implementation of this feature is mostly straight forward.  I have
reworked some of the missing debug file related code so that it can be
shared with this feature.  E.g. gdb/python/lib/gdb/missing_files.py is
mostly content moved from gdb/python/lib/gdb/missing_debug.py, but
updated to be more generic.  Now gdb/python/lib/gdb/missing_debug.py
and the new file gdb/python/lib/gdb/missing_objfile.py both call into
the missing_files.py file.

For gdb/python/lib/gdb/command/missing_files.py this is even more
extreme, gdb/python/lib/gdb/command/missing_debug.py is completely
gone now and gdb/python/lib/gdb/command/missing_files.py provides all
of the new commands in a generic way.

I have made one change to the existing Python API, I renamed the
attribute Progspace.missing_debug_handlers to
Progspace.missing_file_handlers.  I don't see this as too
problematic.  This attribute was only used to implement the missing
debug feature and was never documented beyond the fact that it
existed.  There was no reason for users to be touching this attribute.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-11-10 10:18:23 +00:00
Andrew Burgess
629bcc68d7 gdb: rename ext_lang_missing_debuginfo_result
In preparation for later commits in this series, rename
ext_lang_missing_debuginfo_result to ext_lang_missing_file_result.

A later commit will add additional Python APIs to handle different
types of missing files beyond just debuginfo.

This is just a rename commit, there should be no functional changes
after this commit.

Approved-By: Tom Tromey <tom@tromey.com>
2024-11-10 10:18:22 +00:00
Tom Tromey
76367d2314 Add gdb.events.tui_enabled
This adds a new event source so that Python scripts can track whether
or not the TUI is presently enabled.

v2 of the patch renames "status" -> "enabled".

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32162
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-11-01 11:06:47 -06:00
Tom Tromey
32af040ef2 Require a command argument in gdb.execute_mi
Hannes pointed out that gdb.execute_mi() will crash.
This patch fixes the bug.

Reviewed-By: Guinevere Larsen <guinevere@redhat.com>
2024-10-18 11:50:27 -06:00
Tom de Vries
8f6606b6e3 [gdb] Fix common misspellings
Fix the following common misspellings:
...
accidently -> accidentally
additonal -> additional
addresing -> addressing
adress -> address
agaisnt -> against
albiet -> albeit
arbitary -> arbitrary
artifical -> artificial
auxillary -> auxiliary
auxilliary -> auxiliary
bcak -> back
begining -> beginning
cannonical -> canonical
compatiblity -> compatibility
completetion -> completion
diferent -> different
emited -> emitted
emiting -> emitting
emmitted -> emitted
everytime -> every time
excercise -> exercise
existance -> existence
fucntion -> function
funtion -> function
guarentee -> guarantee
htis -> this
immediatly -> immediately
layed -> laid
noone -> no one
occurances -> occurrences
occured -> occurred
originaly -> originally
preceeded -> preceded
preceeds -> precedes
propogate -> propagate
publically -> publicly
refering -> referring
substract -> subtract
substracting -> subtracting
substraction -> subtraction
taht -> that
targetting -> targeting
teh -> the
thier -> their
thru -> through
transfered -> transferred
transfering -> transferring
upto -> up to
vincinity -> vicinity
whcih -> which
whereever -> wherever
wierd -> weird
withing -> within
writen -> written
wtih -> with
doesnt -> doesn't
...

Tested on x86_64-linux.
2024-10-06 07:59:48 +02:00
oltolm
59529d80e8 gdb-dap: disable events when deleting breakpoints
when I disable a breakpoint in VS Code the breakpoint is removed
instead. I compared the behavior to lldb-dap and disabled events when
removing a breakpoint. Now it is possible to disable and enable
breakpoints in VS Code.
2024-10-03 11:12:40 -06:00
Tom Tromey
887ae0cf2b Add line-number styling
This patch adds separate styling for line numbers.  That is, whenever
gdb prints a source line number, it uses this style.

v2 includes a change to ensure that %ps works in query.

Reviewed-By: Eli Zaretskii <eliz@gnu.org>
Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-09-30 13:23:35 -06:00
Tom de Vries
dfba4847f6 [gdb/python] Make sure python sys.exit makes gdb exit
With gdb 15.1, python sys.exit no longer makes gdb exit:
...
$ gdb -q -batch -ex "python sys.exit(2)" -ex "print 123"; echo $?
Python Exception <class 'SystemExit'>: 2
Error occurred in Python: 2
$1 = 123
0
...

This is a change in behaviour since commit a207f6b3a3 ("Rewrite "python"
command exception handling"), first available in gdb 15.1.

This patch reverts to the old behaviour by handling PyExc_SystemExit in
gdbpy_handle_exception, such what we have instead:
...
$ gdb -q -batch -ex "python sys.exit(2)" -ex "print 123"; echo $?
2
...

Tested on x86_64-linux, with python 3.6 and 3.13.

Tested-By: Guinevere Larsen <blarsen@redhat.com>
Approved-By: Tom Tromey <tom@tromey.com>

PR python/31946
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31946
2024-09-25 19:29:57 +02:00
Schimpe, Christina
fc14343205 gdb, gdbserver, python, testsuite: Remove MPX.
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>
2024-09-25 11:06:57 +00:00