mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-12-05 23:23:09 +00:00
Add a new Corefile.mapped_files method which returns a list of
gdb.CorefileMappedFile objects.
Each gdb.CorefileMappedFile object represents a file that was mapped
into the process when the core file was created.
A gdb.CorefileMappedFile has attributes:
+ filename -- A string, the name of the mapped file.
+ build_id -- A string or None, the build-id of the mapped file if
GDB could find it (None if not).
+ is_main_executable -- A boolean, True if this mapping is the main
executable.
+ regions -- A list containing the regions of this file that were
mapped into the process.
The 'regions' list is a list of gdb.CorefileMappedFileRegion objects,
each of these objects has the following attributes:
+ start -- the start address within the inferior.
+ end -- the end address within the inferior.
+ file_offset -- the offset within the mapped file for this mapping.
There are docs and tests.
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=32844
Approved-By: Tom Tromey <tom@tromey.com>
689 lines
19 KiB
C
689 lines
19 KiB
C
/* Python interface to core files.
|
||
|
||
Copyright (C) 2025 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/>. */
|
||
|
||
#include "python-internal.h"
|
||
#include "progspace.h"
|
||
#include "observable.h"
|
||
#include "inferior.h"
|
||
#include "gdbcore.h"
|
||
#include "gdbsupport/rsp-low.h"
|
||
|
||
/* A gdb.Corefile object. */
|
||
|
||
struct corefile_object
|
||
{
|
||
PyObject_HEAD
|
||
|
||
/* The inferior this core file is attached to. This will be set to NULL
|
||
when the inferior is deleted, or if a different core file is loaded
|
||
for the inferior. When this is NULL the gdb.Corefile object is
|
||
considered invalid.*/
|
||
struct inferior *inferior;
|
||
|
||
/* Dictionary holding user-added attributes. This is the __dict__
|
||
attribute of the object. This is an owning reference. */
|
||
PyObject *dict;
|
||
|
||
/* A Tuple of gdb.CorefileMappedFile objects. This tuple is only created
|
||
the first time the user calls gdb.Corefile.mapped_files(), the result
|
||
is cached here. If this pointer is not NULL then this is an owning
|
||
pointer (i.e. this owns a reference to the Tuple). */
|
||
PyObject *mapped_files;
|
||
};
|
||
|
||
extern PyTypeObject corefile_object_type
|
||
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("corefile_object");
|
||
|
||
/* A gdb.CorefileMapped object. */
|
||
|
||
struct corefile_mapped_file_object
|
||
{
|
||
PyObject_HEAD
|
||
|
||
/* The name of a file that was mapped when the core file was created.
|
||
This is a 'str' object. */
|
||
PyObject *filename;
|
||
|
||
/* The build-id of a file that was mapped when the core file was
|
||
created. This is either a 'str' if the file had a build-id, or
|
||
'None' if there was no build-id for this file. */
|
||
PyObject *build_id;
|
||
|
||
/* A List of gdb.CorefileMappedFileRegion objects. */
|
||
PyObject *regions;
|
||
|
||
/* True if this represents the main executable from which the core file
|
||
was created. */
|
||
bool is_main_exec_p;
|
||
};
|
||
|
||
extern PyTypeObject corefile_mapped_file_object_type
|
||
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("corefile_mapped_file_object");
|
||
|
||
/* A gdb.CorefileMappedFileRegion object. */
|
||
|
||
struct corefile_mapped_file_region_object
|
||
{
|
||
PyObject_HEAD
|
||
|
||
/* The start and end addresses for this mapping, these are addresses
|
||
within the inferior's address space. */
|
||
CORE_ADDR start;
|
||
CORE_ADDR end;
|
||
|
||
/* The offset within the mapped file for this mapping. */
|
||
ULONGEST file_offset;
|
||
};
|
||
|
||
extern PyTypeObject corefile_mapped_file_region_object_type
|
||
CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("corefile_mapped_file_region_object");
|
||
|
||
/* Clear the inferior pointer in a Corefile object OBJ when an inferior is
|
||
deleted. */
|
||
|
||
struct inferior_corefile_deleter
|
||
{
|
||
void operator() (corefile_object *obj)
|
||
{
|
||
if (!gdb_python_initialized)
|
||
return;
|
||
|
||
gdbpy_enter enter_py;
|
||
|
||
/* When OBJECT goes out of scope this will Py_DECREF on OBJ. */
|
||
gdbpy_ref<corefile_object> object (obj);
|
||
|
||
/* Clearing the inferior pointer marks the gdb.Corefile as invalid. */
|
||
object->inferior = nullptr;
|
||
}
|
||
};
|
||
|
||
/* Store a gdb.Corefile object in an inferior's registry. */
|
||
|
||
static const registry<inferior>::key<corefile_object,
|
||
inferior_corefile_deleter>
|
||
cfpy_inferior_corefile_data_key;
|
||
|
||
/* See python-internal.h. */
|
||
|
||
gdbpy_ref<>
|
||
gdbpy_core_file_from_inferior (inferior *inf)
|
||
{
|
||
gdb_assert (inf != nullptr);
|
||
gdb_assert (inf->pspace != nullptr);
|
||
|
||
program_space *pspace = inf->pspace;
|
||
|
||
if (pspace->core_bfd () == nullptr)
|
||
return gdbpy_ref<>::new_reference (Py_None);
|
||
|
||
PyObject *result = (PyObject *) cfpy_inferior_corefile_data_key.get (inf);
|
||
if (result == nullptr)
|
||
{
|
||
gdbpy_ref<corefile_object> object
|
||
(PyObject_New (corefile_object, &corefile_object_type));
|
||
if (object == nullptr)
|
||
return nullptr;
|
||
|
||
/* Ensure the 'inferior' field is set to NULL. If the PyDict_New
|
||
call fails then the gdb.Corefile will be discarded and
|
||
cfpy_dealloc will be called, which requires that the 'inferior' be
|
||
set to NULL. */
|
||
object->inferior = nullptr;
|
||
object->mapped_files = nullptr;
|
||
object->dict = PyDict_New ();
|
||
if (object->dict == nullptr)
|
||
return nullptr;
|
||
|
||
/* Now that the gdb.Corefile has been successfully initialised and we
|
||
know that it is going to be passed back to the user, move it out
|
||
of the invalid state by setting the 'inferior' field to a non NULL
|
||
value. */
|
||
object->inferior = inf;
|
||
cfpy_inferior_corefile_data_key.set (inf, object.get ());
|
||
result = (PyObject *) object.release ();
|
||
}
|
||
|
||
return gdbpy_ref<>::new_reference (result);
|
||
}
|
||
|
||
/* Return true if OBJ is valid. */
|
||
|
||
static bool
|
||
cfpy_corefile_object_is_valid (const corefile_object *obj)
|
||
{
|
||
if (obj->inferior == nullptr)
|
||
return false;
|
||
|
||
gdb_assert (obj->inferior->pspace != nullptr);
|
||
|
||
return obj->inferior->pspace->core_bfd () != nullptr;
|
||
}
|
||
|
||
/* Require that COREFILE_OBJ be a valid core file. A valid core file
|
||
object has a valid program space, and the program space has a core file
|
||
loaded into it. */
|
||
#define CFPY_REQUIRE_VALID(corefile_obj) \
|
||
do { \
|
||
if (!cfpy_corefile_object_is_valid (corefile_obj)) \
|
||
{ \
|
||
PyErr_SetString (PyExc_RuntimeError, \
|
||
_("Corefile no longer exists.")); \
|
||
return nullptr; \
|
||
} \
|
||
} while (0)
|
||
|
||
/* Read the gdb.Corefile.filename attribute. */
|
||
|
||
static PyObject *
|
||
cfpy_get_filename (PyObject *self, void *closure)
|
||
{
|
||
corefile_object *obj = (corefile_object *) self;
|
||
|
||
CFPY_REQUIRE_VALID (obj);
|
||
|
||
/* If the program space's core file had been cleared, then this Corefile
|
||
object would have been invalidated. */
|
||
bfd *abfd = obj->inferior->pspace->core_bfd ();
|
||
gdb_assert (abfd != nullptr);
|
||
|
||
return host_string_to_python_string (bfd_get_filename (abfd)).release ();
|
||
}
|
||
|
||
/* Implementation of gdb.Corefile.is_valid (self) -> Boolean.
|
||
Returns True if this core file object is associated with a program space
|
||
that still exists, an the program space still has a core file loaded. */
|
||
|
||
static PyObject *
|
||
cfpy_is_valid (PyObject *self, PyObject *args)
|
||
{
|
||
corefile_object *obj = (corefile_object *) self;
|
||
|
||
if (!cfpy_corefile_object_is_valid (obj))
|
||
Py_RETURN_FALSE;
|
||
|
||
Py_RETURN_TRUE;
|
||
}
|
||
|
||
/* Implement gdb.Corefile.mapped_files (). Return a List of
|
||
gdb.CorefileMappedFile objects. The list is created the first time
|
||
this method is called, and then cached within the gdb.Corefile object,
|
||
future calls just return a reference to the same list. */
|
||
|
||
static PyObject *
|
||
cfpy_mapped_files (PyObject *self, PyObject *args)
|
||
{
|
||
corefile_object *obj = (corefile_object *) self;
|
||
|
||
CFPY_REQUIRE_VALID (obj);
|
||
|
||
/* If we have already created the List then just return another reference
|
||
to the existing list. */
|
||
if (obj->mapped_files != nullptr)
|
||
{
|
||
Py_INCREF (obj->mapped_files);
|
||
return obj->mapped_files;
|
||
}
|
||
|
||
/* Get all the mapping data from GDB. */
|
||
std::vector<core_mapped_file> mapped_files;
|
||
try
|
||
{
|
||
mapped_files
|
||
= gdb_read_core_file_mappings (obj->inferior->arch (),
|
||
current_program_space->core_bfd ());
|
||
}
|
||
catch (const gdb_exception &except)
|
||
{
|
||
return gdbpy_handle_gdb_exception (nullptr, except);
|
||
}
|
||
|
||
/* Create a new list to hold the results. */
|
||
gdbpy_ref<> tuple (PyTuple_New (mapped_files.size ()));
|
||
if (tuple == nullptr)
|
||
return nullptr;
|
||
|
||
/* Create each gdb.CorefileMappedFile object. */
|
||
Py_ssize_t tuple_idx = 0;
|
||
for (const core_mapped_file &file : mapped_files)
|
||
{
|
||
/* The filename 'str' object. */
|
||
gdbpy_ref<> filename
|
||
= host_string_to_python_string (file.filename.c_str ());
|
||
if (filename == nullptr)
|
||
return nullptr;
|
||
|
||
/* The build-id object. Either a 'str' or 'None'. */
|
||
gdbpy_ref<> build_id;
|
||
if (file.build_id != nullptr)
|
||
{
|
||
std::string hex_form = bin2hex (file.build_id->data,
|
||
file.build_id->size);
|
||
|
||
build_id
|
||
= host_string_to_python_string (hex_form.c_str ());
|
||
if (build_id == nullptr)
|
||
return nullptr;
|
||
}
|
||
else
|
||
build_id = gdbpy_ref<>::new_reference (Py_None);
|
||
|
||
/* List to hold all the gdb.CorefileMappedFileRegion objects. */
|
||
gdbpy_ref<> regions (PyTuple_New (file.regions.size ()));
|
||
if (regions == nullptr)
|
||
return nullptr;
|
||
|
||
/* Create all the gdb.CorefileMappedFileRegion objects. */
|
||
Py_ssize_t regions_idx = 0;
|
||
for (const core_mapped_file::region &r : file.regions)
|
||
{
|
||
/* Actually create the object. */
|
||
gdbpy_ref<corefile_mapped_file_region_object> region_obj
|
||
(PyObject_New (corefile_mapped_file_region_object,
|
||
&corefile_mapped_file_region_object_type));
|
||
if (region_obj == nullptr)
|
||
return nullptr;
|
||
|
||
/* Initialise the object. */
|
||
region_obj->start = r.start;
|
||
region_obj->end = r.end;
|
||
region_obj->file_offset = r.file_ofs;
|
||
|
||
/* Add to the gdb.CorefileMappedFileRegion list. */
|
||
if (PyTuple_SetItem (regions.get (), regions_idx++,
|
||
(PyObject *) region_obj.release ()) < 0)
|
||
return nullptr;
|
||
}
|
||
|
||
/* Actually create the gdb.CorefileMappedFile object. */
|
||
gdbpy_ref<corefile_mapped_file_object> entry
|
||
(PyObject_New (corefile_mapped_file_object,
|
||
&corefile_mapped_file_object_type));
|
||
if (entry == nullptr)
|
||
return nullptr;
|
||
|
||
/* Initialise the object. */
|
||
entry->filename = filename.release ();
|
||
entry->build_id = build_id.release ();
|
||
entry->regions = regions.release ();
|
||
entry->is_main_exec_p = file.is_main_exec;
|
||
|
||
/* Add to the gdb.CorefileMappedFile list. */
|
||
if (PyTuple_SetItem (tuple.get (), tuple_idx++,
|
||
(PyObject *) entry.release ()) < 0)
|
||
return nullptr;
|
||
}
|
||
|
||
/* No errors. Move the reference currently in LIST into the Corefile
|
||
object itself. Then create a new reference and hand this back to the
|
||
user. */
|
||
obj->mapped_files = tuple.release ();
|
||
Py_INCREF (obj->mapped_files);
|
||
return obj->mapped_files;
|
||
}
|
||
|
||
/* Callback from gdb::observers::core_file_changed. The core file in
|
||
PSPACE has been changed. */
|
||
|
||
static void
|
||
cfpy_corefile_changed (inferior *inf)
|
||
{
|
||
cfpy_inferior_corefile_data_key.clear (inf);
|
||
}
|
||
|
||
/* Called when a gdb.Corefile is destroyed. */
|
||
|
||
static void
|
||
cfpy_dealloc (PyObject *obj)
|
||
{
|
||
corefile_object *corefile = (corefile_object *) obj;
|
||
|
||
/* Every gdb.Corefile is cached in an inferior's registry. The only way
|
||
for a gdb.Corefile to be deallocated is to remove the object reference
|
||
from the registry (and dec its ref count), but before we do that, we
|
||
set the object's inferior pointer to NULL. */
|
||
gdb_assert (corefile->inferior == nullptr);
|
||
|
||
Py_XDECREF (corefile->dict);
|
||
Py_XDECREF (corefile->mapped_files);
|
||
|
||
Py_TYPE (obj)->tp_free (obj);
|
||
}
|
||
|
||
/* __repr__ implementation for gdb.Corefile. */
|
||
|
||
static PyObject *
|
||
cfpy_repr (PyObject *self)
|
||
{
|
||
corefile_object *obj = (corefile_object *) self;
|
||
|
||
if (!cfpy_corefile_object_is_valid (obj))
|
||
return gdb_py_invalid_object_repr (self);
|
||
|
||
program_space *pspace = obj->inferior->pspace;
|
||
gdb_assert (pspace != nullptr);
|
||
return PyUnicode_FromFormat ("<%s inferior=%d filename='%s'>",
|
||
Py_TYPE (self)->tp_name,
|
||
obj->inferior->num,
|
||
bfd_get_filename (pspace->core_bfd ()));
|
||
}
|
||
|
||
|
||
|
||
/* Called when a gdb.CorefileMappedFile is destroyed. */
|
||
|
||
static void
|
||
cfmfpy_dealloc (PyObject *obj)
|
||
{
|
||
corefile_mapped_file_object *mapped_file
|
||
= (corefile_mapped_file_object *) obj;
|
||
|
||
Py_XDECREF (mapped_file->filename);
|
||
Py_XDECREF (mapped_file->build_id);
|
||
Py_XDECREF (mapped_file->regions);
|
||
|
||
Py_TYPE (obj)->tp_free (obj);
|
||
}
|
||
|
||
/* Read the gdb.CorefileMappedFile.filename attribute. */
|
||
|
||
static PyObject *
|
||
cfmfpy_get_filename (PyObject *self, void *closure)
|
||
{
|
||
corefile_mapped_file_object *obj
|
||
= (corefile_mapped_file_object *) self;
|
||
|
||
gdb_assert (obj->filename != nullptr);
|
||
|
||
Py_INCREF (obj->filename);
|
||
return obj->filename;
|
||
}
|
||
|
||
/* Read the gdb.CorefileMappedFile.build_id attribute. */
|
||
|
||
static PyObject *
|
||
cfmfpy_get_build_id (PyObject *self, void *closure)
|
||
{
|
||
corefile_mapped_file_object *obj
|
||
= (corefile_mapped_file_object *) self;
|
||
|
||
gdb_assert (obj->build_id != nullptr);
|
||
|
||
Py_INCREF (obj->build_id);
|
||
return obj->build_id;
|
||
}
|
||
|
||
/* Read the gdb.CorefileMappedFile.regions attribute. */
|
||
|
||
static PyObject *
|
||
cfmfpy_get_regions (PyObject *self, void *closure)
|
||
{
|
||
corefile_mapped_file_object *obj
|
||
= (corefile_mapped_file_object *) self;
|
||
|
||
gdb_assert (obj->regions != nullptr);
|
||
|
||
Py_INCREF (obj->regions);
|
||
return obj->regions;
|
||
}
|
||
|
||
/* Read the gdb.CorefileMappedFile.is_main_executable attribute. */
|
||
|
||
static PyObject *
|
||
cfmf_is_main_exec (PyObject *self, void *closure)
|
||
{
|
||
corefile_mapped_file_object *obj
|
||
= (corefile_mapped_file_object *) self;
|
||
|
||
if (obj->is_main_exec_p)
|
||
Py_RETURN_TRUE;
|
||
else
|
||
Py_RETURN_FALSE;
|
||
}
|
||
|
||
|
||
|
||
/* Read the gdb.CorefileMappedFileRegion.start attribute. */
|
||
|
||
static PyObject *
|
||
cfmfrpy_get_start (PyObject *self, void *closure)
|
||
{
|
||
corefile_mapped_file_region_object *obj
|
||
= (corefile_mapped_file_region_object *) self;
|
||
|
||
return gdb_py_object_from_ulongest (obj->start).release ();
|
||
}
|
||
|
||
/* Read the gdb.CorefileMappedFileRegion.end attribute. */
|
||
|
||
static PyObject *
|
||
cfmfrpy_get_end (PyObject *self, void *closure)
|
||
{
|
||
corefile_mapped_file_region_object *obj
|
||
= (corefile_mapped_file_region_object *) self;
|
||
|
||
return gdb_py_object_from_ulongest (obj->end).release ();
|
||
}
|
||
|
||
/* Read the gdb.CorefileMappedFileRegion.file_offset attribute. */
|
||
|
||
static PyObject *
|
||
cfmfrpy_get_file_offset (PyObject *self, void *closure)
|
||
{
|
||
corefile_mapped_file_region_object *obj
|
||
= (corefile_mapped_file_region_object *) self;
|
||
|
||
return gdb_py_object_from_ulongest (obj->file_offset).release ();
|
||
}
|
||
|
||
|
||
|
||
static int
|
||
gdbpy_initialize_corefile ()
|
||
{
|
||
gdb::observers::core_file_changed.attach (cfpy_corefile_changed,
|
||
"py-corefile");
|
||
|
||
if (gdbpy_type_ready (&corefile_object_type) < 0)
|
||
return -1;
|
||
|
||
if (gdbpy_type_ready (&corefile_mapped_file_object_type) < 0)
|
||
return -1;
|
||
|
||
if (gdbpy_type_ready (&corefile_mapped_file_region_object_type) < 0)
|
||
return -1;
|
||
|
||
return 0;
|
||
}
|
||
|
||
GDBPY_INITIALIZE_FILE (gdbpy_initialize_corefile);
|
||
|
||
|
||
|
||
static gdb_PyGetSetDef corefile_getset[] =
|
||
{
|
||
{ "__dict__", gdb_py_generic_dict, nullptr,
|
||
"The __dict__ for the gdb.Corefile.", &corefile_object_type },
|
||
{ "filename", cfpy_get_filename, nullptr,
|
||
"The filename of a valid Corefile object.", nullptr },
|
||
{ nullptr }
|
||
};
|
||
|
||
static PyMethodDef corefile_object_methods[] =
|
||
{
|
||
{ "is_valid", cfpy_is_valid, METH_NOARGS,
|
||
"is_valid () -> Boolean.\n\
|
||
Return true if this Corefile is valid, false if not." },
|
||
{ "mapped_files", cfpy_mapped_files, METH_NOARGS,
|
||
"mapped_files () -> List of mapping tuples.\n\
|
||
Return a list of tuples. Each tuple represents a mapping from the\
|
||
core file." },
|
||
{ nullptr }
|
||
};
|
||
|
||
PyTypeObject corefile_object_type =
|
||
{
|
||
PyVarObject_HEAD_INIT (nullptr, 0)
|
||
"gdb.Corefile", /*tp_name*/
|
||
sizeof (corefile_object), /*tp_basicsize*/
|
||
0, /*tp_itemsize*/
|
||
cfpy_dealloc, /*tp_dealloc*/
|
||
0, /*tp_print*/
|
||
0, /*tp_getattr*/
|
||
0, /*tp_setattr*/
|
||
0, /*tp_compare*/
|
||
cfpy_repr, /*tp_repr*/
|
||
0, /*tp_as_number*/
|
||
0, /*tp_as_sequence*/
|
||
0, /*tp_as_mapping*/
|
||
0, /*tp_hash */
|
||
0, /*tp_call*/
|
||
0, /*tp_str*/
|
||
0, /*tp_getattro*/
|
||
0, /*tp_setattro*/
|
||
0, /*tp_as_buffer*/
|
||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||
"GDB corefile object", /* tp_doc */
|
||
0, /* tp_traverse */
|
||
0, /* tp_clear */
|
||
0, /* tp_richcompare */
|
||
0, /* tp_weaklistoffset */
|
||
0, /* tp_iter */
|
||
0, /* tp_iternext */
|
||
corefile_object_methods, /* tp_methods */
|
||
0, /* tp_members */
|
||
corefile_getset, /* tp_getset */
|
||
0, /* tp_base */
|
||
0, /* tp_dict */
|
||
0, /* tp_descr_get */
|
||
0, /* tp_descr_set */
|
||
offsetof (corefile_object, dict), /* tp_dictoffset */
|
||
0, /* tp_init */
|
||
0, /* tp_alloc */
|
||
0, /* tp_new */
|
||
};
|
||
|
||
static gdb_PyGetSetDef corefile_mapped_file_object_getset[] =
|
||
{
|
||
{ "filename", cfmfpy_get_filename, nullptr,
|
||
"The filename of a CorefileMappedFile object.", nullptr },
|
||
{ "build_id", cfmfpy_get_build_id, nullptr,
|
||
"The build-id of a CorefileMappedFile object or None.", nullptr },
|
||
{ "regions", cfmfpy_get_regions, nullptr,
|
||
"The list of regions from a CorefileMappedFile object.", nullptr },
|
||
{ "is_main_executable", cfmf_is_main_exec, nullptr,
|
||
"True for the main executable mapping, otherwise False.", nullptr },
|
||
{ nullptr }
|
||
};
|
||
|
||
PyTypeObject corefile_mapped_file_object_type =
|
||
{
|
||
PyVarObject_HEAD_INIT (NULL, 0)
|
||
"gdb.CorefileMappedFile", /*tp_name*/
|
||
sizeof (corefile_mapped_file_object), /*tp_basicsize*/
|
||
0, /*tp_itemsize*/
|
||
cfmfpy_dealloc, /*tp_dealloc*/
|
||
0, /*tp_print*/
|
||
0, /*tp_getattr*/
|
||
0, /*tp_setattr*/
|
||
0, /*tp_compare*/
|
||
0, /*tp_repr*/
|
||
0, /*tp_as_number*/
|
||
0, /*tp_as_sequence*/
|
||
0, /*tp_as_mapping*/
|
||
0, /*tp_hash */
|
||
0, /*tp_call*/
|
||
0, /*tp_str*/
|
||
0, /*tp_getattro*/
|
||
0, /*tp_setattro*/
|
||
0, /*tp_as_buffer*/
|
||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||
"GDB corefile mapped file object", /* tp_doc */
|
||
0, /* tp_traverse */
|
||
0, /* tp_clear */
|
||
0, /* tp_richcompare */
|
||
0, /* tp_weaklistoffset */
|
||
0, /* tp_iter */
|
||
0, /* tp_iternext */
|
||
0, /* tp_methods */
|
||
0, /* tp_members */
|
||
corefile_mapped_file_object_getset, /* tp_getset */
|
||
0, /* tp_base */
|
||
0, /* tp_dict */
|
||
0, /* tp_descr_get */
|
||
0, /* tp_descr_set */
|
||
0, /* tp_dictoffset */
|
||
0, /* tp_init */
|
||
0, /* tp_alloc */
|
||
0, /* tp_new */
|
||
};
|
||
|
||
static gdb_PyGetSetDef corefile_mapped_file_region_object_getset[] =
|
||
{
|
||
{ "start", cfmfrpy_get_start, nullptr,
|
||
"The start address of a CorefileMappedFileRegion object.", nullptr },
|
||
{ "end", cfmfrpy_get_end, nullptr,
|
||
"The end address of a CorefileMappedFileRegion object.", nullptr },
|
||
{ "file_offset", cfmfrpy_get_file_offset, nullptr,
|
||
"The file offset of a CorefileMappedFileRegion object.", nullptr },
|
||
{ nullptr }
|
||
};
|
||
|
||
PyTypeObject corefile_mapped_file_region_object_type =
|
||
{
|
||
PyVarObject_HEAD_INIT (NULL, 0)
|
||
"gdb.CorefileMappedFileRegion", /*tp_name*/
|
||
sizeof (corefile_mapped_file_region_object), /*tp_basicsize*/
|
||
0, /*tp_itemsize*/
|
||
0, /*tp_dealloc*/
|
||
0, /*tp_print*/
|
||
0, /*tp_getattr*/
|
||
0, /*tp_setattr*/
|
||
0, /*tp_compare*/
|
||
0, /*tp_repr*/
|
||
0, /*tp_as_number*/
|
||
0, /*tp_as_sequence*/
|
||
0, /*tp_as_mapping*/
|
||
0, /*tp_hash */
|
||
0, /*tp_call*/
|
||
0, /*tp_str*/
|
||
0, /*tp_getattro*/
|
||
0, /*tp_setattro*/
|
||
0, /*tp_as_buffer*/
|
||
Py_TPFLAGS_DEFAULT, /*tp_flags*/
|
||
"GDB corefile mapped file region object", /* tp_doc */
|
||
0, /* tp_traverse */
|
||
0, /* tp_clear */
|
||
0, /* tp_richcompare */
|
||
0, /* tp_weaklistoffset */
|
||
0, /* tp_iter */
|
||
0, /* tp_iternext */
|
||
0, /* tp_methods */
|
||
0, /* tp_members */
|
||
corefile_mapped_file_region_object_getset, /* tp_getset */
|
||
0, /* tp_base */
|
||
0, /* tp_dict */
|
||
0, /* tp_descr_get */
|
||
0, /* tp_descr_set */
|
||
0, /* tp_dictoffset */
|
||
0, /* tp_init */
|
||
0, /* tp_alloc */
|
||
0, /* tp_new */
|
||
};
|