aboutsummaryrefslogtreecommitdiff
path: root/gdb/python
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/python')
-rw-r--r--gdb/python/lib/gdb/dap/breakpoint.py13
-rw-r--r--gdb/python/lib/gdb/dap/events.py4
-rw-r--r--gdb/python/lib/gdb/dap/next.py12
-rw-r--r--gdb/python/lib/gdb/dap/server.py27
-rw-r--r--gdb/python/lib/gdb/dap/startup.py10
-rw-r--r--gdb/python/lib/gdb/dap/varref.py10
-rw-r--r--gdb/python/lib/gdb/printing.py19
-rw-r--r--gdb/python/py-block.c3
-rw-r--r--gdb/python/py-disasm.c85
-rw-r--r--gdb/python/py-event-types.def2
-rw-r--r--gdb/python/py-finishbreakpoint.c6
-rw-r--r--gdb/python/py-framefilter.c2
-rw-r--r--gdb/python/py-infevents.c2
-rw-r--r--gdb/python/py-infthread.c33
-rw-r--r--gdb/python/py-mi.c6
-rw-r--r--gdb/python/py-micmd.c4
-rw-r--r--gdb/python/py-objfile.c12
-rw-r--r--gdb/python/py-record.c3
-rw-r--r--gdb/python/py-symbol.c44
-rw-r--r--gdb/python/py-type.c15
-rw-r--r--gdb/python/py-unwind.c2
-rw-r--r--gdb/python/py-value.c82
-rw-r--r--gdb/python/python-internal.h7
-rw-r--r--gdb/python/python.c32
24 files changed, 259 insertions, 176 deletions
diff --git a/gdb/python/lib/gdb/dap/breakpoint.py b/gdb/python/lib/gdb/dap/breakpoint.py
index 4d4ca18..3162911 100644
--- a/gdb/python/lib/gdb/dap/breakpoint.py
+++ b/gdb/python/lib/gdb/dap/breakpoint.py
@@ -373,10 +373,12 @@ def set_insn_breakpoints(
@in_gdb_thread
def _catch_exception(filterId, **args):
if filterId in ("assert", "exception", "throw", "rethrow", "catch"):
- cmd = "-catch-" + filterId
+ cmd = ["-catch-" + filterId]
else:
raise DAPException("Invalid exception filterID: " + str(filterId))
- result = exec_mi_and_log(cmd)
+ if "exception" in args and args["exception"] is not None:
+ cmd += ["-e", args["exception"]]
+ result = exec_mi_and_log(*cmd)
# While the Ada catchpoints emit a "bkptno" field here, the C++
# ones do not. So, instead we look at the "number" field.
num = result["bkpt"]["number"]
@@ -404,6 +406,13 @@ def _rewrite_exception_breakpoint(
# Note that exception breakpoints do not support a hit count.
**args,
):
+ if filterId == "exception":
+ # Treat Ada exceptions specially -- in particular the
+ # condition is just an exception name, not an expression.
+ return {
+ "filterId": filterId,
+ "exception": condition,
+ }
return {
"filterId": filterId,
"condition": condition,
diff --git a/gdb/python/lib/gdb/dap/events.py b/gdb/python/lib/gdb/dap/events.py
index e8f2655..778acc5 100644
--- a/gdb/python/lib/gdb/dap/events.py
+++ b/gdb/python/lib/gdb/dap/events.py
@@ -161,7 +161,7 @@ _expected_pause = False
@in_gdb_thread
-def exec_and_expect_stop(cmd, expected_pause=False, propagate_exception=False):
+def exec_and_expect_stop(cmd, expected_pause=False):
"""A wrapper for exec_and_log that sets the continue-suppression flag.
When EXPECTED_PAUSE is True, a stop that looks like a pause (e.g.,
@@ -174,7 +174,7 @@ def exec_and_expect_stop(cmd, expected_pause=False, propagate_exception=False):
# continuing.
_suppress_cont = not expected_pause
# FIXME if the call fails should we clear _suppress_cont?
- exec_and_log(cmd, propagate_exception)
+ exec_and_log(cmd)
# Map from gdb stop reasons to DAP stop reasons. Some of these can't
diff --git a/gdb/python/lib/gdb/dap/next.py b/gdb/python/lib/gdb/dap/next.py
index 898fff1..993e9d2 100644
--- a/gdb/python/lib/gdb/dap/next.py
+++ b/gdb/python/lib/gdb/dap/next.py
@@ -17,7 +17,7 @@ import gdb
from .events import exec_and_expect_stop
from .server import capability, request
-from .startup import in_gdb_thread
+from .startup import DAPException, exec_and_log, in_gdb_thread
from .state import set_thread
@@ -36,11 +36,9 @@ def _handle_thread_step(thread_id, single_thread, select=False):
result = False
arg = "off"
try:
- # This can fail, depending on the target, so catch the error
- # and report to our caller. We can't use exec_and_log because
- # that does not propagate exceptions.
- gdb.execute("set scheduler-locking " + arg, from_tty=True, to_string=True)
- except gdb.error:
+ # This can fail, depending on the target, so catch any error.
+ exec_and_log("set scheduler-locking " + arg)
+ except DAPException:
result = False
# Other DAP code may select a frame, and the "finish" command uses
# the selected frame.
@@ -76,7 +74,7 @@ def step_in(
@request("stepOut")
def step_out(*, threadId: int, singleThread: bool = False, **args):
_handle_thread_step(threadId, singleThread, True)
- exec_and_expect_stop("finish &", propagate_exception=True)
+ exec_and_expect_stop("finish &")
@request("continue")
diff --git a/gdb/python/lib/gdb/dap/server.py b/gdb/python/lib/gdb/dap/server.py
index 7dab582..98a8084 100644
--- a/gdb/python/lib/gdb/dap/server.py
+++ b/gdb/python/lib/gdb/dap/server.py
@@ -398,7 +398,7 @@ class Server:
# responses are flushed to the client before exiting.
self._write_queue.put(None)
json_writer.join()
- send_gdb("quit")
+ send_gdb(lambda: exec_and_log("quit"))
@in_dap_thread
def set_defer_events(self):
@@ -614,7 +614,7 @@ def terminate(**args):
@capability("supportTerminateDebuggee")
def disconnect(*, terminateDebuggee: bool = False, **args):
if terminateDebuggee:
- send_gdb_with_response("kill")
+ send_gdb_with_response(lambda: exec_and_log("kill"))
_server.shutdown()
@@ -633,18 +633,6 @@ def cancel(**args):
return None
-class Invoker(object):
- """A simple class that can invoke a gdb command."""
-
- def __init__(self, cmd):
- self._cmd = cmd
-
- # This is invoked in the gdb thread to run the command.
- @in_gdb_thread
- def __call__(self):
- exec_and_log(self._cmd)
-
-
class Cancellable(object):
def __init__(self, fn, result_q=None):
@@ -677,25 +665,16 @@ class Cancellable(object):
def send_gdb(cmd):
"""Send CMD to the gdb thread.
- CMD can be either a function or a string.
- If it is a string, it is passed to gdb.execute."""
- if isinstance(cmd, str):
- cmd = Invoker(cmd)
-
+ CMD is a function."""
# Post the event and don't wait for the result.
gdb.post_event(Cancellable(cmd))
def send_gdb_with_response(fn):
"""Send FN to the gdb thread and return its result.
- If FN is a string, it is passed to gdb.execute and None is
- returned as the result.
If FN throws an exception, this function will throw the
same exception in the calling thread.
"""
- if isinstance(fn, str):
- fn = Invoker(fn)
-
# Post the event and wait for the result in result_q.
result_q = DAPQueue()
gdb.post_event(Cancellable(fn, result_q))
diff --git a/gdb/python/lib/gdb/dap/startup.py b/gdb/python/lib/gdb/dap/startup.py
index ab3e8fd..0c95ada 100644
--- a/gdb/python/lib/gdb/dap/startup.py
+++ b/gdb/python/lib/gdb/dap/startup.py
@@ -204,7 +204,7 @@ def log_stack(level=LogLevel.DEFAULT):
@in_gdb_thread
-def exec_and_log(cmd, propagate_exception=False):
+def exec_and_log(cmd):
"""Execute the gdb command CMD.
If logging is enabled, log the command and its output."""
log("+++ " + cmd)
@@ -213,10 +213,10 @@ def exec_and_log(cmd, propagate_exception=False):
if output != "":
log(">>> " + output)
except gdb.error as e:
- if propagate_exception:
- raise DAPException(str(e)) from e
- else:
- log_stack()
+ # Don't normally want to see this, as it interferes with the
+ # test suite.
+ log_stack(LogLevel.FULL)
+ raise DAPException(str(e)) from e
@in_gdb_thread
diff --git a/gdb/python/lib/gdb/dap/varref.py b/gdb/python/lib/gdb/dap/varref.py
index 8a13c51..d18197b 100644
--- a/gdb/python/lib/gdb/dap/varref.py
+++ b/gdb/python/lib/gdb/dap/varref.py
@@ -146,6 +146,10 @@ class BaseReference(ABC):
if self._children is None:
self._children = [None] * self.child_count()
for idx in range(start, start + count):
+ if idx >= len(self._children):
+ raise DAPException(
+ f"requested child {idx} outside range of variable {self._ref}"
+ )
if self._children[idx] is None:
(name, value) = self.fetch_one_child(idx)
name = self._compute_name(name)
@@ -242,7 +246,11 @@ class VariableReference(BaseReference):
# changed DAP to allow memory references for any of the
# variable response requests, and to lift the restriction
# to pointer-to-function from Variable.
- if self._value.type.strip_typedefs().code == gdb.TYPE_CODE_PTR:
+ if (
+ self._value.type.strip_typedefs().code == gdb.TYPE_CODE_PTR
+ and not self._value.is_optimized_out
+ and not self._value.is_unavailable
+ ):
result["memoryReference"] = hex(int(self._value))
if client_bool_capability("supportsVariableType"):
result["type"] = str(self._value.type)
diff --git a/gdb/python/lib/gdb/printing.py b/gdb/python/lib/gdb/printing.py
index cba27d2..f1ac19d 100644
--- a/gdb/python/lib/gdb/printing.py
+++ b/gdb/python/lib/gdb/printing.py
@@ -415,10 +415,21 @@ def make_visualizer(value):
result = NoOpArrayPrinter(ty, value)
elif ty.code in (gdb.TYPE_CODE_STRUCT, gdb.TYPE_CODE_UNION):
result = NoOpStructPrinter(ty, value)
- elif ty.code in (
- gdb.TYPE_CODE_PTR,
- gdb.TYPE_CODE_REF,
- gdb.TYPE_CODE_RVALUE_REF,
+ elif (
+ ty.code
+ in (
+ gdb.TYPE_CODE_PTR,
+ gdb.TYPE_CODE_REF,
+ gdb.TYPE_CODE_RVALUE_REF,
+ )
+ # Avoid "void *" here because those pointers can't be
+ # dereferenced without a cast.
+ and ty.target().code != gdb.TYPE_CODE_VOID
+ # An optimized-out or unavailable pointer should just be
+ # treated as a scalar, since there's no way to dereference
+ # it.
+ and not value.is_optimized_out
+ and not value.is_unavailable
):
result = NoOpPointerReferencePrinter(value)
else:
diff --git a/gdb/python/py-block.c b/gdb/python/py-block.c
index fa7dd19..66ccad7 100644
--- a/gdb/python/py-block.c
+++ b/gdb/python/py-block.c
@@ -356,6 +356,9 @@ block_to_block_object (const struct block *block, struct objfile *objfile)
}
result = PyObject_New (block_object, &block_object_type);
+ if (result == nullptr)
+ return nullptr;
+
result->block = block;
result->objfile = objfile;
diff --git a/gdb/python/py-disasm.c b/gdb/python/py-disasm.c
index 17064dc..47ae99c 100644
--- a/gdb/python/py-disasm.c
+++ b/gdb/python/py-disasm.c
@@ -254,15 +254,15 @@ disasm_info_object_is_valid (disasm_info_object *obj)
/* Fill in OBJ with all the other arguments. */
static void
-disasm_info_fill (disasm_info_object *obj, struct gdbarch *gdbarch,
+disasm_info_fill (disasm_info_object &obj, struct gdbarch *gdbarch,
program_space *progspace, bfd_vma address,
disassemble_info *di, disasm_info_object *next)
{
- obj->gdbarch = gdbarch;
- obj->program_space = progspace;
- obj->address = address;
- obj->gdb_info = di;
- obj->next = next;
+ obj.gdbarch = gdbarch;
+ obj.program_space = progspace;
+ obj.address = address;
+ obj.gdb_info = di;
+ obj.next = next;
}
/* Implement DisassembleInfo.__init__. Takes a single argument that must
@@ -281,7 +281,7 @@ disasm_info_init (PyObject *self, PyObject *args, PyObject *kwargs)
disasm_info_object *other = (disasm_info_object *) info_obj;
disasm_info_object *info = (disasm_info_object *) self;
- disasm_info_fill (info, other->gdbarch, other->program_space,
+ disasm_info_fill (*info, other->gdbarch, other->program_space,
other->address, other->gdb_info, other->next);
other->next = info;
@@ -1156,19 +1156,18 @@ gdbpy_disassembler::gdbpy_disassembler (disasm_info_object *obj)
happens when gdbpy_print_insn returns. This class is responsible for
marking the DisassembleInfo as invalid in its destructor. */
-struct scoped_disasm_info_object
+struct scoped_invalidate_disasm_info
{
- /* Constructor. */
- scoped_disasm_info_object (struct gdbarch *gdbarch, CORE_ADDR memaddr,
- disassemble_info *info)
- : m_disasm_info (allocate_disasm_info_object ())
+ /* Constructor. Just cache DISASM_INFO for use in the destructor. */
+ scoped_invalidate_disasm_info
+ (gdbpy_ref<disasm_info_object> disasm_info)
+ : m_disasm_info (std::move (disasm_info))
{
- disasm_info_fill (m_disasm_info.get (), gdbarch, current_program_space,
- memaddr, info, nullptr);
+ /* Nothing. */
}
/* Upon destruction mark m_disasm_info as invalid. */
- ~scoped_disasm_info_object ()
+ ~scoped_invalidate_disasm_info ()
{
/* Invalidate the original DisassembleInfo object as well as any copies
that the user might have made. */
@@ -1178,30 +1177,15 @@ struct scoped_disasm_info_object
obj->gdb_info = nullptr;
}
- /* Return a pointer to the underlying disasm_info_object instance. */
- disasm_info_object *
- get () const
- {
- return m_disasm_info.get ();
- }
-
private:
- /* Wrapper around the call to PyObject_New, this wrapper function can be
- called from the constructor initialization list, while PyObject_New, a
- macro, can't. */
- static disasm_info_object *
- allocate_disasm_info_object ()
- {
- return (disasm_info_object *) PyObject_New (disasm_info_object,
- &disasm_info_object_type);
- }
-
/* A reference to a gdb.disassembler.DisassembleInfo object. When this
- containing instance goes out of scope this reference is released,
- however, the user might be holding other references to the
- DisassembleInfo object in Python code, so the underlying object might
- not be deleted. */
+ object goes out of scope this reference is released, however, the user
+ might be holding other references to the DisassembleInfo (either
+ directly, or via copies of this object), in which case the underlying
+ object will not be deleted. The destructor of this class ensures
+ that this DisassembleInfo object, and any copies, are all marked
+ invalid. */
gdbpy_ref<disasm_info_object> m_disasm_info;
};
@@ -1242,17 +1226,30 @@ gdbpy_print_insn (struct gdbarch *gdbarch, CORE_ADDR memaddr,
return {};
}
- /* Create the new DisassembleInfo object we will pass into Python. This
- object will be marked as invalid when we leave this scope. */
- scoped_disasm_info_object scoped_disasm_info (gdbarch, memaddr, info);
- disasm_info_object *disasm_info = scoped_disasm_info.get ();
+ /* Create the new DisassembleInfo object we will pass into Python. */
+ gdbpy_ref<disasm_info_object> disasm_info
+ ((disasm_info_object *) PyObject_New (disasm_info_object,
+ &disasm_info_object_type));
+ if (disasm_info == nullptr)
+ {
+ gdbpy_print_stack ();
+ return {};
+ }
+
+ /* Initialise the DisassembleInfo object. */
+ disasm_info_fill (*disasm_info.get (), gdbarch, current_program_space,
+ memaddr, info, nullptr);
+
+ /* Ensure the DisassembleInfo, along with any copies the user makes, are
+ marked as invalid when we leave this scope. */
+ scoped_invalidate_disasm_info invalidate_disasm (disasm_info);
/* Call into the registered disassembler to (possibly) perform the
disassembly. */
- PyObject *insn_disas_obj = (PyObject *) disasm_info;
- gdbpy_ref<> result (PyObject_CallFunctionObjArgs (hook.get (),
- insn_disas_obj,
- nullptr));
+ gdbpy_ref<> result
+ (PyObject_CallFunctionObjArgs (hook.get (),
+ (PyObject *) disasm_info.get (),
+ nullptr));
if (result == nullptr)
{
diff --git a/gdb/python/py-event-types.def b/gdb/python/py-event-types.def
index 15cd9fa..83167f3 100644
--- a/gdb/python/py-event-types.def
+++ b/gdb/python/py-event-types.def
@@ -54,7 +54,7 @@ GDB_PY_DEFINE_EVENT_TYPE (new_thread,
GDB_PY_DEFINE_EVENT_TYPE (thread_exited,
"ThreadExitedEvent",
"GDB thread exited event object",
- event_object_type);
+ thread_event_object_type);
GDB_PY_DEFINE_EVENT_TYPE (new_inferior,
"NewInferiorEvent",
diff --git a/gdb/python/py-finishbreakpoint.c b/gdb/python/py-finishbreakpoint.c
index 0ea629f..70e1684 100644
--- a/gdb/python/py-finishbreakpoint.c
+++ b/gdb/python/py-finishbreakpoint.c
@@ -175,7 +175,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
struct frame_id frame_id;
PyObject *internal = NULL;
int internal_bp = 0;
- CORE_ADDR pc;
+ std::optional<CORE_ADDR> pc;
if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
&frame_obj, &internal))
@@ -249,9 +249,9 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
try
{
- if (get_frame_pc_if_available (frame, &pc))
+ if ((pc = get_frame_pc_if_available (frame)))
{
- struct symbol *function = find_pc_function (pc);
+ struct symbol *function = find_pc_function (*pc);
if (function != nullptr)
{
struct type *ret_type =
diff --git a/gdb/python/py-framefilter.c b/gdb/python/py-framefilter.c
index adf4233..db8c274 100644
--- a/gdb/python/py-framefilter.c
+++ b/gdb/python/py-framefilter.c
@@ -168,7 +168,7 @@ mi_should_print (struct symbol *sym, enum mi_print_types type)
{
int print_me = 0;
- switch (sym->aclass ())
+ switch (sym->loc_class ())
{
default:
case LOC_UNDEF: /* catches errors */
diff --git a/gdb/python/py-infevents.c b/gdb/python/py-infevents.c
index e63ba52..f74fb01 100644
--- a/gdb/python/py-infevents.c
+++ b/gdb/python/py-infevents.c
@@ -40,7 +40,7 @@ create_inferior_call_event_object (inferior_call_kind flag, ptid_t ptid,
gdb_assert_not_reached ("invalid inferior_call_kind");
}
- gdbpy_ref<> ptid_obj (gdbpy_create_ptid_object (ptid));
+ gdbpy_ref<> ptid_obj = gdbpy_create_ptid_object (ptid);
if (ptid_obj == NULL)
return NULL;
diff --git a/gdb/python/py-infthread.c b/gdb/python/py-infthread.c
index 4f1f8d4..08533fe 100644
--- a/gdb/python/py-infthread.c
+++ b/gdb/python/py-infthread.c
@@ -190,7 +190,7 @@ thpy_get_ptid (PyObject *self, void *closure)
THPY_REQUIRE_VALID (thread_obj);
- return gdbpy_create_ptid_object (thread_obj->thread->ptid);
+ return gdbpy_create_ptid_object (thread_obj->thread->ptid).release ();
}
/* Implement gdb.InferiorThread.ptid_string attribute. */
@@ -361,23 +361,14 @@ thpy_repr (PyObject *self)
target_pid_to_str (thr->ptid).c_str ());
}
-/* Return a reference to a new Python object representing a ptid_t.
- The object is a tuple containing (pid, lwp, tid). */
-PyObject *
+/* See python-internal.h. */
+
+gdbpy_ref<>
gdbpy_create_ptid_object (ptid_t ptid)
{
- int pid;
- long lwp;
- ULONGEST tid;
- PyObject *ret;
-
- ret = PyTuple_New (3);
- if (!ret)
- return NULL;
-
- pid = ptid.pid ();
- lwp = ptid.lwp ();
- tid = ptid.tid ();
+ int pid = ptid.pid ();
+ long lwp = ptid.lwp ();
+ ULONGEST tid = ptid.tid ();
gdbpy_ref<> pid_obj = gdb_py_object_from_longest (pid);
if (pid_obj == nullptr)
@@ -389,10 +380,14 @@ gdbpy_create_ptid_object (ptid_t ptid)
if (tid_obj == nullptr)
return nullptr;
+ gdbpy_ref<> ret (PyTuple_New (3));
+ if (ret == nullptr)
+ return nullptr;
+
/* Note that these steal references, hence the use of 'release'. */
- PyTuple_SET_ITEM (ret, 0, pid_obj.release ());
- PyTuple_SET_ITEM (ret, 1, lwp_obj.release ());
- PyTuple_SET_ITEM (ret, 2, tid_obj.release ());
+ PyTuple_SET_ITEM (ret.get (), 0, pid_obj.release ());
+ PyTuple_SET_ITEM (ret.get (), 1, lwp_obj.release ());
+ PyTuple_SET_ITEM (ret.get (), 2, tid_obj.release ());
return ret;
}
diff --git a/gdb/python/py-mi.c b/gdb/python/py-mi.c
index 9b871d4..b2ab4e2 100644
--- a/gdb/python/py-mi.c
+++ b/gdb/python/py-mi.c
@@ -218,11 +218,11 @@ py_object_to_mi_key (PyObject *key_obj)
{
gdb_assert (name != nullptr);
- if (*name == '\0' || !isalpha (*name))
+ if (*name == '\0' || !c_isalpha (*name))
return false;
for (; *name != '\0'; ++name)
- if (!isalnum (*name) && *name != '_' && *name != '-')
+ if (!c_isalnum (*name) && *name != '_' && *name != '-')
return false;
return true;
@@ -363,7 +363,7 @@ gdbpy_notify_mi (PyObject *self, PyObject *args, PyObject *kwargs)
}
for (int i = 0; i < name_len; i++)
{
- if (!isalnum (name[i]) && name[i] != '-')
+ if (!c_isalnum (name[i]) && name[i] != '-')
{
PyErr_Format
(PyExc_ValueError,
diff --git a/gdb/python/py-micmd.c b/gdb/python/py-micmd.c
index 72f427f..07db0cc 100644
--- a/gdb/python/py-micmd.c
+++ b/gdb/python/py-micmd.c
@@ -350,7 +350,7 @@ micmdpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
PyErr_SetString (PyExc_ValueError, _("MI command name is empty."));
return -1;
}
- else if ((name_len < 2) || (name[0] != '-') || !isalnum (name[1]))
+ else if ((name_len < 2) || (name[0] != '-') || !c_isalnum (name[1]))
{
PyErr_SetString (PyExc_ValueError,
_("MI command name does not start with '-'"
@@ -361,7 +361,7 @@ micmdpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
{
for (int i = 2; i < name_len; i++)
{
- if (!isalnum (name[i]) && name[i] != '-')
+ if (!c_isalnum (name[i]) && name[i] != '-')
{
PyErr_Format
(PyExc_ValueError,
diff --git a/gdb/python/py-objfile.c b/gdb/python/py-objfile.c
index 1c6f569..a9f5754 100644
--- a/gdb/python/py-objfile.c
+++ b/gdb/python/py-objfile.c
@@ -556,7 +556,7 @@ objfpy_build_id_ok (const char *string)
return 0;
for (i = 0; i < n; ++i)
{
- if (!isxdigit (string[i]))
+ if (!c_isxdigit (string[i]))
return 0;
}
return 1;
@@ -619,9 +619,8 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
struct objfile *objfile = nullptr;
if (by_build_id)
- gdbarch_iterate_over_objfiles_in_search_order
- (current_inferior ()->arch (),
- [&objfile, name] (struct objfile *obj)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([&objfile, name] (struct objfile *obj)
{
/* Don't return separate debug files. */
if (obj->separate_debug_objfile_backlink != nullptr)
@@ -642,9 +641,8 @@ gdbpy_lookup_objfile (PyObject *self, PyObject *args, PyObject *kw)
return 1;
}, gdbpy_current_objfile);
else
- gdbarch_iterate_over_objfiles_in_search_order
- (current_inferior ()->arch (),
- [&objfile, name] (struct objfile *obj)
+ current_program_space->iterate_over_objfiles_in_search_order
+ ([&objfile, name] (struct objfile *obj)
{
/* Don't return separate debug files. */
if (obj->separate_debug_objfile_backlink != nullptr)
diff --git a/gdb/python/py-record.c b/gdb/python/py-record.c
index 7e7904b..89c2e77 100644
--- a/gdb/python/py-record.c
+++ b/gdb/python/py-record.c
@@ -696,6 +696,9 @@ gdbpy_current_recording (PyObject *self, PyObject *args)
Py_RETURN_NONE;
ret = PyObject_New (recpy_record_object, &recpy_record_type);
+ if (ret == nullptr)
+ return nullptr;
+
ret->thread = inferior_thread ();
ret->method = target_record_method (ret->thread->ptid);
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index 3028a30..284e385 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -126,7 +126,7 @@ sympy_get_addr_class (PyObject *self, void *closure)
SYMPY_REQUIRE_VALID (self, symbol);
- return gdb_py_object_from_longest (symbol->aclass ()).release ();
+ return gdb_py_object_from_longest (symbol->loc_class ()).release ();
}
/* Implement gdb.Symbol.domain attribute. Return the domain as an
@@ -156,42 +156,39 @@ static PyObject *
sympy_is_constant (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
- enum address_class theclass;
SYMPY_REQUIRE_VALID (self, symbol);
- theclass = symbol->aclass ();
+ location_class loc_class = symbol->loc_class ();
- return PyBool_FromLong (theclass == LOC_CONST || theclass == LOC_CONST_BYTES);
+ return PyBool_FromLong (loc_class == LOC_CONST || loc_class == LOC_CONST_BYTES);
}
static PyObject *
sympy_is_function (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
- enum address_class theclass;
SYMPY_REQUIRE_VALID (self, symbol);
- theclass = symbol->aclass ();
+ location_class loc_class = symbol->loc_class ();
- return PyBool_FromLong (theclass == LOC_BLOCK);
+ return PyBool_FromLong (loc_class == LOC_BLOCK);
}
static PyObject *
sympy_is_variable (PyObject *self, void *closure)
{
struct symbol *symbol = NULL;
- enum address_class theclass;
SYMPY_REQUIRE_VALID (self, symbol);
- theclass = symbol->aclass ();
+ location_class loc_class = symbol->loc_class ();
return PyBool_FromLong (!symbol->is_argument ()
- && (theclass == LOC_LOCAL || theclass == LOC_REGISTER
- || theclass == LOC_STATIC || theclass == LOC_COMPUTED
- || theclass == LOC_OPTIMIZED_OUT));
+ && (loc_class == LOC_LOCAL || loc_class == LOC_REGISTER
+ || loc_class == LOC_STATIC || loc_class == LOC_COMPUTED
+ || loc_class == LOC_OPTIMIZED_OUT));
}
/* Implementation of Symbol.is_artificial. */
@@ -279,7 +276,7 @@ sympy_value (PyObject *self, PyObject *args)
}
SYMPY_REQUIRE_VALID (self, symbol);
- if (symbol->aclass () == LOC_TYPEDEF)
+ if (symbol->loc_class () == LOC_TYPEDEF)
{
PyErr_SetString (PyExc_TypeError, "cannot get the value of a typedef");
return NULL;
@@ -605,17 +602,15 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
/* Expand any symtabs that contain potentially matching symbols. */
lookup_name_info lookup_name (name, symbol_name_match_type::FULL);
- expand_symtabs_matching (NULL, lookup_name, NULL, NULL,
- SEARCH_STATIC_BLOCK, flags);
for (objfile *objfile : current_program_space->objfiles ())
{
- for (compunit_symtab *cust : objfile->compunits ())
+ auto callback = [&] (compunit_symtab *cust)
{
/* Skip included compunits to prevent including compunits from
being searched twice. */
if (cust->user != nullptr)
- continue;
+ return true;
const struct blockvector *bv = cust->blockvector ();
const struct block *block = bv->static_block ();
@@ -628,13 +623,18 @@ gdbpy_lookup_static_symbols (PyObject *self, PyObject *args, PyObject *kw)
if (symbol != nullptr)
{
PyObject *sym_obj = symbol_to_symbol_object (symbol);
- if (sym_obj == nullptr)
- return nullptr;
- if (PyList_Append (return_list.get (), sym_obj) == -1)
- return nullptr;
+ if (sym_obj == nullptr
+ || PyList_Append (return_list.get (), sym_obj) == -1)
+ return false;
}
}
- }
+
+ return true;
+ };
+
+ if (!objfile->search (nullptr, &lookup_name, nullptr, callback,
+ SEARCH_STATIC_BLOCK, flags))
+ return nullptr;
}
}
catch (const gdb_exception &except)
diff --git a/gdb/python/py-type.c b/gdb/python/py-type.c
index c546aa7..a2c5939 100644
--- a/gdb/python/py-type.c
+++ b/gdb/python/py-type.c
@@ -1045,9 +1045,9 @@ typy_template_argument (PyObject *self, PyObject *args)
}
sym = TYPE_TEMPLATE_ARGUMENT (type, argno);
- if (sym->aclass () == LOC_TYPEDEF)
+ if (sym->loc_class () == LOC_TYPEDEF)
return type_to_type_object (sym->type ());
- else if (sym->aclass () == LOC_OPTIMIZED_OUT)
+ else if (sym->loc_class () == LOC_OPTIMIZED_OUT)
{
PyErr_Format (PyExc_RuntimeError,
_("Template argument is optimized out"));
@@ -1312,10 +1312,9 @@ static PyObject *
typy_has_key (PyObject *self, PyObject *args)
{
struct type *type = ((type_object *) self)->type;
- const char *field;
- int i;
+ const char *field_name;
- if (!PyArg_ParseTuple (args, "s", &field))
+ if (!PyArg_ParseTuple (args, "s", &field_name))
return NULL;
/* We want just fields of this type, not of base types, so instead of
@@ -1326,11 +1325,11 @@ typy_has_key (PyObject *self, PyObject *args)
if (type == NULL)
return NULL;
- for (i = 0; i < type->num_fields (); i++)
+ for (const auto &field : type->fields ())
{
- const char *t_field_name = type->field (i).name ();
+ const char *t_field_name = field.name ();
- if (t_field_name && (strcmp_iw (t_field_name, field) == 0))
+ if (t_field_name && (strcmp_iw (t_field_name, field_name) == 0))
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
diff --git a/gdb/python/py-unwind.c b/gdb/python/py-unwind.c
index dc078ec..43125bb 100644
--- a/gdb/python/py-unwind.c
+++ b/gdb/python/py-unwind.c
@@ -287,6 +287,8 @@ pyuw_create_unwind_info (PyObject *pyo_pending_frame,
unwind_info_object *unwind_info
= PyObject_New (unwind_info_object, &unwind_info_object_type);
+ if (unwind_info == nullptr)
+ return nullptr;
unwind_info->frame_id = frame_id;
Py_INCREF (pyo_pending_frame);
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index 8a2e263..5d8fab9 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -478,6 +478,9 @@ valpy_get_dynamic_type (PyObject *self, void *closure)
type = value_rtti_type (val, NULL, NULL, NULL);
else
type = val->type ();
+
+ if (type == nullptr)
+ type = val->type ();
}
catch (const gdb_exception &except)
{
@@ -1288,6 +1291,30 @@ valpy_get_is_optimized_out (PyObject *self, void *closure)
Py_RETURN_FALSE;
}
+/* Implements gdb.Value.is_unavailable. Return true if any part of the
+ value is unavailable. */
+
+static PyObject *
+valpy_get_is_unavailable (PyObject *self, void *closure)
+{
+ struct value *value = ((value_object *) self)->value;
+ bool entirely_available = false;
+
+ try
+ {
+ entirely_available = value->entirely_available ();
+ }
+ catch (const gdb_exception &except)
+ {
+ return gdbpy_handle_gdb_exception (nullptr, except);
+ }
+
+ if (!entirely_available)
+ Py_RETURN_TRUE;
+
+ Py_RETURN_FALSE;
+}
+
/* Implements gdb.Value.is_lazy. */
static PyObject *
valpy_get_is_lazy (PyObject *self, void *closure)
@@ -1842,7 +1869,7 @@ valpy_long (PyObject *self)
{
struct value *value = ((value_object *) self)->value;
struct type *type = value->type ();
- LONGEST l = 0;
+ PyObject *result;
try
{
@@ -1858,17 +1885,57 @@ valpy_long (PyObject *self)
&& type->code () != TYPE_CODE_PTR)
error (_("Cannot convert value to long."));
- l = value_as_long (value);
+ gdb::array_view<const gdb_byte> contents = value->contents ();
+#if PY_VERSION_HEX >= 0x030d0000
+ int flags = (type_byte_order (type) == BFD_ENDIAN_BIG
+ ? Py_ASNATIVEBYTES_BIG_ENDIAN
+ : Py_ASNATIVEBYTES_LITTLE_ENDIAN);
+ if (type->is_unsigned ())
+ flags |= Py_ASNATIVEBYTES_UNSIGNED_BUFFER;
+ result = PyLong_FromNativeBytes (contents.data (), contents.size (),
+ flags);
+#else
+ /* Here we construct a call to "int.from_bytes", passing in the
+ appropriate arguments. We need a somewhat roundabout
+ approach because int.from_bytes requires "signed" to be a
+ keyword arg. */
+
+ /* PyObject_Call requires a tuple argument. */
+ gdbpy_ref<> empty_tuple (PyTuple_New (0));
+ if (empty_tuple == nullptr)
+ return nullptr;
+
+ /* Since we need a dictionary anyway, we pass all arguments as
+ keywords, building the dictionary here. */
+ gdbpy_ref<> args
+ (Py_BuildValue ("{sy#sssO}",
+ "bytes", contents.data (),
+ (Py_ssize_t) contents.size (),
+ "byteorder",
+ (type_byte_order (type) == BFD_ENDIAN_BIG
+ ? "big" : "little"),
+ "signed",
+ type->is_unsigned ()
+ ? Py_False : Py_True));
+ if (args == nullptr)
+ return nullptr;
+
+ /* Find the "int.from_bytes" callable. */
+ gdbpy_ref<> callable (PyObject_GetAttrString ((PyObject *) &PyLong_Type,
+ "from_bytes"));
+ if (callable == nullptr)
+ return nullptr;
+
+ result = PyObject_Call (callable.get (), empty_tuple.get (),
+ args.get ());
+#endif
}
catch (const gdb_exception &except)
{
return gdbpy_handle_gdb_exception (nullptr, except);
}
- if (type->is_unsigned ())
- return gdb_py_object_from_ulongest (l).release ();
- else
- return gdb_py_object_from_longest (l).release ();
+ return result;
}
/* Implements conversion to float. */
@@ -2194,6 +2261,9 @@ static gdb_PyGetSetDef value_object_getset[] = {
"Boolean telling whether the value is optimized "
"out (i.e., not available).",
NULL },
+ { "is_unavailable", valpy_get_is_unavailable, nullptr,
+ "Boolean telling whether the value is unavailable.",
+ nullptr },
{ "type", valpy_get_type, NULL, "Type of the value.", NULL },
{ "dynamic_type", valpy_get_dynamic_type, NULL,
"Dynamic type of the value.", NULL },
diff --git a/gdb/python/python-internal.h b/gdb/python/python-internal.h
index 7f4237e..f61a175 100644
--- a/gdb/python/python-internal.h
+++ b/gdb/python/python-internal.h
@@ -503,7 +503,12 @@ PyObject *gdbpy_create_lazy_string_object (CORE_ADDR address, long length,
const char *encoding,
struct type *type);
PyObject *gdbpy_inferiors (PyObject *unused, PyObject *unused2);
-PyObject *gdbpy_create_ptid_object (ptid_t ptid);
+
+/* Return a reference to a new Python Tuple object representing a ptid_t.
+ The object is a tuple containing (pid, lwp, tid). */
+
+extern gdbpy_ref<> gdbpy_create_ptid_object (ptid_t ptid);
+
PyObject *gdbpy_selected_thread (PyObject *self, PyObject *args);
PyObject *gdbpy_selected_inferior (PyObject *self, PyObject *args);
PyObject *gdbpy_string_to_argv (PyObject *self, PyObject *args);
diff --git a/gdb/python/python.c b/gdb/python/python.c
index cb0d642..740b196 100644
--- a/gdb/python/python.c
+++ b/gdb/python/python.c
@@ -31,7 +31,6 @@
#include "python.h"
#include "extension-priv.h"
#include "cli/cli-utils.h"
-#include <ctype.h>
#include "location.h"
#include "run-on-main-thread.h"
#include "observable.h"
@@ -1202,15 +1201,22 @@ gdbpy_post_event (PyObject *self, PyObject *args)
static PyObject *
gdbpy_interrupt (PyObject *self, PyObject *args)
{
+#ifdef __MINGW32__
{
- /* Make sure the interrupt isn't delivered immediately somehow.
- This probably is not truly needed, but at the same time it
- seems more clear to be explicit about the intent. */
gdbpy_allow_threads temporarily_exit_python;
scoped_disable_cooperative_sigint_handling no_python_sigint;
set_quit_flag ();
}
+#else
+ {
+ /* For targets with support kill() just send SIGINT. This will be
+ handled as if the user hit Ctrl+C. This isn't exactly the same as
+ the above, which directly sets the quit flag. Consider, for
+ example, every place that install_sigint_handler is called. */
+ kill (getpid (), SIGINT);
+ }
+#endif
Py_RETURN_NONE;
}
@@ -1570,21 +1576,21 @@ gdbpy_write (PyObject *self, PyObject *args, PyObject *kw)
try
{
+ ui_file *stream;
switch (stream_type)
{
case 1:
- {
- gdb_printf (gdb_stderr, "%s", arg);
- break;
- }
+ stream = gdb_stderr;
+ break;
case 2:
- {
- gdb_printf (gdb_stdlog, "%s", arg);
- break;
- }
+ stream = gdb_stdlog;
+ break;
default:
- gdb_printf (gdb_stdout, "%s", arg);
+ stream = gdb_stdout;
+ break;
}
+
+ gdb_puts (arg, stream);
}
catch (const gdb_exception &except)
{