Commit Graph

1615 Commits

Author SHA1 Message Date
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
Schimpe, Christina
ee06c79b0f gdb, testsuite, python: Add missing imports.
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>
2024-09-25 11:04:45 +00:00
Felix Willgerodt
cdd65168f3 btrace: Add support for interrupt events.
Newer Intel CPUs support recording asynchronous events in the PT trace.
Libipt also recently added support for decoding these.

This patch adds support for interrupt events, based on the existing aux
infrastructure.  GDB can now display such events during the record
instruction-history and function-call-history commands.

Subsequent patches will add the rest of the events currently supported.

Approved-By: Markus Metzger <markus.t.metzger@intel.com>
2024-09-24 14:22:28 +02:00
Tom de Vries
e1863c7d7c [gdb/python] Use gdbpy_handle_gdb_exception in valpy_assign_core
In valpy_assign_core we have:
...
  catch (const gdb_exception &except)
    {
      gdbpy_convert_exception (except);
      return false;
     }
...

Use instead:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception (false, except);
    }
...

No functional changes.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-24 13:06:32 +02:00
Tom de Vries
fa61a48db2 [gdb/python] Eliminate GDB_PY_SET_HANDLE_EXCEPTION
Result of:
...
$ search="GDB_PY_SET_HANDLE_EXCEPTION ("
$ replace="return gdbpy_handle_gdb_exception (-1, "
$ sed -i \
    "s/$search/$replace/" \
    gdb/python/*.c
...

Also remove the now unused GDB_PY_SET_HANDLE_EXCEPTION.

No functional changes.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-24 13:06:32 +02:00
Tom de Vries
1ccb6f106a [gdb/python] Eliminate GDB_PY_HANDLE_EXCEPTION
Result of:
...
$ search="GDB_PY_HANDLE_EXCEPTION ("
$ replace="return gdbpy_handle_gdb_exception (nullptr, "
$ sed -i \
    "s/$search/$replace/" \
    gdb/python/*.c
...

Also remove the now unused GDB_PY_HANDLE_EXCEPTION.

No functional changes.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-24 13:06:32 +02:00
Tom de Vries
912bc231ab [gdb/python] Add gdbpy_handle_gdb_exception
I've recently committed two patches:
- commit 2f8cd40c37 ("[gdb/python] Use GDB_PY_HANDLE_EXCEPTION more often")
- commit fbf8e4c35c ("[gdb/python] Use GDB_PY_SET_HANDLE_EXCEPTION more often")
which use the macros GDB_PY_HANDLE_EXCEPTION and GDB_PY_SET_HANDLE_EXCEPTION
more often, with the goal of making things more consistent.

Having done that, I wondered if a better approach could be possible.

Consider GDB_PY_HANDLE_EXCEPTION:
...
 /* Use this in a 'catch' block to convert the exception to a Python
    exception and return nullptr.  */
 #define GDB_PY_HANDLE_EXCEPTION(Exception)	\
   do {						\
     gdbpy_convert_exception (Exception);	\
     return nullptr;				\
   } while (0)
...

The macro nicely codifies how python handles exceptions:
- setting an error condition using some PyErr_Set* variant, and
- returning a value implying that something went wrong
presumably with the goal that using the macro will mean not accidentally:
- forgetting to return on error, or
- returning the wrong value on error.

The problems are that:
- the macro hides control flow, specifically the return statement, and
- the macro hides the return value.

For example, when reading somewhere:
...
  catch (const gdb_exception &except)
    {
      GDB_PY_HANDLE_EXCEPTION (except);
    }
...
in order to understand what this does, you have to know that the macro
returns, and that it returns nullptr.

Add a template gdbpy_handle_gdb_exception:
...
template<typename T>
[[nodiscard]] T
gdbpy_handle_gdb_exception (T val, const gdb_exception &e)
{
  gdbpy_convert_exception (e);
  return val;
}
...
which can be used instead:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception (nullptr, except);
    }
...

[ Initially I tried this:
...
template<auto val>
[[nodiscard]] auto
gdbpy_handle_gdb_exception (const gdb_exception &e)
{
  gdbpy_convert_exception (e);
  return val;
}
...
with which the usage is slightly better looking:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception<nullptr> (except);
    }
...
but I ran into trouble with older gcc compilers. ]

While still a single statement, we now have it clear:
- that the statement returns,
- what value the statement returns.

[ FWIW, this could also be handled by say:
...
-      GDB_PY_HANDLE_EXCEPTION (except);
+      GDB_PY_HANDLE_EXCEPTION_AND_RETURN_VAL (except, nullptr);
...
but I still didn't find the fact that it returns easy to spot.

Alternatively, this is the simplest form we could use:
...
      return gdbpy_convert_exception (e), nullptr;
...
but the pairing would not necessarily survive a copy/paste/edit cycle. ]

Also note how making the value explicit makes it easier to check for
consistency:
...
  catch (const gdb_exception &except)
    {
      return gdbpy_handle_gdb_exception (-1, except);
    }

  if (PyErr_Occurred ())
    return -1;
...
given that we do use the explicit constants almost everywhere else.

Compared to using GDB_PY_HANDLE_EXCEPTION, there is the burden now to specify
the return value, but I assume that this will be generally copy-pasted and
therefore present no problem.

Also, there's no longer a guarantee that there's an immediate return, but I
assume that nodiscard making sure that the return value is not silently
ignored is sufficient mitigation.

For now, re-implement GDB_PY_HANDLE_EXCEPTION and GDB_PY_SET_HANDLE_EXCEPTION
in terms of gdbpy_handle_gdb_exception.

Follow-up patches will eliminate the macros.

No functional changes.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-09-24 13:06:32 +02:00
Tom Tromey
336bb2a1c1 Automatically add types to Python modules
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>
2024-09-23 13:44:59 -06:00
oltolm
1136616707 gdb dap: introduce stopOnEntry option
Approved-By: Tom Tromey <tom@tromey.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-09-13 14:19:34 -06:00
Tom Tromey
c7e57281af Add quoting to 'file' invocations in DAP
Oleg Tolmatcev noticed that DAP launch and attach requests don't
properly handle Windows filenames, because "file" doesn't handle the
backslash characters correctly.  This patch adds quoting to the
command in an attempt to fix this.
2024-09-13 09:34:50 -06:00
Andrew Burgess
5ddd0d7eef gdb/python: avoid depending on the curses library
The commit:

  commit 29c7078711
  Date:   Sun Sep 8 07:46:09 2024 +0200

      [gdb/testsuite] Handle missing curses in gdb.python/py-missing-debug.exp

Highlighted that in some cases we might be running on a system with an
older version of Python (earlier than 3.7), and on a system for which
the curses library has not been installed.

In these circumstances the gdb.missing_debug module will not load as
it uses curses to provide isalnum() and isascii() functions.

To avoid this problem I propose that we copy the isalnum() and
isascii() from the Python curses library.  These functions are
basically trivial and removing the curses dependency means GDB will
work in more cases without increasing its dependencies.

I did consider keeping the uses of curses and only having the function
definitions be a fallback for when the curses library failed to load,
but this felt like overkill.  The function definitions are both tiny
and I think "obvious" given their specifications, so I figure we might
as well just use our own definitions if they are not available as
builtin methods on the str class.

For testing I changed this line:

  if sys.version_info >= (3, 7):

to

  if sys.version_info >= (3, 7) and False:

then reran gdb.python/py-missing-debug.exp, there were no failures.

Approved-By: Tom de Vries <tdevries@suse.de>
2024-09-10 14:07:11 +01:00
Tom Tromey
a35cc8ff85 Remove tui_wrefresh
This removes tui_wrefresh, moving the code into refresh_window.  We
remove tui_norefresh_window as well, because now the command window's
refresh_window has to do what tui_wrefresh previously did.
2024-09-07 14:23:04 -06:00
Tom Tromey
d3acf3d759 Rename tui_suppress_output
This patch renames tui_suppress_output to the more descriptive
tui_batch_rendering.  This code was never really correct, and was
based on a misunderstanding of the curses API.  The updated comments
describe the intended use of this class.

This also removes the erroneous tui_win_info::no_refresh.
wnoutrefresh does not prevent any output; rather, it copies from one
curses buffer to another but (unlike woutrefresh) without then
flushing to the screen.

tui_batch_rendering now works in the correct way: calling doupdate in
the destructor of the outermost instance, thus batching all screen
output until that point.

The patch adds instantiations of tui_batch_rendering to various spots,
to make sure it is active when refreshing.
2024-09-07 14:23:04 -06:00
Andrew Burgess
4076f962e8 gdb: split apart two different types of filename completion
Unfortunately we have two different types of filename completion in
GDB.

The majority of commands have what I call unquoted filename
completion, this is for commands like 'set logging file ...', 'target
core ...', and 'add-auto-load-safe-path ...'.  For these commands
everything after the command name (that is not a command option) is
treated as a single filename.  If the filename contains white space
then this does not need to be escaped, nor does the filename need to
be quoted.  In fact, the filename argument is not de-quoted, and does
not have any escaping removed, so if a user does try to add such
things, they will be treated as part of the filename.  As an example:

  (gdb) target core "/path/that contains/some white space"

Will look for a directory calls '"' (double quotes) in the local
directory.

A small number of commands do de-quote and remove escapes from
filename arguments.  These command accept what I call quoted and
escaped filenames.  Right now these are the commands that specify the
file for GDB to debug, so:

  file
  exec-file
  symbol-file
  add-symbol-file
  remove-symbol-file

As an example of this in action:

  (gdb) file "/path/that contains/some white space"

In this case GDB would load the file:

  /path/that contains/some white space

Current filename completion always assumes that filenames can be
quoted, though escaping doesn't work in completion right now.  But the
assumption that quoting is allowed is clearly wrong.

This commit splits filename completion into two.  The existing
filename_completer is retained, and is used for unquoted filenames.  A
second filename_maybe_quoted_completer is added which can be used for
completing quoted filenames.

The filename completion test has been extended to cover more cases.
As part of the extended testing I need to know the character that
should be used to separate filenames within a path.  For this TCL 8.6+
has $::tcl_platform(pathSeparator).  To support older versions of TCL
I've added some code to testsuite/lib/gdb.exp.

You might notice that after this commit the completion for unquoted
files is all done in the brkchars phase, that is the function
filename_completer_handle_brkchars calculates the completions and
marks the completion_tracker as using a custom word point.  The reason
for this is that we don't want to break on white space for this
completion, but if we rely on readline to find the completion word,
readline will consider the entire command line, and with no white
space in the word break character set, readline will end up using the
entire command line as the word to complete.

For now at least, the completer for quoted filenames does generate its
completions during the completion phase, though this is going to
change in a later commit.
2024-09-07 20:28:57 +01:00
Tom de Vries
fbf8e4c35c [gdb/python] Use GDB_PY_SET_HANDLE_EXCEPTION more often
I found a few more places where we can use GDB_PY_SET_HANDLE_EXCEPTION.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-08-27 09:20:18 +02:00
Tom de Vries
2f8cd40c37 [gdb/python] Use GDB_PY_HANDLE_EXCEPTION more often
I found a few more places where we can use GDB_PY_HANDLE_EXCEPTION.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-08-27 09:20:18 +02:00
Tom de Vries
50f8a39878 [gdb] Add const to catch gdb_exception
I did a review of lines containing "catch (gdb_exception" and found a few
where we can add const.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-08-22 09:49:53 +02:00
Tom de Vries
365b32b9c7 [gdb/python] Eliminate catch(...) in type_to_type_object
In type_to_type_object we have:
...
  try
    {
      if (type->is_stub ())
	type = check_typedef (type);
    }
  catch (...)
    {
      /* Just ignore failures in check_typedef.  */
    }
...

The catch is supposed to ignore gdb_exception_error, but it ignores any
exception.

Fix that by only ignoring gdb_exception_error, and handling
gdb_exception_quit / gdb_exception_forced_quit using GDB_PY_HANDLE_EXCEPTION.

Tested on x86_64-linux.

Approved-By: Tom Tromey <tom@tromey.com>
2024-08-22 09:49:53 +02:00
Tom Tromey
807f697b17 Fix DAP failure when fetching global variables
The relatively new "globals" scope code in DAP has a fairly obvious
bug -- the fetch_one_child method should return a tuple with two
elements, but instead just returns the variable's value.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32029
Reviewed-By: Tom de Vries <tdevries@suse.de>
2024-08-16 08:47:00 -06:00
Tom Tromey
7e2d5218ff Log gdb version and configuration in DAP
I think it would be useful for gdb's DAP logs to come with the version
and configuration information.  This might make debugging some bug
reports a little simpler.
2024-08-14 10:11:29 -06:00
Tom Tromey
f238737757 Fix failure with C++ exceptions in DAP
While working on earlier patches, I noticed that the DAP C++ exception
test had some strange results in the log.  Digging into this, I found
that while the Ada catchpoints emit a "bkptno" field in the MI result,
the C++ ones do not -- but the DAP code was relying on this.

This patch fixes the problem by changing which field is examined, and
then updates the tests to verify this.

Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-08-14 10:08:58 -06:00
Tom Tromey
0c3bfda0ac Make DAP instruction breakpoints unverified
Currently, when a DAP client uses setInstructionBreakpoints, the
resulting breakpoints are created as "verified", even though there is
no symbol file and thus the breakpoint can't possibly have a source
location.

This patch changes the DAP code to assume that all breakpoints are
unverified before launch.

Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-08-14 10:08:58 -06:00
Tom Tromey
0341f2767a Introduce exec_mi_and_log for DAP
This adds a new exec_mi_and_log function that wraps gdb.execute_mi and
logs the command.  This can be handy when debugging DAP.

Reviewed-by: Keith Seitz <keiths@redhat.com>
2024-08-14 10:08:58 -06:00
Felix Willgerodt
6be9971c93 btrace, python: Enable ptwrite filter registration.
By default GDB will be printing the hex payload of the ptwrite package as
auxiliary information.  To customize this, the user can register a ptwrite
filter function in python, that takes the payload and the PC as arguments and
returns a string which will be printed instead.  Registering the filter
function is done using a factory pattern to make per-thread filtering easier.

Approved-By: Markus Metzger <markus.t.metzger@intel.com>
2024-08-14 11:20:57 +02:00
Felix Willgerodt
8958aefd34 python: Add clear() to gdb.Record.
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>
2024-08-14 11:20:56 +02:00
Felix Willgerodt
bea4f6fac4 python: Introduce gdb.RecordAuxiliary class.
Auxiliary instructions are no real instructions and get their own object
class, similar to gaps. gdb.Record.instruction_history is now possibly a
list of gdb.RecordInstruction, gdb.RecordGap or gdb.RecordAuxiliary
objects.

This patch is in preparation for the new ptwrite feature, which is based on
auxiliary instructions.

Approved-By: Markus Metzger <markus.t.metzger@intel.com>
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-08-14 11:20:56 +02:00
Simon Marchi
03b40f6f55 gdb: drop struct keyword when using bound_minimal_symbol
This is a simple find / replace from "struct bound_minimal_symbol" to
"bound_minimal_symbol", to make things shorter and more consisten
througout.  In some cases, move variable declarations where first used.

Change-Id: Ica4af11c4ac528aa842bfa49a7afe8fe77a66849
Reviewed-by: Keith Seitz <keiths@redhat.com>
Approved-By: Andrew Burgess <aburgess@redhat.com>
2024-08-12 10:31:09 -04:00
Tom de Vries
647adc6812 [gdb/python] Fix handling of ^C during disassembly
Inspired by the trigger patch I used here [1], I tried this in
gdbpy_print_insn:
...
   /* Call into the registered disassembler to (possibly) perform the
      disassembly.  */
+  set_quit_flag ();
   PyObject *insn_disas_obj = (PyObject *) disasm_info;
   gdbpy_ref<> result (PyObject_CallFunctionObjArgs (hook.get (),
                                                    insn_disas_obj,
...
and with test-case gdb.python/py-disasm-exec.exp ran into:
...
(gdb) disassemble test^M
Dump of assembler code for function test:^M
   0x00000000004101ac <+0>:     Python Exception <class 'KeyboardInterrupt'>: ^M
^M
unknown disassembler error (error = -1)^M
(gdb)
...

This is incorrect, the KeyboardInterrupt should propagate and interrupt the
command.

Fix this by using gdbpy_print_stack_or_quit instead of gdbpy_print_stack in
gdbpy_print_insn, giving us instead:
...
(gdb) disassemble test^M
Dump of assembler code for function test:^M
   0x00000000004101ac <+0>:     ^M
Quit^M
(gdb)
...

Tested on aarch64-linux.

Approved-By: Andrew Burgess <aburgess@redhat.com>

[1] https://sourceware.org/pipermail/gdb-patches/2024-July/210798.html
2024-08-08 23:52:00 +02:00
Tom de Vries
de272a5e90 [gdb/exp] Allow internal function to indicate return type
Currently an internal function handler has this prototype:
...
struct value *handler (struct gdbarch *gdbarch,
                       const struct language_defn *language,
                       void *cookie, int argc, struct value **argv);
...

Also allow an internal function with a handler with an additional
"enum noside noside" parameter:
...
struct value *handler (struct gdbarch *gdbarch,
                       const struct language_defn *language, void *cookie,
                       int argc, struct value **argv, enum noside noside);
...

In case such a handler is called with noside == EVAL_AVOID_SIDE_EFFECTS, it's
expected to return some value with the correct return type.

At least, provided it can do so without side effects, otherwise it should
throw an error.

No functional changes.

Tested on x86_64-linux and aarch64-linux.

Reviewed-By: Keith Seitz <keiths@redhat.com>
2024-07-24 16:32:35 +02:00
Tom Tromey
c51fb38679 Add returnValue scope to DAP
The DAP spec recently changed to add a new scope for the return value
from a "stepOut" request.  This new scope uses the "returnValue"
presentation hint.  See:

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

This patch implements this for gdb.

Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31945
Reviewed-By: Eli Zaretskii <eliz@gnu.org>
2024-07-23 11:31:49 -06:00