struct gdbarch *gdbarch;
};
+static_assert (gdb::is_python_allocatable_v<arch_object>);
+
static const registry<gdbarch>::key<PyObject, gdb::noop_deleter<PyObject>>
arch_object_data;
struct objfile *objfile;
};
+static_assert (gdb::is_python_allocatable_v<block_object>);
+
struct block_syms_iterator_object : public PyObject
{
/* The block. */
block_object *source;
};
+static_assert (gdb::is_python_allocatable_v<block_syms_iterator_object>);
+
/* Require a valid block. All access to block_object->block should be
gated by this call. */
#define BLPY_REQUIRE_VALID(block_obj, block) \
gdbpy_breakpoint_object *owner;
};
+static_assert (gdb::is_python_allocatable_v<gdbpy_breakpoint_location_object>);
+
/* Require that BREAKPOINT and LOCATION->OWNER are the same; throw a Python
exception if they are not. */
#define BPLOCPY_REQUIRE_VALID(Breakpoint, Location) \
struct cmd_list_element *sub_list;
};
+static_assert (gdb::is_python_allocatable_v<cmdpy_object>);
+
extern PyTypeObject cmdpy_object_type;
/* Constants used by this module. */
ui_file_style::color color;
};
+static_assert (gdb::is_python_allocatable_v<colorpy_object>);
+
extern PyTypeObject colorpy_object_type;
/* See py-color.h. */
struct process_stratum_target *target;
};
+static_assert (gdb::is_python_allocatable_v<connection_object>);
+
extern PyTypeObject connection_object_type;
extern PyTypeObject remote_connection_object_type;
bool is_main_exec_p;
};
+static_assert (gdb::is_python_allocatable_v<corefile_mapped_file_object>);
+
extern PyTypeObject corefile_mapped_file_object_type;
/* A gdb.CorefileMappedFileRegion object. */
ULONGEST file_offset;
};
+static_assert (gdb::is_python_allocatable_v<corefile_mapped_file_region_object>);
+
extern PyTypeObject corefile_mapped_file_region_object_type;
/* Clear the inferior pointer in a Corefile object OBJ when an inferior is
struct disasm_info_object *next;
};
+static_assert (gdb::is_python_allocatable_v<disasm_info_object>);
+
extern PyTypeObject disasm_info_object_type;
/* Implement gdb.disassembler.DisassembleAddressPart type. An object of
struct gdbarch *gdbarch;
};
+static_assert (gdb::is_python_allocatable_v<disasm_addr_part_object>);
+
extern PyTypeObject disasm_addr_part_object_type;
/* Implement gdb.disassembler.DisassembleTextPart type. An object of
enum disassembler_style style;
};
+static_assert (gdb::is_python_allocatable_v<disasm_text_part_object>);
+
extern PyTypeObject disasm_text_part_object_type;
extern PyTypeObject disasm_part_object_type;
std::vector<gdbpy_ref<>> *parts;
};
+static_assert (gdb::is_python_allocatable_v<disasm_result_object>);
+
extern PyTypeObject disasm_result_object_type;
/* When this is false we fast path out of gdbpy_print_insn, which should
PyObject *callbacks;
};
+static_assert (gdb::is_python_allocatable_v<eventregistry_object>);
+
/* Struct holding references to event registries both in python and c.
This is meant to be a singleton. */
int frame_id_is_next;
};
+static_assert (gdb::is_python_allocatable_v<frame_object>);
+
/* Require a valid frame. This must be called inside a TRY_CATCH, or
another context in which a gdb exception is allowed. */
#define FRAPY_REQUIRE_VALID(frame_obj, frame) \
struct py_insn_obj: public PyObject
{};
+static_assert (gdb::is_python_allocatable_v<py_insn_obj>);
+
/* Getter function for gdb.Instruction attributes. */
static PyObject *
PyObject *type;
};
+static_assert (gdb::is_python_allocatable_v<lazy_string_object>);
+
extern PyTypeObject lazy_string_object_type;
static PyObject *
CORE_ADDR pc;
};
+static_assert (gdb::is_python_allocatable_v<linetable_entry_object>);
+
extern PyTypeObject linetable_entry_object_type;
struct linetable_object : public PyObject
PyObject *symtab;
};
+static_assert (gdb::is_python_allocatable_v<linetable_object>);
+
extern PyTypeObject linetable_object_type;
struct ltpy_iterator_object : public PyObject
PyObject *source;
};
+static_assert (gdb::is_python_allocatable_v<ltpy_iterator_object>);
+
extern PyTypeObject ltpy_iterator_object_type;
/* Internal helper function to extract gdb.Symtab from a gdb.LineTable
CORE_ADDR length;
};
+static_assert (gdb::is_python_allocatable_v<membuf_object>);
+
extern PyTypeObject membuf_object_type;
/* Wrap BUFFER, ADDRESS, and LENGTH into a gdb.Membuf object. ADDRESS is
char *mi_command_name;
};
+static_assert (gdb::is_python_allocatable_v<micmdpy_object>);
+
/* The MI command implemented in Python. */
struct mi_command_py : public mi_command
const char **enumeration;
};
+static_assert (gdb::is_python_allocatable_v<parmpy_object>);
+
/* Wraps a setting around an existing parmpy_object. This abstraction
is used to manipulate the value in S->VALUE in a type safe manner using
the setting interface. */
struct printer_object : public PyObject
{};
+static_assert (gdb::is_python_allocatable_v<printer_object>);
+
/* The ValuePrinter type object. */
PyTypeObject printer_object_type =
{
PyTypeObject* element_type;
};
+static_assert (gdb::is_python_allocatable_v<btpy_list_object>);
+
/* Python type for btrace lists. */
static PyTypeObject btpy_list_type = {
Py_ssize_t number;
};
+static_assert (gdb::is_python_allocatable_v<recpy_gap_object>);
+
/* Implementation of record.method. */
static PyObject *
enum record_method method;
};
+static_assert (gdb::is_python_allocatable_v<recpy_record_object>);
+
/* Python recorded element object. This is generic enough to represent
recorded instructions as well as recorded function call segments, hence the
generic name. */
Py_ssize_t number;
};
+static_assert (gdb::is_python_allocatable_v<recpy_element_object>);
+
/* Python RecordInstruction type. */
extern PyTypeObject recpy_insn_type;
#define GDB_PYTHON_PY_REF_H
#include "gdbsupport/gdb_ref_ptr.h"
+#include "python-traits.h"
/* A policy class for gdb::ref_ptr for Python reference counting. */
struct gdbpy_ref_policy
}
};
+static_assert (gdb::is_python_allocatable_v<gdbpy_dict_wrapper>);
+
#endif /* GDB_PYTHON_PY_REF_H */
struct gdbarch *gdbarch;
};
+static_assert (gdb::is_python_allocatable_v<register_descriptor_iterator_object>);
+
extern PyTypeObject register_descriptor_iterator_object_type;
/* A register descriptor. */
struct gdbarch *gdbarch;
};
+static_assert (gdb::is_python_allocatable_v<register_descriptor_object>);
+
extern PyTypeObject register_descriptor_object_type;
/* Structure for iterator over register groups. */
struct gdbarch *gdbarch;
};
+static_assert (gdb::is_python_allocatable_v<reggroup_iterator_object>);
+
extern PyTypeObject reggroup_iterator_object_type;
/* A register group object. */
const struct reggroup *reggroup;
};
+static_assert (gdb::is_python_allocatable_v<reggroup_object>);
+
extern PyTypeObject reggroup_object_type;
/* Map from GDB's internal reggroup objects to the Python
char *style_name;
};
+static_assert (gdb::is_python_allocatable_v<style_object>);
+
extern PyTypeObject style_object_type;
/* Initialize the 'style' module. */
struct symbol *symbol;
};
+static_assert (gdb::is_python_allocatable_v<symbol_object>);
+
/* Require a valid symbol. All access to symbol_object->symbol should be
gated by this call. */
#define SYMPY_REQUIRE_VALID(symbol_obj, symbol) \
struct symtab *symtab;
};
+static_assert (gdb::is_python_allocatable_v<symtab_object>);
+
extern PyTypeObject symtab_object_type;
static const gdbpy_registry<gdbpy_memoizing_registry_storage<symtab_object,
symtab, &symtab_object::symtab>> stpy_registry;
sal_object *next;
};
+static_assert (gdb::is_python_allocatable_v<sal_object>);
+
/* This is called when an objfile is about to be freed. Invalidate
the sal object as further actions on the sal would result in bad
data. All access to obj->sal should be gated by
bool is_valid () const;
};
+static_assert (gdb::is_python_allocatable_v<gdbpy_tui_window>);
+
extern PyTypeObject gdbpy_tui_window_object_type;
/* A TUI window written in Python. */
struct type *type;
};
+static_assert (gdb::is_python_allocatable_v<type_object>);
+
extern PyTypeObject type_object_type;
/* A Field object. */
type_object *source;
};
+static_assert (gdb::is_python_allocatable_v<typy_iterator_object>);
+
extern PyTypeObject type_iterator_object_type;
/* This is used to initialize various gdb.TYPE_ constants. */
std::vector<saved_reg> *saved_regs;
};
+static_assert (gdb::is_python_allocatable_v<unwind_info_object>);
+
/* The data we keep for a frame we can unwind: frame ID and an array of
(register_number, register_value) pairs. */
PyObject *content_bytes;
};
+static_assert (gdb::is_python_allocatable_v<value_object>);
+
/* List of all values which are currently exposed to Python. It is
maintained so that when an objfile is discarded, preserve_values
can copy the values' types if needed. */
int is_finish_bp;
};
+static_assert (gdb::is_python_allocatable_v<gdbpy_breakpoint_object>);
+
/* Require that BREAKPOINT be a valid breakpoint ID; throw a Python
exception if it is invalid. */
#define BPPY_REQUIRE_VALID(Breakpoint) \
--- /dev/null
+/* Type traits relating to GDB's Python integration.
+
+ Copyright (C) 2008-2026 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDB_PYTHON_PYTHON_TRAITS_H
+#define GDB_PYTHON_PYTHON_TRAITS_H
+
+namespace gdb
+{
+/* All of our custom Python types are created as structs, like this:
+
+ struct some_new_type : public PyObject
+ {
+ ... various fields ...
+ };
+
+ Then instances of this struct are created by calling PyObject_New,
+ either directly within GDB's C++ code, or within Python when a user's
+ Python script creates an instance of that class.
+
+ The problem is that Python is written in C, and PyObject_New doesn't
+ call any constructors for `some_new_type`, nor for any of the fields
+ within `some_new_type`.
+
+ If `some_new_type` is Plain Old Data (POD), then this is fine. Or, to
+ be more C++ specific, if `some_new_type` is trivially default
+ constructable, then we're fine.
+
+ But if a field within `some_new_type` has a non-trivial constructor,
+ then we're in trouble as that constructor will never be run.
+
+ An example of a problematic field type is frame_info_ptr. The
+ constructor for this type registers the new object with a central
+ management object, recording the `this` pointer, using this type within
+ `some_new_type` will not work as expected; frame invalidation will not
+ show up within the frame_info_ptr as you might expect.
+
+ And so, this type trait exists. Whenever a struct is created to define
+ a new Python type we should add a line like:
+
+ static_assert (gdb::is_python_allocatable_v<some_new_type>);
+
+ This will fail if any field of `some_new_type` is unsuitable for this
+ use.
+
+ We don't actually check is_trivially_default_constructible here. Some
+ types, e.g. ui_file_style::color, have non-trivial (or no default)
+ constructors, but are still safe to use within `some_new_type` because
+ their constructors just initialise data fields; there's nothing
+ "special" that the constructor does that cannot be achieved by
+ assigning the fields after creation with PyObject_New.
+
+ What actually matters is that the type is trivially destructible
+ (Python won't call C++ destructors, so destructors with side effects,
+ like deregistering from a list, would be skipped) and trivially
+ copyable (Python may copy objects with memcpy). Types like
+ frame_info_ptr, whose constructors and destructors have side effects
+ such as registering with a central management object, will be caught
+ because they are neither trivially destructible nor trivially copyable.
+ Types like ui_file_style are trivially destructible and copyable, so
+ pass this trait. */
+
+template<typename T>
+struct is_python_allocatable
+{
+ static constexpr bool value =
+ std::is_trivially_destructible_v<T>
+ && std::is_trivially_copyable_v<T>;
+};
+
+/* Helper for the above trait to make it more usable. */
+
+template<typename T>
+inline constexpr bool is_python_allocatable_v
+ = is_python_allocatable<T>::value;
+}
+
+#endif /* GDB_PYTHON_PYTHON_TRAITS_H */