mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 01:33:06 +00:00
libdrgn: support getting register values from stack frames
Currently, the only information available from a stack frame is the program counter. Eventually, we'd like to add support for getting arguments and local variables, but that will require more work. In the mean time, we can at least get the values of other registers. A determined user can read the assembly for the code they're debugging and derive the values of variables from the registers.
This commit is contained in:
parent
4fb0e2e110
commit
0da60a41cd
@ -879,6 +879,23 @@ Stack Traces
|
||||
|
||||
:rtype: Symbol
|
||||
|
||||
.. method:: register(reg)
|
||||
|
||||
Get the value of the given register at this stack frame. The register
|
||||
can be specified by name (e.g., ``'rax'``), number (see
|
||||
:attr:`RegisterInfo.number`), or as a :class:`RegisterInfo`.
|
||||
|
||||
:param reg: Register to get.
|
||||
:type reg: str, int, or RegisterInfo
|
||||
:rtype: int
|
||||
|
||||
.. method:: registers()
|
||||
|
||||
Get the values of all available registers at this stack frame as a
|
||||
dictionary with the register names as keys.
|
||||
|
||||
:rtype: dict[str, int]
|
||||
|
||||
.. _api-reference-types:
|
||||
|
||||
Types
|
||||
|
@ -2300,6 +2300,16 @@ uint64_t drgn_stack_frame_pc(struct drgn_stack_frame frame);
|
||||
struct drgn_error *drgn_stack_frame_symbol(struct drgn_stack_frame frame,
|
||||
struct drgn_symbol **ret);
|
||||
|
||||
/** Get the value of a register (by number) in a stack frame. */
|
||||
struct drgn_error *drgn_stack_frame_register(struct drgn_stack_frame frame,
|
||||
enum drgn_register_number regno,
|
||||
uint64_t *ret);
|
||||
|
||||
/** Get the value of a register (by name) in a stack frame. */
|
||||
struct drgn_error *
|
||||
drgn_stack_frame_register_by_name(struct drgn_stack_frame frame,
|
||||
const char *name, uint64_t *ret);
|
||||
|
||||
/**
|
||||
* Get a stack trace for the thread represented by @p obj.
|
||||
*
|
||||
|
@ -24,6 +24,15 @@ struct drgn_architecture_info {
|
||||
struct drgn_object *);
|
||||
};
|
||||
|
||||
static inline const struct drgn_register *
|
||||
drgn_architecture_register_by_name(const struct drgn_architecture_info *arch,
|
||||
const char *name)
|
||||
{
|
||||
if (!arch->register_by_name)
|
||||
return NULL;
|
||||
return arch->register_by_name(name);
|
||||
}
|
||||
|
||||
extern const struct drgn_architecture_info arch_info_unknown;
|
||||
extern const struct drgn_architecture_info arch_info_x86_64;
|
||||
|
||||
|
@ -103,6 +103,72 @@ static PyObject *StackFrame_symbol(StackFrame *self)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PyObject *StackFrame_register(StackFrame *self, PyObject *arg)
|
||||
{
|
||||
struct drgn_error *err;
|
||||
uint64_t value;
|
||||
|
||||
if (PyUnicode_Check(arg)) {
|
||||
err = drgn_stack_frame_register_by_name(self->frame,
|
||||
PyUnicode_AsUTF8(arg),
|
||||
&value);
|
||||
} else {
|
||||
struct index_arg number = {};
|
||||
|
||||
if (PyObject_TypeCheck(arg, &Register_type))
|
||||
arg = PyStructSequence_GET_ITEM(arg, 1);
|
||||
if (!index_converter(arg, &number))
|
||||
return NULL;
|
||||
err = drgn_stack_frame_register(self->frame, number.value,
|
||||
&value);
|
||||
}
|
||||
if (err)
|
||||
return set_drgn_error(err);
|
||||
return PyLong_FromUnsignedLongLong(value);
|
||||
}
|
||||
|
||||
static PyObject *StackFrame_registers(StackFrame *self)
|
||||
{
|
||||
struct drgn_error *err;
|
||||
PyObject *dict;
|
||||
const struct drgn_platform *platform;
|
||||
size_t num_registers, i;
|
||||
|
||||
dict = PyDict_New();
|
||||
if (!dict)
|
||||
return NULL;
|
||||
platform = drgn_program_platform(&self->trace->prog->prog);
|
||||
num_registers = drgn_platform_num_registers(platform);
|
||||
for (i = 0; i < num_registers; i++) {
|
||||
const struct drgn_register *reg;
|
||||
uint64_t value;
|
||||
PyObject *value_obj;
|
||||
int ret;
|
||||
|
||||
reg = drgn_platform_register(platform, i);
|
||||
err = drgn_stack_frame_register(self->frame,
|
||||
drgn_register_number(reg),
|
||||
&value);
|
||||
if (err) {
|
||||
drgn_error_destroy(err);
|
||||
continue;
|
||||
}
|
||||
value_obj = PyLong_FromUnsignedLongLong(value);
|
||||
if (!value_obj) {
|
||||
Py_DECREF(dict);
|
||||
return NULL;
|
||||
}
|
||||
ret = PyDict_SetItemString(dict, drgn_register_name(reg),
|
||||
value_obj);
|
||||
Py_DECREF(value_obj);
|
||||
if (ret == -1) {
|
||||
Py_DECREF(dict);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
static PyObject *StackFrame_get_pc(StackFrame *self, void *arg)
|
||||
{
|
||||
return PyLong_FromUnsignedLongLong(drgn_stack_frame_pc(self->frame));
|
||||
@ -111,6 +177,10 @@ static PyObject *StackFrame_get_pc(StackFrame *self, void *arg)
|
||||
static PyMethodDef StackFrame_methods[] = {
|
||||
{"symbol", (PyCFunction)StackFrame_symbol, METH_NOARGS,
|
||||
drgn_StackFrame_symbol_DOC},
|
||||
{"register", (PyCFunction)StackFrame_register,
|
||||
METH_O, drgn_StackFrame_register_DOC},
|
||||
{"registers", (PyCFunction)StackFrame_registers,
|
||||
METH_NOARGS, drgn_StackFrame_registers_DOC},
|
||||
{},
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
// Copyright 2019 - Omar Sandoval
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include <dwarf.h>
|
||||
#include <elfutils/libdwfl.h>
|
||||
#include <endian.h>
|
||||
#include <inttypes.h>
|
||||
@ -110,6 +111,34 @@ drgn_stack_frame_symbol(struct drgn_stack_frame frame, struct drgn_symbol **ret)
|
||||
ret);
|
||||
}
|
||||
|
||||
LIBDRGN_PUBLIC struct drgn_error *
|
||||
drgn_stack_frame_register(struct drgn_stack_frame frame,
|
||||
enum drgn_register_number regno, uint64_t *ret)
|
||||
{
|
||||
const Dwarf_Op op = { .atom = DW_OP_regx, .number = regno, };
|
||||
Dwarf_Addr value;
|
||||
|
||||
if (!dwfl_frame_eval_expr(frame.trace->frames[frame.i], &op, 1, &value))
|
||||
return drgn_error_libdwfl();
|
||||
*ret = value;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LIBDRGN_PUBLIC struct drgn_error *
|
||||
drgn_stack_frame_register_by_name(struct drgn_stack_frame frame,
|
||||
const char *name, uint64_t *ret)
|
||||
{
|
||||
const struct drgn_register *reg;
|
||||
|
||||
reg = drgn_architecture_register_by_name(frame.trace->prog->platform.arch,
|
||||
name);
|
||||
if (!reg) {
|
||||
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
||||
"unknown register '%s'", name);
|
||||
}
|
||||
return drgn_stack_frame_register(frame, reg->number, ret);
|
||||
}
|
||||
|
||||
static bool drgn_thread_memory_read(Dwfl *dwfl, Dwarf_Addr addr,
|
||||
Dwarf_Word *result, void *dwfl_arg)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user