libdrgn/python: add Program.cache

For caching metadata between invocations of helpers (e.g., detected
kernel version differences or config options).
This commit is contained in:
Omar Sandoval 2019-06-28 16:15:07 -07:00
parent 25e7a9d3b8
commit 97ebc2a57c
4 changed files with 46 additions and 2 deletions

View File

@ -268,6 +268,30 @@ Programs
available for some files; other files with debugging information
are still loaded if this is raised
.. attribute:: cache
Dictionary for caching program metadata.
This isn't used by drgn itself. It is intended to be used by helpers to
cache metadata about the program. For example, if a helper for a
program depends on the program version or an optional feature, the
helper can detect it and cache it for subsequent invocations:
.. code-block:: python3
def my_helper(prog):
try:
have_foo = prog.cache['have_foo']
except KeyError:
have_foo = detect_foo_feature(prog)
prog.cache['have_foo'] = have_foo
if have_foo:
return prog['foo']
else:
return prog['bar']
:vartype: dict
.. class:: ProgramFlags
``ProgramFlags`` is an :class:`enum.Flag` of flags that can apply to a

View File

@ -119,6 +119,8 @@ extern const char drgn_Program_add_type_finder_DOC[];
#define drgn_Program_add_type_finder_DOC (char *)drgn_Program_add_type_finder_DOC
extern const char drgn_Program_arch_DOC[];
#define drgn_Program_arch_DOC (char *)drgn_Program_arch_DOC
extern const char drgn_Program_cache_DOC[];
#define drgn_Program_cache_DOC (char *)drgn_Program_cache_DOC
extern const char drgn_Program_constant_DOC[];
#define drgn_Program_constant_DOC (char *)drgn_Program_constant_DOC
extern const char drgn_Program_flags_DOC[];
@ -149,6 +151,8 @@ extern const char drgn_ProgramFlags_DOC[];
#define drgn_ProgramFlags_DOC (char *)drgn_ProgramFlags_DOC
extern const char drgn_ProgramFlags_IS_LINUX_KERNEL_DOC[];
#define drgn_ProgramFlags_IS_LINUX_KERNEL_DOC (char *)drgn_ProgramFlags_IS_LINUX_KERNEL_DOC
extern const char drgn_ProgramFlags_IS_RUNNING_KERNEL_DOC[];
#define drgn_ProgramFlags_IS_RUNNING_KERNEL_DOC (char *)drgn_ProgramFlags_IS_RUNNING_KERNEL_DOC
extern const char drgn_Qualifiers_DOC[];
#define drgn_Qualifiers_DOC (char *)drgn_Qualifiers_DOC
extern const char drgn_Qualifiers_ATOMIC_DOC[];

View File

@ -75,6 +75,7 @@ typedef struct {
PyObject_HEAD
struct drgn_program prog;
PyObject *objects;
PyObject *cache;
} Program;
typedef struct {

View File

@ -71,7 +71,7 @@ static Program *Program_new(PyTypeObject *subtype, PyObject *args,
.value = DRGN_ARCH_AUTO,
.allow_none = true,
};
PyObject *objects;
PyObject *objects, *cache;
Program *prog;
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&:Program", keywords,
@ -82,12 +82,18 @@ static Program *Program_new(PyTypeObject *subtype, PyObject *args,
if (!objects)
return NULL;
cache = PyDict_New();
if (!cache)
return NULL;
prog = (Program *)Program_type.tp_alloc(&Program_type, 0);
if (!prog) {
Py_DECREF(cache);
Py_DECREF(objects);
return NULL;
}
prog->objects = objects;
prog->cache = cache;
drgn_program_init(&prog->prog, arch.value);
return prog;
}
@ -96,18 +102,21 @@ static void Program_dealloc(Program *self)
{
drgn_program_deinit(&self->prog);
Py_XDECREF(self->objects);
Py_XDECREF(self->cache);
Py_TYPE(self)->tp_free((PyObject *)self);
}
static int Program_traverse(Program *self, visitproc visit, void *arg)
{
Py_VISIT(self->objects);
Py_VISIT(self->cache);
return 0;
}
static int Program_clear(Program *self)
{
Py_CLEAR(self->objects);
Py_CLEAR(self->cache);
return 0;
}
@ -838,6 +847,12 @@ static PyMethodDef Program_methods[] = {
{},
};
static PyMemberDef Program_members[] = {
{"cache", T_OBJECT_EX, offsetof(Program, cache), 0,
drgn_Program_cache_DOC},
{},
};
static PyGetSetDef Program_getset[] = {
{"flags", (getter)Program_get_flags, NULL, drgn_Program_flags_DOC},
{"arch", (getter)Program_get_arch, NULL, drgn_Program_arch_DOC},
@ -892,7 +907,7 @@ PyTypeObject Program_type = {
NULL, /* tp_iter */
NULL, /* tp_iternext */
Program_methods, /* tp_methods */
NULL, /* tp_members */
Program_members, /* tp_members */
Program_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */