mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 09:43:06 +00:00
463b7ab074
For the most part, this simply entails adding the correct decorator. There are some notable conversions: - All of the memory management helpers that already had (prog: Program, addr: IntegerLike) and (addr: Object) overloads are now much simpler and support keyword arguments. - Helpers that already took a Program or an Object are also now much simpler and support keyword arguments. - Helpers that previously took a Program and positional parameters with a default value (path_lookup(), for_each_mount(), print_mounts()) had those parameters converted to keyword-only. This is not backwards-compatible, unfortunately. Signed-off-by: Omar Sandoval <osandov@osandov.com>
274 lines
7.6 KiB
C
274 lines
7.6 KiB
C
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
|
|
|
#include "drgnpy.h"
|
|
#include "../helpers.h"
|
|
#include "../program.h"
|
|
|
|
PyObject *drgnpy_linux_helper_direct_mapping_offset(PyObject *self, PyObject *arg)
|
|
{
|
|
struct drgn_error *err;
|
|
if (!PyObject_TypeCheck(arg, &Program_type)) {
|
|
return PyErr_Format(PyExc_TypeError, "expected Program, not %s",
|
|
Py_TYPE(arg)->tp_name);
|
|
}
|
|
uint64_t ret;
|
|
err = linux_helper_direct_mapping_offset(&((Program *)arg)->prog, &ret);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return PyLong_FromUint64(ret);
|
|
}
|
|
|
|
PyObject *drgnpy_linux_helper_read_vm(PyObject *self, PyObject *args,
|
|
PyObject *kwds)
|
|
{
|
|
static char *keywords[] = {"prog", "pgtable", "address", "size", NULL};
|
|
struct drgn_error *err;
|
|
Program *prog;
|
|
struct index_arg pgtable = {};
|
|
struct index_arg address = {};
|
|
Py_ssize_t size;
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O&O&n:read_vm",
|
|
keywords, &Program_type, &prog,
|
|
index_converter, &pgtable,
|
|
index_converter, &address, &size))
|
|
return NULL;
|
|
|
|
if (size < 0) {
|
|
PyErr_SetString(PyExc_ValueError, "negative size");
|
|
return NULL;
|
|
}
|
|
_cleanup_pydecref_ PyObject *buf = PyBytes_FromStringAndSize(NULL, size);
|
|
if (!buf)
|
|
return NULL;
|
|
err = linux_helper_read_vm(&prog->prog, pgtable.uvalue, address.uvalue,
|
|
PyBytes_AS_STRING(buf), size);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return_ptr(buf);
|
|
}
|
|
|
|
PyObject *drgnpy_linux_helper_follow_phys(PyObject *self, PyObject *args,
|
|
PyObject *kwds)
|
|
{
|
|
static char *keywords[] = {"prog", "pgtable", "address", NULL};
|
|
struct drgn_error *err;
|
|
Program *prog;
|
|
struct index_arg pgtable = {};
|
|
struct index_arg address = {};
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O&O&:follow_phys",
|
|
keywords, &Program_type, &prog,
|
|
index_converter, &pgtable,
|
|
index_converter, &address))
|
|
return NULL;
|
|
|
|
uint64_t phys;
|
|
err = linux_helper_follow_phys(&prog->prog, pgtable.uvalue,
|
|
address.uvalue, &phys);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return PyLong_FromUint64(phys);
|
|
}
|
|
|
|
DrgnObject *drgnpy_linux_helper_per_cpu_ptr(PyObject *self, PyObject *args,
|
|
PyObject *kwds)
|
|
{
|
|
static char *keywords[] = {"ptr", "cpu", NULL};
|
|
struct drgn_error *err;
|
|
DrgnObject *ptr;
|
|
struct index_arg cpu = {};
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O&:per_cpu_ptr",
|
|
keywords, &DrgnObject_type, &ptr,
|
|
index_converter, &cpu))
|
|
return NULL;
|
|
|
|
_cleanup_pydecref_ DrgnObject *res = DrgnObject_alloc(DrgnObject_prog(ptr));
|
|
if (!res)
|
|
return NULL;
|
|
err = linux_helper_per_cpu_ptr(&res->obj, &ptr->obj, cpu.uvalue);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return_ptr(res);
|
|
}
|
|
|
|
DrgnObject *drgnpy_linux_helper_cpu_curr(PyObject *self, PyObject *args)
|
|
{
|
|
struct drgn_error *err;
|
|
Program *prog;
|
|
struct index_arg cpu = {};
|
|
if (!PyArg_ParseTuple(args, "O!O&:cpu_curr", &Program_type, &prog,
|
|
index_converter, &cpu))
|
|
return NULL;
|
|
|
|
_cleanup_pydecref_ DrgnObject *res = DrgnObject_alloc(prog);
|
|
if (!res)
|
|
return NULL;
|
|
err = linux_helper_cpu_curr(&res->obj, cpu.uvalue);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return_ptr(res);
|
|
}
|
|
|
|
DrgnObject *drgnpy_linux_helper_idle_task(PyObject *self, PyObject *args)
|
|
{
|
|
struct drgn_error *err;
|
|
Program *prog;
|
|
struct index_arg cpu = {};
|
|
if (!PyArg_ParseTuple(args, "O!O&:idle_task", &Program_type, &prog,
|
|
index_converter, &cpu))
|
|
return NULL;
|
|
|
|
_cleanup_pydecref_ DrgnObject *res = DrgnObject_alloc(prog);
|
|
if (!res)
|
|
return NULL;
|
|
err = linux_helper_idle_task(&res->obj, cpu.uvalue);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return_ptr(res);
|
|
}
|
|
|
|
PyObject *drgnpy_linux_helper_task_cpu(PyObject *self, PyObject *args,
|
|
PyObject *kwds)
|
|
{
|
|
static char *keywords[] = {"task", NULL};
|
|
struct drgn_error *err;
|
|
DrgnObject *task;
|
|
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!:task_cpu", keywords,
|
|
&DrgnObject_type, &task))
|
|
return NULL;
|
|
uint64_t cpu;
|
|
err = linux_helper_task_cpu(&task->obj, &cpu);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return PyLong_FromUint64(cpu);
|
|
}
|
|
|
|
DrgnObject *drgnpy_linux_helper_xa_load(PyObject *self, PyObject *args,
|
|
PyObject *kwds)
|
|
{
|
|
static char *keywords[] = {"xa", "index", NULL};
|
|
struct drgn_error *err;
|
|
DrgnObject *xa;
|
|
struct index_arg index = {};
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O&:xa_load", keywords,
|
|
&DrgnObject_type, &xa, index_converter,
|
|
&index))
|
|
return NULL;
|
|
|
|
_cleanup_pydecref_ DrgnObject *res = DrgnObject_alloc(DrgnObject_prog(xa));
|
|
if (!res)
|
|
return NULL;
|
|
err = linux_helper_xa_load(&res->obj, &xa->obj, index.uvalue);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return_ptr(res);
|
|
}
|
|
|
|
DrgnObject *drgnpy_linux_helper_idr_find(PyObject *self, PyObject *args,
|
|
PyObject *kwds)
|
|
{
|
|
static char *keywords[] = {"idr", "id", NULL};
|
|
struct drgn_error *err;
|
|
DrgnObject *idr;
|
|
struct index_arg id = {};
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O&:idr_find", keywords,
|
|
&DrgnObject_type, &idr,
|
|
index_converter, &id))
|
|
return NULL;
|
|
|
|
_cleanup_pydecref_ DrgnObject *res =
|
|
DrgnObject_alloc(DrgnObject_prog(idr));
|
|
if (!res)
|
|
return NULL;
|
|
err = linux_helper_idr_find(&res->obj, &idr->obj, id.uvalue);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return_ptr(res);
|
|
}
|
|
|
|
DrgnObject *drgnpy_linux_helper_find_pid(PyObject *self, PyObject *args)
|
|
{
|
|
struct drgn_error *err;
|
|
DrgnObject *ns;
|
|
struct index_arg pid = {};
|
|
if (!PyArg_ParseTuple(args, "O!O&:find_pid", &DrgnObject_type, &ns,
|
|
index_converter, &pid))
|
|
return NULL;
|
|
|
|
_cleanup_pydecref_ DrgnObject *res =
|
|
DrgnObject_alloc(DrgnObject_prog(ns));
|
|
if (!res)
|
|
return NULL;
|
|
err = linux_helper_find_pid(&res->obj, &ns->obj, pid.uvalue);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return_ptr(res);
|
|
}
|
|
|
|
DrgnObject *drgnpy_linux_helper_pid_task(PyObject *self, PyObject *args,
|
|
PyObject *kwds)
|
|
{
|
|
static char *keywords[] = {"pid", "pid_type", NULL};
|
|
struct drgn_error *err;
|
|
DrgnObject *pid;
|
|
struct index_arg pid_type = {};
|
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O&:pid_task", keywords,
|
|
&DrgnObject_type, &pid,
|
|
index_converter, &pid_type))
|
|
return NULL;
|
|
|
|
_cleanup_pydecref_ DrgnObject *res = DrgnObject_alloc(DrgnObject_prog(pid));
|
|
if (!res)
|
|
return NULL;
|
|
err = linux_helper_pid_task(&res->obj, &pid->obj, pid_type.uvalue);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return_ptr(res);
|
|
}
|
|
|
|
DrgnObject *drgnpy_linux_helper_find_task(PyObject *self, PyObject *args)
|
|
{
|
|
struct drgn_error *err;
|
|
DrgnObject *ns;
|
|
struct index_arg pid = {};
|
|
if (!PyArg_ParseTuple(args, "O!O&:find_task", &DrgnObject_type, &ns,
|
|
index_converter, &pid))
|
|
return NULL;
|
|
|
|
_cleanup_pydecref_ DrgnObject *res =
|
|
DrgnObject_alloc(DrgnObject_prog(ns));
|
|
if (!res)
|
|
return NULL;
|
|
err = linux_helper_find_task(&res->obj, &ns->obj, pid.uvalue);
|
|
if (err)
|
|
return set_drgn_error(err);
|
|
return_ptr(res);
|
|
}
|
|
|
|
PyObject *drgnpy_linux_helper_kaslr_offset(PyObject *self, PyObject *arg)
|
|
|
|
{
|
|
if (!PyObject_TypeCheck(arg, &Program_type)) {
|
|
return PyErr_Format(PyExc_TypeError, "expected Program, not %s",
|
|
Py_TYPE(arg)->tp_name);
|
|
}
|
|
Program *prog = (Program *)arg;
|
|
if (!(prog->prog.flags & DRGN_PROGRAM_IS_LINUX_KERNEL))
|
|
return PyErr_Format(PyExc_ValueError, "not Linux kernel");
|
|
return PyLong_FromUint64(prog->prog.vmcoreinfo.kaslr_offset);
|
|
}
|
|
|
|
PyObject *drgnpy_linux_helper_pgtable_l5_enabled(PyObject *self, PyObject *arg)
|
|
|
|
{
|
|
if (!PyObject_TypeCheck(arg, &Program_type)) {
|
|
return PyErr_Format(PyExc_TypeError, "expected Program, not %s",
|
|
Py_TYPE(arg)->tp_name);
|
|
}
|
|
Program *prog = (Program *)arg;
|
|
if (!(prog->prog.flags & DRGN_PROGRAM_IS_LINUX_KERNEL))
|
|
return PyErr_Format(PyExc_ValueError, "not Linux kernel");
|
|
Py_RETURN_BOOL(prog->prog.vmcoreinfo.pgtable_l5_enabled);
|
|
}
|