mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-22 17:23:06 +00:00
libdrgn: replace symbol index with object index
struct drgn_symbol doesn't really represent a symbol; it's just an
object which hasn't been fully initialized (see c2be52dff0
("libdrgn:
rename object index to symbol index"), it used to be called a "partial
object"). For stack traces, we're going to have a notion of a symbol
that more closely represents an ELF symbol, so let's get rid of the
temporary struct drgn_symbol representation and just return an object
directly.
This commit is contained in:
parent
74bd59e38a
commit
0c5df56fba
@ -201,18 +201,19 @@ Programs
|
|||||||
filename)``. The filename should be matched with
|
filename)``. The filename should be matched with
|
||||||
:func:`filename_matches()`. This should return a :class:`Type`.
|
:func:`filename_matches()`. This should return a :class:`Type`.
|
||||||
|
|
||||||
.. method:: add_symbol_finder(fn)
|
.. method:: add_object_finder(fn)
|
||||||
|
|
||||||
Register a callback for finding symbols in the program.
|
Register a callback for finding objects in the program.
|
||||||
|
|
||||||
Callbacks are called in reverse order of the order they were added
|
Callbacks are called in reverse order of the order they were added
|
||||||
until the symbol is found. So, more recently added callbacks take
|
until the object is found. So, more recently added callbacks take
|
||||||
precedence.
|
precedence.
|
||||||
|
|
||||||
:param fn: Callable taking a name (:class:`str`),
|
:param fn: Callable taking a program (:class:`Program`), name
|
||||||
:class:`FindObjectFlags`, and filename (:class:`str` or ``None``):
|
(:class:`str`), :class:`FindObjectFlags`, and filename
|
||||||
``(name, flags, filename)``. The filename should be matched with
|
(:class:`str` or ``None``): ``(prog, name, flags, filename)``. The
|
||||||
:func:`filename_matches()`. This should return a :class:`Symbol`.
|
filename should be matched with :func:`filename_matches()`. This
|
||||||
|
should return an :class:`Object`.
|
||||||
|
|
||||||
.. method:: set_core_dump(path)
|
.. method:: set_core_dump(path)
|
||||||
|
|
||||||
@ -716,61 +717,6 @@ Objects
|
|||||||
structure or union type
|
structure or union type
|
||||||
:raises LookupError: If the type does not have a member with the given name
|
:raises LookupError: If the type does not have a member with the given name
|
||||||
|
|
||||||
.. class:: Symbol(type, *, value=None, address=None, is_enumerator=False, byteorder=None)
|
|
||||||
|
|
||||||
A ``Symbol`` represents a variable, constant, or function loaded from a
|
|
||||||
program's debugging information. It is returned by a symbol finder (see
|
|
||||||
:meth:`Program.add_symbol_finder()`) and then converted to an
|
|
||||||
:class:`Object`.
|
|
||||||
|
|
||||||
Exactly one of *value*, *address*, or *is_enumerator* must be given. If
|
|
||||||
*value* is given, then the symbol is a constant with the given value. If
|
|
||||||
*address* is given, then the symbol is a variable or function at the given
|
|
||||||
address, and *byteorder* must also be given. If *is_enumerator* is
|
|
||||||
``True``, then the symbol is an enumerator constant; its value will be
|
|
||||||
determined from the given type based on the name that was passed to the
|
|
||||||
symbol finder.
|
|
||||||
|
|
||||||
:param Type type: The type of the symbol.
|
|
||||||
:param value: The constant value of the symbol.
|
|
||||||
:type value: int or float
|
|
||||||
:param int address: The address of the symbol in the program.
|
|
||||||
:param bool is_enumerator: Whether the symbol is an enumerator.
|
|
||||||
:param str byteorder: The byte order of the symbol. This is only valid for
|
|
||||||
non-constants. It should be ``'little'`` or ``'big'``.
|
|
||||||
|
|
||||||
.. attribute:: type
|
|
||||||
|
|
||||||
Type of this symbol
|
|
||||||
|
|
||||||
:vartype: Type
|
|
||||||
|
|
||||||
.. attribute:: value
|
|
||||||
|
|
||||||
Value of this symbol if it is a constant, ``None`` otherwise.
|
|
||||||
|
|
||||||
:vartype: int, float, or None
|
|
||||||
|
|
||||||
.. attribute:: address
|
|
||||||
|
|
||||||
Address of this symbol if it is a variable or function, ``None``
|
|
||||||
otherwise.
|
|
||||||
|
|
||||||
:vartype: int or None
|
|
||||||
|
|
||||||
.. attribute:: is_enumerator
|
|
||||||
|
|
||||||
Whether this symbol is an enumerator.
|
|
||||||
|
|
||||||
:vartype: bool
|
|
||||||
|
|
||||||
.. attribute:: byteorder
|
|
||||||
|
|
||||||
Byte order of this symbol (either ``'little'`` or ``'big'``) if it is a
|
|
||||||
variable or function, ``None`` otherwise.
|
|
||||||
|
|
||||||
:vartype: str or None
|
|
||||||
|
|
||||||
.. _api-reference-types:
|
.. _api-reference-types:
|
||||||
|
|
||||||
Types
|
Types
|
||||||
|
@ -55,7 +55,6 @@ from _drgn import (
|
|||||||
Program,
|
Program,
|
||||||
ProgramFlags,
|
ProgramFlags,
|
||||||
Qualifiers,
|
Qualifiers,
|
||||||
Symbol,
|
|
||||||
Type,
|
Type,
|
||||||
TypeKind,
|
TypeKind,
|
||||||
__version__,
|
__version__,
|
||||||
@ -93,7 +92,6 @@ __all__ = [
|
|||||||
'Program',
|
'Program',
|
||||||
'ProgramFlags',
|
'ProgramFlags',
|
||||||
'Qualifiers',
|
'Qualifiers',
|
||||||
'Symbol',
|
|
||||||
'Type',
|
'Type',
|
||||||
'TypeKind',
|
'TypeKind',
|
||||||
'array_type',
|
'array_type',
|
||||||
|
@ -28,6 +28,8 @@ libdrgnimpl_la_SOURCES = binary_search_tree.h \
|
|||||||
memory_reader.h \
|
memory_reader.h \
|
||||||
object.c \
|
object.c \
|
||||||
object.h \
|
object.h \
|
||||||
|
object_index.c \
|
||||||
|
object_index.h \
|
||||||
path.c \
|
path.c \
|
||||||
program.c \
|
program.c \
|
||||||
program.h \
|
program.h \
|
||||||
@ -38,8 +40,6 @@ libdrgnimpl_la_SOURCES = binary_search_tree.h \
|
|||||||
splay_tree.c \
|
splay_tree.c \
|
||||||
string_builder.c \
|
string_builder.c \
|
||||||
string_builder.h \
|
string_builder.h \
|
||||||
symbol_index.c \
|
|
||||||
symbol_index.h \
|
|
||||||
type.c \
|
type.c \
|
||||||
type.h \
|
type.h \
|
||||||
type_index.c \
|
type_index.c \
|
||||||
@ -70,7 +70,6 @@ _drgn_la_SOURCES = python/docstrings.h \
|
|||||||
python/module.c \
|
python/module.c \
|
||||||
python/object.c \
|
python/object.c \
|
||||||
python/program.c \
|
python/program.c \
|
||||||
python/symbol.c \
|
|
||||||
python/test.c \
|
python/test.c \
|
||||||
python/type.c \
|
python/type.c \
|
||||||
python/util.c
|
python/util.c
|
||||||
|
@ -127,7 +127,7 @@ extern struct drgn_error drgn_enomem;
|
|||||||
* Non-fatal lookup @ref drgn_error.
|
* Non-fatal lookup @ref drgn_error.
|
||||||
*
|
*
|
||||||
* This has a code of @ref DRGN_ERROR_LOOKUP. It should be returned from a @ref
|
* This has a code of @ref DRGN_ERROR_LOOKUP. It should be returned from a @ref
|
||||||
* drgn_type_find_fn() or @ref drgn_symbol_find_fn() to indicate that the entity
|
* drgn_type_find_fn() or @ref drgn_object_find_fn() to indicate that the entity
|
||||||
* in question could not be found. It does not need to be passed to @ref
|
* in question could not be found. It does not need to be passed to @ref
|
||||||
* drgn_error_destroy() (but it can be).
|
* drgn_error_destroy() (but it can be).
|
||||||
*/
|
*/
|
||||||
@ -1019,93 +1019,38 @@ enum drgn_find_object_flags {
|
|||||||
DRGN_FIND_OBJECT_ANY = (1 << 3) - 1,
|
DRGN_FIND_OBJECT_ANY = (1 << 3) - 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Kind of symbol. */
|
|
||||||
enum drgn_symbol_kind {
|
|
||||||
/**
|
|
||||||
* A symbol with an address in the program. @ref drgn_symbol::address is
|
|
||||||
* set to the address.
|
|
||||||
*/
|
|
||||||
DRGN_SYMBOL_ADDRESS,
|
|
||||||
/**
|
|
||||||
* A symbol with a constant value. One of @ref drgn_symbol::svalue, @ref
|
|
||||||
* drgn_symbol::uvalue, or @ref drgn_symbol::fvalue is set, depending on
|
|
||||||
* @ref drgn_symbol::type.
|
|
||||||
*/
|
|
||||||
DRGN_SYMBOL_CONSTANT,
|
|
||||||
/**
|
|
||||||
* An enumerator. No address or value is set.
|
|
||||||
*
|
|
||||||
* A symbol with this kind may be returned by a @ref
|
|
||||||
* drgn_symbol_find_fn(); it is converted to a constant.
|
|
||||||
*/
|
|
||||||
DRGN_SYMBOL_ENUMERATOR,
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An indexed symbol in a program.
|
* Callback for finding an object.
|
||||||
*
|
*
|
||||||
* This is the result of a lookup by a @ref drgn_symbol_find_fn. It is typically
|
* @param[in] name Name of object. This is @em not null-terminated.
|
||||||
* converted to a @ref drgn_object.
|
|
||||||
*/
|
|
||||||
struct drgn_symbol {
|
|
||||||
/** Type of this symbol. */
|
|
||||||
struct drgn_type *type;
|
|
||||||
/** Qualifiers on @ref drgn_symbol::type. */
|
|
||||||
enum drgn_qualifiers qualifiers;
|
|
||||||
/** Kind of this symbol. */
|
|
||||||
enum drgn_symbol_kind kind;
|
|
||||||
/**
|
|
||||||
* Whether the symbol is little-endian.
|
|
||||||
*
|
|
||||||
* This is ignored for constants and enumerators.
|
|
||||||
*/
|
|
||||||
bool little_endian;
|
|
||||||
union {
|
|
||||||
/**
|
|
||||||
* If not a constant or enumerator, the address of the symbol.
|
|
||||||
*/
|
|
||||||
uint64_t address;
|
|
||||||
/** If a signed constant, the value. */
|
|
||||||
int64_t svalue;
|
|
||||||
/** If an unsigned constant, the value. */
|
|
||||||
uint64_t uvalue;
|
|
||||||
/** If a floating-point constant, the value. */
|
|
||||||
double fvalue;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Callback for finding a symbol.
|
|
||||||
*
|
|
||||||
* @param[in] name Name of symbol. This is @em not null-terminated.
|
|
||||||
* @param[in] name_len Length of @p name.
|
* @param[in] name_len Length of @p name.
|
||||||
* @param[in] filename Filename containing the symbol definition or @c NULL.
|
* @param[in] filename Filename containing the object definition or @c NULL.
|
||||||
* This should be matched with @ref drgn_filename_matches().
|
* This should be matched with @ref drgn_filename_matches().
|
||||||
* @param[in] flags Flags indicating what kind of object to look for.
|
* @param[in] flags Flags indicating what kind of object to look for.
|
||||||
* @param[in] arg Argument passed to @ref drgn_program_add_symbol_finder().
|
* @param[in] arg Argument passed to @ref drgn_program_add_object_finder().
|
||||||
* @param[out] ret Returned symbol.
|
* @param[out] ret Returned object. This must only be modified on success.
|
||||||
* @return @c NULL on success, non-@c NULL on error. In particular, if the
|
* @return @c NULL on success, non-@c NULL on error. In particular, if the
|
||||||
* symbol is not found, this should return &@ref drgn_not_found; any other
|
* object is not found, this should return &@ref drgn_not_found; any other
|
||||||
* errors are considered fatal.
|
* errors are considered fatal.
|
||||||
*/
|
*/
|
||||||
typedef struct drgn_error *
|
typedef struct drgn_error *
|
||||||
(*drgn_symbol_find_fn)(const char *name, size_t name_len, const char *filename,
|
(*drgn_object_find_fn)(const char *name, size_t name_len, const char *filename,
|
||||||
enum drgn_find_object_flags flags, void *arg,
|
enum drgn_find_object_flags flags, void *arg,
|
||||||
struct drgn_symbol *ret);
|
struct drgn_object *ret);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a symbol finding callback.
|
* Register a object finding callback.
|
||||||
*
|
*
|
||||||
* Callbacks are called in reverse order of the order they were added until the
|
* Callbacks are called in reverse order of the order they were added until the
|
||||||
* symbol is found. So, more recently added callbacks take precedence.
|
* object is found. So, more recently added callbacks take precedence.
|
||||||
*
|
*
|
||||||
* @param[in] fn The callback.
|
* @param[in] fn The callback.
|
||||||
* @param[in] arg Argument to pass to @p fn.
|
* @param[in] arg Argument to pass to @p fn.
|
||||||
* @return @c NULL on success, non-@c NULL on error.
|
* @return @c NULL on success, non-@c NULL on error.
|
||||||
*/
|
*/
|
||||||
struct drgn_error *
|
struct drgn_error *
|
||||||
drgn_program_add_symbol_finder(struct drgn_program *prog,
|
drgn_program_add_object_finder(struct drgn_program *prog,
|
||||||
drgn_symbol_find_fn fn, void *arg);
|
drgn_object_find_fn fn, void *arg);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a @ref drgn_program to a core dump.
|
* Set a @ref drgn_program to a core dump.
|
||||||
@ -1250,9 +1195,8 @@ struct drgn_error *drgn_program_find_type(struct drgn_program *prog,
|
|||||||
* matched with @ref drgn_filename_matches(). If multiple definitions match, one
|
* matched with @ref drgn_filename_matches(). If multiple definitions match, one
|
||||||
* is returned arbitrarily.
|
* is returned arbitrarily.
|
||||||
* @param[in] flags Flags indicating what kind of object to look for.
|
* @param[in] flags Flags indicating what kind of object to look for.
|
||||||
* @param[out] ret Returned object. This can be @c NULL to check for the
|
* @param[out] ret Returned object. This must have already been initialized with
|
||||||
* object's existence without returning it. If not @c NULL, this must have
|
* @ref drgn_object_init().
|
||||||
* already been initialized with @ref drgn_object_init().
|
|
||||||
* @return @c NULL on success, non-@c NULL on error.
|
* @return @c NULL on success, non-@c NULL on error.
|
||||||
*/
|
*/
|
||||||
struct drgn_error *drgn_program_find_object(struct drgn_program *prog,
|
struct drgn_error *drgn_program_find_object(struct drgn_program *prog,
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include "dwarf_index.h"
|
#include "dwarf_index.h"
|
||||||
#include "dwarf_info_cache.h"
|
#include "dwarf_info_cache.h"
|
||||||
#include "hash_table.h"
|
#include "hash_table.h"
|
||||||
#include "symbol_index.h"
|
#include "object_index.h"
|
||||||
#include "type_index.h"
|
#include "type_index.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
@ -1406,9 +1406,40 @@ struct drgn_error *drgn_dwarf_type_find(enum drgn_type_kind kind,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct drgn_error *
|
static struct drgn_error *
|
||||||
drgn_symbol_from_dwarf_subprogram(struct drgn_dwarf_info_cache *dicache,
|
drgn_object_from_dwarf_enumerator(struct drgn_dwarf_info_cache *dicache,
|
||||||
|
Dwarf_Die *die, const char *name,
|
||||||
|
struct drgn_object *ret)
|
||||||
|
{
|
||||||
|
struct drgn_error *err;
|
||||||
|
struct drgn_qualified_type qualified_type;
|
||||||
|
const struct drgn_type_enumerator *enumerators;
|
||||||
|
size_t num_enumerators, i;
|
||||||
|
|
||||||
|
err = drgn_type_from_dwarf(dicache, die, &qualified_type);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
enumerators = drgn_type_enumerators(qualified_type.type);
|
||||||
|
num_enumerators = drgn_type_num_enumerators(qualified_type.type);
|
||||||
|
for (i = 0; i < num_enumerators; i++) {
|
||||||
|
if (strcmp(enumerators[i].name, name) != 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (drgn_enum_type_is_signed(qualified_type.type)) {
|
||||||
|
return drgn_object_set_signed(ret, qualified_type,
|
||||||
|
enumerators[i].svalue, 0);
|
||||||
|
} else {
|
||||||
|
return drgn_object_set_unsigned(ret, qualified_type,
|
||||||
|
enumerators[i].uvalue,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DRGN_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct drgn_error *
|
||||||
|
drgn_object_from_dwarf_subprogram(struct drgn_dwarf_info_cache *dicache,
|
||||||
Dwarf_Die *die, uint64_t bias,
|
Dwarf_Die *die, uint64_t bias,
|
||||||
const char *name, struct drgn_symbol *ret)
|
const char *name, struct drgn_object *ret)
|
||||||
{
|
{
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
struct drgn_qualified_type qualified_type;
|
struct drgn_qualified_type qualified_type;
|
||||||
@ -1417,24 +1448,19 @@ drgn_symbol_from_dwarf_subprogram(struct drgn_dwarf_info_cache *dicache,
|
|||||||
err = drgn_type_from_dwarf(dicache, die, &qualified_type);
|
err = drgn_type_from_dwarf(dicache, die, &qualified_type);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
ret->type = qualified_type.type;
|
|
||||||
ret->qualifiers = qualified_type.qualifiers;
|
|
||||||
|
|
||||||
ret->kind = DRGN_SYMBOL_ADDRESS;
|
|
||||||
if (dwarf_lowpc(die, &low_pc) == -1) {
|
if (dwarf_lowpc(die, &low_pc) == -1) {
|
||||||
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
||||||
"could not find address of '%s'",
|
"could not find address of '%s'",
|
||||||
name);
|
name);
|
||||||
}
|
}
|
||||||
ret->address = low_pc + bias;
|
return drgn_object_set_reference(ret, qualified_type, low_pc + bias, 0,
|
||||||
ret->little_endian = dwarf_die_is_little_endian(die);
|
0, dwarf_die_byte_order(die));
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drgn_error *
|
static struct drgn_error *
|
||||||
drgn_symbol_from_dwarf_variable(struct drgn_dwarf_info_cache *dicache,
|
drgn_object_from_dwarf_variable(struct drgn_dwarf_info_cache *dicache,
|
||||||
Dwarf_Die *die, uint64_t bias, const char *name,
|
Dwarf_Die *die, uint64_t bias, const char *name,
|
||||||
struct drgn_symbol *ret)
|
struct drgn_object *ret)
|
||||||
{
|
{
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
struct drgn_qualified_type qualified_type;
|
struct drgn_qualified_type qualified_type;
|
||||||
@ -1447,10 +1473,6 @@ drgn_symbol_from_dwarf_variable(struct drgn_dwarf_info_cache *dicache,
|
|||||||
&qualified_type);
|
&qualified_type);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
ret->type = qualified_type.type;
|
|
||||||
ret->qualifiers = qualified_type.qualifiers;
|
|
||||||
|
|
||||||
ret->kind = DRGN_SYMBOL_ADDRESS;
|
|
||||||
if (!(attr = dwarf_attr_integrate(die, DW_AT_location, &attr_mem))) {
|
if (!(attr = dwarf_attr_integrate(die, DW_AT_location, &attr_mem))) {
|
||||||
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
||||||
"could not find address of '%s'",
|
"could not find address of '%s'",
|
||||||
@ -1458,20 +1480,19 @@ drgn_symbol_from_dwarf_variable(struct drgn_dwarf_info_cache *dicache,
|
|||||||
}
|
}
|
||||||
if (dwarf_getlocation(attr, &loc, &nloc))
|
if (dwarf_getlocation(attr, &loc, &nloc))
|
||||||
return drgn_error_libdw();
|
return drgn_error_libdw();
|
||||||
|
|
||||||
if (nloc != 1 || loc[0].atom != DW_OP_addr) {
|
if (nloc != 1 || loc[0].atom != DW_OP_addr) {
|
||||||
return drgn_error_create(DRGN_ERROR_DWARF_FORMAT,
|
return drgn_error_create(DRGN_ERROR_DWARF_FORMAT,
|
||||||
"DW_AT_location has unimplemented operation");
|
"DW_AT_location has unimplemented operation");
|
||||||
}
|
}
|
||||||
ret->address = loc[0].number + bias;
|
return drgn_object_set_reference(ret, qualified_type,
|
||||||
ret->little_endian = dwarf_die_is_little_endian(die);
|
loc[0].number + bias, 0, 0,
|
||||||
return NULL;
|
dwarf_die_byte_order(die));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct drgn_error *
|
struct drgn_error *
|
||||||
drgn_dwarf_symbol_find(const char *name, size_t name_len, const char *filename,
|
drgn_dwarf_object_find(const char *name, size_t name_len, const char *filename,
|
||||||
enum drgn_find_object_flags flags, void *arg,
|
enum drgn_find_object_flags flags, void *arg,
|
||||||
struct drgn_symbol *ret)
|
struct drgn_object *ret)
|
||||||
{
|
{
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
struct drgn_dwarf_info_cache *dicache = arg;
|
struct drgn_dwarf_info_cache *dicache = arg;
|
||||||
@ -1495,24 +1516,15 @@ drgn_dwarf_symbol_find(const char *name, size_t name_len, const char *filename,
|
|||||||
if (!die_matches_filename(&die, filename))
|
if (!die_matches_filename(&die, filename))
|
||||||
continue;
|
continue;
|
||||||
switch (dwarf_tag(&die)) {
|
switch (dwarf_tag(&die)) {
|
||||||
case DW_TAG_enumeration_type: {
|
case DW_TAG_enumeration_type:
|
||||||
struct drgn_qualified_type qualified_type;
|
return drgn_object_from_dwarf_enumerator(dicache, &die,
|
||||||
|
name, ret);
|
||||||
ret->kind = DRGN_SYMBOL_ENUMERATOR;
|
|
||||||
err = drgn_type_from_dwarf(dicache, &die,
|
|
||||||
&qualified_type);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
ret->type = qualified_type.type;
|
|
||||||
ret->qualifiers = qualified_type.qualifiers;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
case DW_TAG_subprogram:
|
case DW_TAG_subprogram:
|
||||||
return drgn_symbol_from_dwarf_subprogram(dicache, &die,
|
return drgn_object_from_dwarf_subprogram(dicache, &die,
|
||||||
bias, name,
|
bias, name,
|
||||||
ret);
|
ret);
|
||||||
case DW_TAG_variable:
|
case DW_TAG_variable:
|
||||||
return drgn_symbol_from_dwarf_variable(dicache, &die,
|
return drgn_object_from_dwarf_variable(dicache, &die,
|
||||||
bias, name, ret);
|
bias, name, ret);
|
||||||
default:
|
default:
|
||||||
DRGN_UNREACHABLE();
|
DRGN_UNREACHABLE();
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
*
|
*
|
||||||
* @ref drgn_dwarf_info_cache bridges the raw DWARF information indexed by @ref
|
* @ref drgn_dwarf_info_cache bridges the raw DWARF information indexed by @ref
|
||||||
* drgn_dwarf_index to the higher-level @ref drgn_type_index and @ref
|
* drgn_dwarf_index to the higher-level @ref drgn_type_index and @ref
|
||||||
* drgn_symbol_index.
|
* drgn_object_index.
|
||||||
*
|
*
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
@ -47,14 +47,12 @@ struct drgn_dwarf_type {
|
|||||||
DEFINE_HASH_MAP_TYPE(dwarf_type_map, const void *, struct drgn_dwarf_type);
|
DEFINE_HASH_MAP_TYPE(dwarf_type_map, const void *, struct drgn_dwarf_type);
|
||||||
|
|
||||||
struct drgn_dwarf_index;
|
struct drgn_dwarf_index;
|
||||||
struct drgn_program;
|
|
||||||
struct drgn_symbol;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cache of types and symbols from DWARF debugging information.
|
* Cache of types and objects from DWARF debugging information.
|
||||||
*
|
*
|
||||||
* This is the argument for @ref drgn_dwarf_type_find() and @ref
|
* This is the argument for @ref drgn_dwarf_type_find() and @ref
|
||||||
* drgn_dwarf_symbol_find().
|
* drgn_dwarf_object_find().
|
||||||
*/
|
*/
|
||||||
struct drgn_dwarf_info_cache {
|
struct drgn_dwarf_info_cache {
|
||||||
/** Index of DWARF debugging information. */
|
/** Index of DWARF debugging information. */
|
||||||
@ -93,11 +91,11 @@ struct drgn_error *drgn_dwarf_type_find(enum drgn_type_kind kind,
|
|||||||
const char *filename, void *arg,
|
const char *filename, void *arg,
|
||||||
struct drgn_qualified_type *ret);
|
struct drgn_qualified_type *ret);
|
||||||
|
|
||||||
/** @ref drgn_symbol_find_fn() that uses DWARF debugging information. */
|
/** @ref drgn_object_find_fn() that uses DWARF debugging information. */
|
||||||
struct drgn_error *
|
struct drgn_error *
|
||||||
drgn_dwarf_symbol_find(const char *name, size_t name_len, const char *filename,
|
drgn_dwarf_object_find(const char *name, size_t name_len, const char *filename,
|
||||||
enum drgn_find_object_flags flags, void *arg,
|
enum drgn_find_object_flags flags, void *arg,
|
||||||
struct drgn_symbol *ret);
|
struct drgn_object *ret);
|
||||||
|
|
||||||
/** @} */
|
/** @} */
|
||||||
|
|
||||||
|
@ -202,6 +202,12 @@ static inline bool dwarf_die_is_little_endian(Dwarf_Die *die)
|
|||||||
return elf_is_little_endian(dwarf_getelf(dwarf_cu_getdwarf(die->cu)));
|
return elf_is_little_endian(dwarf_getelf(dwarf_cu_getdwarf(die->cu)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline enum drgn_byte_order dwarf_die_byte_order(Dwarf_Die *die)
|
||||||
|
{
|
||||||
|
return (dwarf_die_is_little_endian(die) ?
|
||||||
|
DRGN_LITTLE_ENDIAN : DRGN_BIG_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
bool die_matches_filename(Dwarf_Die *die, const char *filename);
|
bool die_matches_filename(Dwarf_Die *die, const char *filename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -228,52 +228,49 @@ out:
|
|||||||
}
|
}
|
||||||
|
|
||||||
static struct drgn_error *
|
static struct drgn_error *
|
||||||
vmcoreinfo_symbol_find(const char *name, size_t name_len, const char *filename,
|
vmcoreinfo_object_find(const char *name, size_t name_len, const char *filename,
|
||||||
enum drgn_find_object_flags flags, void *arg,
|
enum drgn_find_object_flags flags, void *arg,
|
||||||
struct drgn_symbol *ret)
|
struct drgn_object *ret)
|
||||||
{
|
{
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
struct drgn_program *prog = arg;
|
struct drgn_program *prog = arg;
|
||||||
|
|
||||||
if (filename)
|
if (!filename && (flags & DRGN_FIND_OBJECT_CONSTANT)) {
|
||||||
goto not_found;
|
struct drgn_qualified_type qualified_type = {};
|
||||||
|
|
||||||
if (flags & DRGN_FIND_OBJECT_CONSTANT) {
|
|
||||||
if (name_len == strlen("PAGE_SHIFT") &&
|
if (name_len == strlen("PAGE_SHIFT") &&
|
||||||
memcmp(name, "PAGE_SHIFT", name_len) == 0) {
|
memcmp(name, "PAGE_SHIFT", name_len) == 0) {
|
||||||
err = drgn_type_index_find_primitive(&prog->tindex,
|
err = drgn_type_index_find_primitive(&prog->tindex,
|
||||||
DRGN_C_TYPE_INT,
|
DRGN_C_TYPE_INT,
|
||||||
&ret->type);
|
&qualified_type.type);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
ret->svalue = ctz(prog->vmcoreinfo.page_size);
|
return drgn_object_set_signed(ret, qualified_type,
|
||||||
|
ctz(prog->vmcoreinfo.page_size),
|
||||||
|
0);
|
||||||
} else if (name_len == strlen("PAGE_SIZE") &&
|
} else if (name_len == strlen("PAGE_SIZE") &&
|
||||||
memcmp(name, "PAGE_SIZE", name_len) == 0) {
|
memcmp(name, "PAGE_SIZE", name_len) == 0) {
|
||||||
err = drgn_type_index_find_primitive(&prog->tindex,
|
err = drgn_type_index_find_primitive(&prog->tindex,
|
||||||
DRGN_C_TYPE_UNSIGNED_LONG,
|
DRGN_C_TYPE_UNSIGNED_LONG,
|
||||||
&ret->type);
|
&qualified_type.type);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
ret->uvalue = prog->vmcoreinfo.page_size;
|
return drgn_object_set_unsigned(ret, qualified_type,
|
||||||
|
prog->vmcoreinfo.page_size,
|
||||||
|
0);
|
||||||
} else if (name_len == strlen("PAGE_MASK") &&
|
} else if (name_len == strlen("PAGE_MASK") &&
|
||||||
memcmp(name, "PAGE_MASK", name_len) == 0) {
|
memcmp(name, "PAGE_MASK", name_len) == 0) {
|
||||||
err = drgn_type_index_find_primitive(&prog->tindex,
|
err = drgn_type_index_find_primitive(&prog->tindex,
|
||||||
DRGN_C_TYPE_UNSIGNED_LONG,
|
DRGN_C_TYPE_UNSIGNED_LONG,
|
||||||
&ret->type);
|
&qualified_type.type);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
ret->uvalue = ~(prog->vmcoreinfo.page_size - 1);
|
return drgn_object_set_unsigned(ret, qualified_type,
|
||||||
} else {
|
~(prog->vmcoreinfo.page_size - 1),
|
||||||
goto not_found;
|
0);
|
||||||
}
|
}
|
||||||
ret->qualifiers = 0;
|
|
||||||
ret->kind = DRGN_SYMBOL_CONSTANT;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
return &drgn_not_found;
|
||||||
not_found:
|
|
||||||
ret->type = NULL;
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct kernel_module_iterator {
|
struct kernel_module_iterator {
|
||||||
@ -1598,13 +1595,13 @@ linux_kernel_load_default_debug_info(struct drgn_program *prog)
|
|||||||
{
|
{
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
|
|
||||||
if (!prog->added_vmcoreinfo_symbol_finder) {
|
if (!prog->added_vmcoreinfo_object_finder) {
|
||||||
err = drgn_program_add_symbol_finder(prog,
|
err = drgn_program_add_object_finder(prog,
|
||||||
vmcoreinfo_symbol_find,
|
vmcoreinfo_object_find,
|
||||||
prog);
|
prog);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
prog->added_vmcoreinfo_symbol_finder = true;
|
prog->added_vmcoreinfo_object_finder = true;
|
||||||
}
|
}
|
||||||
return linux_kernel_load_debug_info_internal(prog, NULL, 0, 0, true);
|
return linux_kernel_load_debug_info_internal(prog, NULL, 0, 0, true);
|
||||||
}
|
}
|
||||||
|
93
libdrgn/object_index.c
Normal file
93
libdrgn/object_index.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
// Copyright 2018-2019 - Omar Sandoval
|
||||||
|
// SPDX-License-Identifier: GPL-3.0+
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
#include "object_index.h"
|
||||||
|
#include "type.h"
|
||||||
|
|
||||||
|
void drgn_object_index_init(struct drgn_object_index *oindex)
|
||||||
|
{
|
||||||
|
oindex->finders = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drgn_object_index_deinit(struct drgn_object_index *oindex)
|
||||||
|
{
|
||||||
|
struct drgn_object_finder *finder;
|
||||||
|
|
||||||
|
finder = oindex->finders;
|
||||||
|
while (finder) {
|
||||||
|
struct drgn_object_finder *next = finder->next;
|
||||||
|
|
||||||
|
free(finder);
|
||||||
|
finder = next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drgn_error *
|
||||||
|
drgn_object_index_add_finder(struct drgn_object_index *oindex,
|
||||||
|
drgn_object_find_fn fn, void *arg)
|
||||||
|
{
|
||||||
|
struct drgn_object_finder *finder;
|
||||||
|
|
||||||
|
finder = malloc(sizeof(*finder));
|
||||||
|
if (!finder)
|
||||||
|
return &drgn_enomem;
|
||||||
|
finder->fn = fn;
|
||||||
|
finder->arg = arg;
|
||||||
|
finder->next = oindex->finders;
|
||||||
|
oindex->finders = finder;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct drgn_error *drgn_object_index_find(struct drgn_object_index *oindex,
|
||||||
|
const char *name,
|
||||||
|
const char *filename,
|
||||||
|
enum drgn_find_object_flags flags,
|
||||||
|
struct drgn_object *ret)
|
||||||
|
{
|
||||||
|
struct drgn_error *err;
|
||||||
|
size_t name_len;
|
||||||
|
struct drgn_object_finder *finder;
|
||||||
|
const char *kind_str;
|
||||||
|
|
||||||
|
if ((flags & ~DRGN_FIND_OBJECT_ANY) || !flags) {
|
||||||
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
||||||
|
"invalid find object flags");
|
||||||
|
}
|
||||||
|
|
||||||
|
name_len = strlen(name);
|
||||||
|
finder = oindex->finders;
|
||||||
|
while (finder) {
|
||||||
|
err = finder->fn(name, name_len, filename, flags, finder->arg,
|
||||||
|
ret);
|
||||||
|
if (err != &drgn_not_found)
|
||||||
|
return err;
|
||||||
|
finder = finder->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (flags) {
|
||||||
|
case DRGN_FIND_OBJECT_CONSTANT:
|
||||||
|
kind_str = "constant ";
|
||||||
|
break;
|
||||||
|
case DRGN_FIND_OBJECT_FUNCTION:
|
||||||
|
kind_str = "function ";
|
||||||
|
break;
|
||||||
|
case DRGN_FIND_OBJECT_VARIABLE:
|
||||||
|
kind_str = "variable ";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
kind_str = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (filename) {
|
||||||
|
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
||||||
|
"could not find %s'%s' in '%s'",
|
||||||
|
kind_str, name, filename);
|
||||||
|
} else {
|
||||||
|
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
||||||
|
"could not find %s'%s'", kind_str,
|
||||||
|
name);
|
||||||
|
}
|
||||||
|
}
|
83
libdrgn/object_index.h
Normal file
83
libdrgn/object_index.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// Copyright 2018-2019 - Omar Sandoval
|
||||||
|
// SPDX-License-Identifier: GPL-3.0+
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* Object lookup.
|
||||||
|
*
|
||||||
|
* See @ref ObjectIndex.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DRGN_OBJECT_INDEX_H
|
||||||
|
#define DRGN_OBJECT_INDEX_H
|
||||||
|
|
||||||
|
#include "drgn.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup Internals
|
||||||
|
*
|
||||||
|
* @defgroup ObjectIndex Object index
|
||||||
|
*
|
||||||
|
* Object lookup.
|
||||||
|
*
|
||||||
|
* @ref drgn_object_index provides a common interface for finding objects (e.g.,
|
||||||
|
* variables, constants, and functions) in a program.
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** Registered callback in a @ref drgn_object_index. */
|
||||||
|
struct drgn_object_finder {
|
||||||
|
/** The callback. */
|
||||||
|
drgn_object_find_fn fn;
|
||||||
|
/** Argument to pass to @ref drgn_object_finder::fn. */
|
||||||
|
void *arg;
|
||||||
|
/** Next callback to try. */
|
||||||
|
struct drgn_object_finder *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Object index.
|
||||||
|
*
|
||||||
|
* A object index is used to find objects (variables, constants, and functions)
|
||||||
|
* by name. The types are found using callbacks which are registered with @ref
|
||||||
|
* drgn_object_index_add_finder(). @ref drgn_object_index_find() searches for an
|
||||||
|
* object.
|
||||||
|
*/
|
||||||
|
struct drgn_object_index {
|
||||||
|
/** Callbacks for finding objects. */
|
||||||
|
struct drgn_object_finder *finders;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Initialize a @ref drgn_object_index. */
|
||||||
|
void drgn_object_index_init(struct drgn_object_index *oindex);
|
||||||
|
|
||||||
|
/** Deinitialize a @ref drgn_object_index. */
|
||||||
|
void drgn_object_index_deinit(struct drgn_object_index *oindex);
|
||||||
|
|
||||||
|
/** @sa drgn_program_add_object_finder() */
|
||||||
|
struct drgn_error *
|
||||||
|
drgn_object_index_add_finder(struct drgn_object_index *oindex,
|
||||||
|
drgn_object_find_fn fn, void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find an object in a @ref drgn_object_index.
|
||||||
|
*
|
||||||
|
* @param[in] oindex Object index.
|
||||||
|
* @param[in] name Name of the object.
|
||||||
|
* @param[in] filename Exact filename containing the object definition, or @c
|
||||||
|
* NULL for any definition.
|
||||||
|
* @param[in] flags Bitmask of @ref drgn_find_object_flags.
|
||||||
|
* @param[out] ret Returned object.
|
||||||
|
* @return @c NULL on success, non-@c NULL on error.
|
||||||
|
*/
|
||||||
|
struct drgn_error *drgn_object_index_find(struct drgn_object_index *oindex,
|
||||||
|
const char *name,
|
||||||
|
const char *filename,
|
||||||
|
enum drgn_find_object_flags flags,
|
||||||
|
struct drgn_object *ret);
|
||||||
|
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
#endif /* DRGN_OBJECT_INDEX_H */
|
@ -19,10 +19,10 @@
|
|||||||
#include "language.h"
|
#include "language.h"
|
||||||
#include "linux_kernel.h"
|
#include "linux_kernel.h"
|
||||||
#include "memory_reader.h"
|
#include "memory_reader.h"
|
||||||
|
#include "object_index.h"
|
||||||
#include "program.h"
|
#include "program.h"
|
||||||
#include "read.h"
|
#include "read.h"
|
||||||
#include "string_builder.h"
|
#include "string_builder.h"
|
||||||
#include "symbol_index.h"
|
|
||||||
#include "type_index.h"
|
#include "type_index.h"
|
||||||
#include "vector.h"
|
#include "vector.h"
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ void drgn_program_init(struct drgn_program *prog,
|
|||||||
memset(prog, 0, sizeof(*prog));
|
memset(prog, 0, sizeof(*prog));
|
||||||
drgn_memory_reader_init(&prog->reader);
|
drgn_memory_reader_init(&prog->reader);
|
||||||
drgn_type_index_init(&prog->tindex);
|
drgn_type_index_init(&prog->tindex);
|
||||||
drgn_symbol_index_init(&prog->sindex);
|
drgn_object_index_init(&prog->oindex);
|
||||||
prog->core_fd = -1;
|
prog->core_fd = -1;
|
||||||
prog->arch = DRGN_ARCH_AUTO;
|
prog->arch = DRGN_ARCH_AUTO;
|
||||||
if (arch != DRGN_ARCH_AUTO)
|
if (arch != DRGN_ARCH_AUTO)
|
||||||
@ -77,7 +77,7 @@ void drgn_program_init(struct drgn_program *prog,
|
|||||||
|
|
||||||
void drgn_program_deinit(struct drgn_program *prog)
|
void drgn_program_deinit(struct drgn_program *prog)
|
||||||
{
|
{
|
||||||
drgn_symbol_index_deinit(&prog->sindex);
|
drgn_object_index_deinit(&prog->oindex);
|
||||||
drgn_type_index_deinit(&prog->tindex);
|
drgn_type_index_deinit(&prog->tindex);
|
||||||
drgn_memory_reader_deinit(&prog->reader);
|
drgn_memory_reader_deinit(&prog->reader);
|
||||||
|
|
||||||
@ -136,10 +136,10 @@ drgn_program_add_type_finder(struct drgn_program *prog, drgn_type_find_fn fn,
|
|||||||
}
|
}
|
||||||
|
|
||||||
LIBDRGN_PUBLIC struct drgn_error *
|
LIBDRGN_PUBLIC struct drgn_error *
|
||||||
drgn_program_add_symbol_finder(struct drgn_program *prog,
|
drgn_program_add_object_finder(struct drgn_program *prog,
|
||||||
drgn_symbol_find_fn fn, void *arg)
|
drgn_object_find_fn fn, void *arg)
|
||||||
{
|
{
|
||||||
return drgn_symbol_index_add_finder(&prog->sindex, fn, arg);
|
return drgn_object_index_add_finder(&prog->oindex, fn, arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static enum drgn_architecture_flags drgn_architecture_from_elf(Elf *elf)
|
static enum drgn_architecture_flags drgn_architecture_from_elf(Elf *elf)
|
||||||
@ -484,8 +484,8 @@ struct drgn_error *drgn_program_update_dwarf_index(struct drgn_program *prog)
|
|||||||
drgn_dwarf_info_cache_destroy(dicache);
|
drgn_dwarf_info_cache_destroy(dicache);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
err = drgn_program_add_symbol_finder(prog,
|
err = drgn_program_add_object_finder(prog,
|
||||||
drgn_dwarf_symbol_find,
|
drgn_dwarf_object_find,
|
||||||
dicache);
|
dicache);
|
||||||
if (err) {
|
if (err) {
|
||||||
drgn_type_index_remove_finder(&prog->tindex);
|
drgn_type_index_remove_finder(&prog->tindex);
|
||||||
@ -753,42 +753,12 @@ drgn_program_find_object(struct drgn_program *prog, const char *name,
|
|||||||
enum drgn_find_object_flags flags,
|
enum drgn_find_object_flags flags,
|
||||||
struct drgn_object *ret)
|
struct drgn_object *ret)
|
||||||
{
|
{
|
||||||
struct drgn_error *err;
|
|
||||||
struct drgn_symbol sym;
|
|
||||||
struct drgn_qualified_type qualified_type;
|
|
||||||
|
|
||||||
if (ret && ret->prog != prog) {
|
if (ret && ret->prog != prog) {
|
||||||
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
||||||
"object is from wrong program");
|
"object is from wrong program");
|
||||||
}
|
}
|
||||||
|
return drgn_object_index_find(&prog->oindex, name, filename, flags,
|
||||||
err = drgn_symbol_index_find(&prog->sindex, name, filename, flags,
|
ret);
|
||||||
&sym);
|
|
||||||
if (err || !ret)
|
|
||||||
return err;
|
|
||||||
qualified_type.type = sym.type;
|
|
||||||
qualified_type.qualifiers = sym.qualifiers;
|
|
||||||
if (sym.kind == DRGN_SYMBOL_CONSTANT) {
|
|
||||||
switch (drgn_type_object_kind(sym.type)) {
|
|
||||||
case DRGN_OBJECT_SIGNED:
|
|
||||||
return drgn_object_set_signed(ret, qualified_type,
|
|
||||||
sym.svalue, 0);
|
|
||||||
case DRGN_OBJECT_UNSIGNED:
|
|
||||||
return drgn_object_set_unsigned(ret, qualified_type,
|
|
||||||
sym.uvalue, 0);
|
|
||||||
case DRGN_OBJECT_FLOAT:
|
|
||||||
return drgn_object_set_float(ret, qualified_type,
|
|
||||||
sym.fvalue);
|
|
||||||
default:
|
|
||||||
return drgn_type_error("cannot create '%s' constant",
|
|
||||||
sym.type);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
assert(sym.kind == DRGN_SYMBOL_ADDRESS);
|
|
||||||
return drgn_object_set_reference(ret, qualified_type,
|
|
||||||
sym.address, 0, 0,
|
|
||||||
sym.little_endian);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LIBDRGN_PUBLIC struct drgn_error *
|
LIBDRGN_PUBLIC struct drgn_error *
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
#include <elfutils/libdwfl.h>
|
#include <elfutils/libdwfl.h>
|
||||||
|
|
||||||
#include "memory_reader.h"
|
#include "memory_reader.h"
|
||||||
#include "symbol_index.h"
|
#include "object_index.h"
|
||||||
#include "type_index.h"
|
#include "type_index.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,7 +51,7 @@ struct drgn_program {
|
|||||||
/** @privatesection */
|
/** @privatesection */
|
||||||
struct drgn_memory_reader reader;
|
struct drgn_memory_reader reader;
|
||||||
struct drgn_type_index tindex;
|
struct drgn_type_index tindex;
|
||||||
struct drgn_symbol_index sindex;
|
struct drgn_object_index oindex;
|
||||||
struct drgn_memory_file_segment *file_segments;
|
struct drgn_memory_file_segment *file_segments;
|
||||||
size_t num_file_segments;
|
size_t num_file_segments;
|
||||||
/*
|
/*
|
||||||
@ -69,7 +69,7 @@ struct drgn_program {
|
|||||||
int core_fd;
|
int core_fd;
|
||||||
enum drgn_program_flags flags;
|
enum drgn_program_flags flags;
|
||||||
enum drgn_architecture_flags arch;
|
enum drgn_architecture_flags arch;
|
||||||
bool added_vmcoreinfo_symbol_finder;
|
bool added_vmcoreinfo_object_finder;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Initialize a @ref drgn_program. */
|
/** Initialize a @ref drgn_program. */
|
||||||
|
@ -113,8 +113,8 @@ extern const char drgn_Program___getitem___DOC[];
|
|||||||
#define drgn_Program___getitem___DOC (char *)drgn_Program___getitem___DOC
|
#define drgn_Program___getitem___DOC (char *)drgn_Program___getitem___DOC
|
||||||
extern const char drgn_Program_add_memory_segment_DOC[];
|
extern const char drgn_Program_add_memory_segment_DOC[];
|
||||||
#define drgn_Program_add_memory_segment_DOC (char *)drgn_Program_add_memory_segment_DOC
|
#define drgn_Program_add_memory_segment_DOC (char *)drgn_Program_add_memory_segment_DOC
|
||||||
extern const char drgn_Program_add_symbol_finder_DOC[];
|
extern const char drgn_Program_add_object_finder_DOC[];
|
||||||
#define drgn_Program_add_symbol_finder_DOC (char *)drgn_Program_add_symbol_finder_DOC
|
#define drgn_Program_add_object_finder_DOC (char *)drgn_Program_add_object_finder_DOC
|
||||||
extern const char drgn_Program_add_type_finder_DOC[];
|
extern const char drgn_Program_add_type_finder_DOC[];
|
||||||
#define drgn_Program_add_type_finder_DOC (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[];
|
extern const char drgn_Program_arch_DOC[];
|
||||||
@ -163,18 +163,6 @@ extern const char drgn_Qualifiers_RESTRICT_DOC[];
|
|||||||
#define drgn_Qualifiers_RESTRICT_DOC (char *)drgn_Qualifiers_RESTRICT_DOC
|
#define drgn_Qualifiers_RESTRICT_DOC (char *)drgn_Qualifiers_RESTRICT_DOC
|
||||||
extern const char drgn_Qualifiers_VOLATILE_DOC[];
|
extern const char drgn_Qualifiers_VOLATILE_DOC[];
|
||||||
#define drgn_Qualifiers_VOLATILE_DOC (char *)drgn_Qualifiers_VOLATILE_DOC
|
#define drgn_Qualifiers_VOLATILE_DOC (char *)drgn_Qualifiers_VOLATILE_DOC
|
||||||
extern const char drgn_Symbol_DOC[];
|
|
||||||
#define drgn_Symbol_DOC (char *)drgn_Symbol_DOC
|
|
||||||
extern const char drgn_Symbol_address_DOC[];
|
|
||||||
#define drgn_Symbol_address_DOC (char *)drgn_Symbol_address_DOC
|
|
||||||
extern const char drgn_Symbol_byteorder_DOC[];
|
|
||||||
#define drgn_Symbol_byteorder_DOC (char *)drgn_Symbol_byteorder_DOC
|
|
||||||
extern const char drgn_Symbol_is_enumerator_DOC[];
|
|
||||||
#define drgn_Symbol_is_enumerator_DOC (char *)drgn_Symbol_is_enumerator_DOC
|
|
||||||
extern const char drgn_Symbol_type_DOC[];
|
|
||||||
#define drgn_Symbol_type_DOC (char *)drgn_Symbol_type_DOC
|
|
||||||
extern const char drgn_Symbol_value_DOC[];
|
|
||||||
#define drgn_Symbol_value_DOC (char *)drgn_Symbol_value_DOC
|
|
||||||
extern const char drgn_Type_DOC[];
|
extern const char drgn_Type_DOC[];
|
||||||
#define drgn_Type_DOC (char *)drgn_Type_DOC
|
#define drgn_Type_DOC (char *)drgn_Type_DOC
|
||||||
extern const char drgn_Type_enumerators_DOC[];
|
extern const char drgn_Type_enumerators_DOC[];
|
||||||
|
@ -78,12 +78,6 @@ typedef struct {
|
|||||||
PyObject *cache;
|
PyObject *cache;
|
||||||
} Program;
|
} Program;
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
PyObject_HEAD
|
|
||||||
struct drgn_symbol sym;
|
|
||||||
DrgnType *type_obj;
|
|
||||||
} Symbol;
|
|
||||||
|
|
||||||
extern PyObject *Architecture_class;
|
extern PyObject *Architecture_class;
|
||||||
extern PyObject *FindObjectFlags_class;
|
extern PyObject *FindObjectFlags_class;
|
||||||
extern PyObject *PrimitiveType_class;
|
extern PyObject *PrimitiveType_class;
|
||||||
@ -94,7 +88,6 @@ extern PyTypeObject DrgnObject_type;
|
|||||||
extern PyTypeObject DrgnType_type;
|
extern PyTypeObject DrgnType_type;
|
||||||
extern PyTypeObject ObjectIterator_type;
|
extern PyTypeObject ObjectIterator_type;
|
||||||
extern PyTypeObject Program_type;
|
extern PyTypeObject Program_type;
|
||||||
extern PyTypeObject Symbol_type;
|
|
||||||
extern PyObject *FaultError;
|
extern PyObject *FaultError;
|
||||||
extern PyObject *FileFormatError;
|
extern PyObject *FileFormatError;
|
||||||
extern PyObject *MissingDebugInfoError;
|
extern PyObject *MissingDebugInfoError;
|
||||||
|
@ -159,11 +159,6 @@ DRGNPY_PUBLIC PyMODINIT_FUNC PyInit__drgn(void)
|
|||||||
Py_INCREF(&DrgnType_type);
|
Py_INCREF(&DrgnType_type);
|
||||||
PyModule_AddObject(m, "Type", (PyObject *)&DrgnType_type);
|
PyModule_AddObject(m, "Type", (PyObject *)&DrgnType_type);
|
||||||
|
|
||||||
if (PyType_Ready(&Symbol_type) < 0)
|
|
||||||
goto err;
|
|
||||||
Py_INCREF(&Symbol_type);
|
|
||||||
PyModule_AddObject(m, "Symbol", (PyObject *)&Symbol_type);
|
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -281,15 +281,15 @@ static PyObject *Program_add_type_finder(Program *self, PyObject *args,
|
|||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct drgn_error *py_symbol_find_fn(const char *name, size_t name_len,
|
static struct drgn_error *py_object_find_fn(const char *name, size_t name_len,
|
||||||
const char *filename,
|
const char *filename,
|
||||||
enum drgn_find_object_flags flags,
|
enum drgn_find_object_flags flags,
|
||||||
void *arg, struct drgn_symbol *ret)
|
void *arg, struct drgn_object *ret)
|
||||||
{
|
{
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
PyGILState_STATE gstate;
|
PyGILState_STATE gstate;
|
||||||
PyObject *name_obj, *flags_obj;
|
PyObject *name_obj, *flags_obj;
|
||||||
PyObject *sym_obj;
|
PyObject *obj;
|
||||||
|
|
||||||
gstate = PyGILState_Ensure();
|
gstate = PyGILState_Ensure();
|
||||||
name_obj = PyUnicode_FromStringAndSize(name, name_len);
|
name_obj = PyUnicode_FromStringAndSize(name, name_len);
|
||||||
@ -303,32 +303,27 @@ static struct drgn_error *py_symbol_find_fn(const char *name, size_t name_len,
|
|||||||
err = drgn_error_from_python();
|
err = drgn_error_from_python();
|
||||||
goto out_name_obj;
|
goto out_name_obj;
|
||||||
}
|
}
|
||||||
sym_obj = PyObject_CallFunction(PyTuple_GET_ITEM(arg, 1), "OOs",
|
obj = PyObject_CallFunction(PyTuple_GET_ITEM(arg, 1), "OOOs",
|
||||||
name_obj, flags_obj, filename);
|
PyTuple_GET_ITEM(arg, 0), name_obj,
|
||||||
if (!sym_obj) {
|
flags_obj, filename);
|
||||||
|
if (!obj) {
|
||||||
err = drgn_error_from_python();
|
err = drgn_error_from_python();
|
||||||
goto out_flags_obj;
|
goto out_flags_obj;
|
||||||
}
|
}
|
||||||
if (sym_obj == Py_None) {
|
if (obj == Py_None) {
|
||||||
err = &drgn_not_found;
|
err = &drgn_not_found;
|
||||||
goto out_sym_obj;
|
goto out_obj;
|
||||||
}
|
}
|
||||||
if (!PyObject_TypeCheck(sym_obj, &Symbol_type)) {
|
if (!PyObject_TypeCheck(obj, &DrgnObject_type)) {
|
||||||
PyErr_SetString(PyExc_TypeError,
|
PyErr_SetString(PyExc_TypeError,
|
||||||
"symbol find callback must return Symbol or None");
|
"object find callback must return Object or None");
|
||||||
err = drgn_error_from_python();
|
err = drgn_error_from_python();
|
||||||
goto out_sym_obj;
|
goto out_obj;
|
||||||
}
|
|
||||||
if (Program_hold_type((Program *)PyTuple_GET_ITEM(arg, 0),
|
|
||||||
((Symbol *)sym_obj)->type_obj) == -1) {
|
|
||||||
err = drgn_error_from_python();
|
|
||||||
goto out_sym_obj;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*ret = ((Symbol *)sym_obj)->sym;
|
err = drgn_object_copy(ret, &((DrgnObject *)obj)->obj);
|
||||||
err = NULL;
|
out_obj:
|
||||||
out_sym_obj:
|
Py_DECREF(obj);
|
||||||
Py_DECREF(sym_obj);
|
|
||||||
out_flags_obj:
|
out_flags_obj:
|
||||||
Py_DECREF(flags_obj);
|
Py_DECREF(flags_obj);
|
||||||
out_name_obj:
|
out_name_obj:
|
||||||
@ -338,7 +333,7 @@ out_gstate:
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *Program_add_symbol_finder(Program *self, PyObject *args,
|
static PyObject *Program_add_object_finder(Program *self, PyObject *args,
|
||||||
PyObject *kwds)
|
PyObject *kwds)
|
||||||
{
|
{
|
||||||
static char *keywords[] = {"fn", NULL};
|
static char *keywords[] = {"fn", NULL};
|
||||||
@ -346,7 +341,7 @@ static PyObject *Program_add_symbol_finder(Program *self, PyObject *args,
|
|||||||
PyObject *fn, *arg;
|
PyObject *fn, *arg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:add_symbol_finder",
|
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:add_object_finder",
|
||||||
keywords, &fn))
|
keywords, &fn))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
@ -363,7 +358,7 @@ static PyObject *Program_add_symbol_finder(Program *self, PyObject *args,
|
|||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
err = drgn_program_add_symbol_finder(&self->prog, py_symbol_find_fn,
|
err = drgn_program_add_object_finder(&self->prog, py_object_find_fn,
|
||||||
arg);
|
arg);
|
||||||
if (err)
|
if (err)
|
||||||
return set_drgn_error(err);
|
return set_drgn_error(err);
|
||||||
@ -711,6 +706,7 @@ static int Program_contains(Program *self, PyObject *key)
|
|||||||
{
|
{
|
||||||
struct drgn_error *err;
|
struct drgn_error *err;
|
||||||
const char *name;
|
const char *name;
|
||||||
|
struct drgn_object tmp;
|
||||||
bool clear;
|
bool clear;
|
||||||
|
|
||||||
if (!PyUnicode_Check(key)) {
|
if (!PyUnicode_Check(key)) {
|
||||||
@ -722,11 +718,13 @@ static int Program_contains(Program *self, PyObject *key)
|
|||||||
if (!name)
|
if (!name)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
drgn_object_init(&tmp, &self->prog);
|
||||||
clear = set_drgn_in_python();
|
clear = set_drgn_in_python();
|
||||||
err = drgn_program_find_object(&self->prog, name, NULL,
|
err = drgn_program_find_object(&self->prog, name, NULL,
|
||||||
DRGN_FIND_OBJECT_ANY, NULL);
|
DRGN_FIND_OBJECT_ANY, &tmp);
|
||||||
if (clear)
|
if (clear)
|
||||||
clear_drgn_in_python();
|
clear_drgn_in_python();
|
||||||
|
drgn_object_deinit(&tmp);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err->code == DRGN_ERROR_LOOKUP) {
|
if (err->code == DRGN_ERROR_LOOKUP) {
|
||||||
drgn_error_destroy(err);
|
drgn_error_destroy(err);
|
||||||
@ -756,8 +754,8 @@ static PyMethodDef Program_methods[] = {
|
|||||||
METH_VARARGS | METH_KEYWORDS, drgn_Program_add_memory_segment_DOC},
|
METH_VARARGS | METH_KEYWORDS, drgn_Program_add_memory_segment_DOC},
|
||||||
{"add_type_finder", (PyCFunction)Program_add_type_finder,
|
{"add_type_finder", (PyCFunction)Program_add_type_finder,
|
||||||
METH_VARARGS | METH_KEYWORDS, drgn_Program_add_type_finder_DOC},
|
METH_VARARGS | METH_KEYWORDS, drgn_Program_add_type_finder_DOC},
|
||||||
{"add_symbol_finder", (PyCFunction)Program_add_symbol_finder,
|
{"add_object_finder", (PyCFunction)Program_add_object_finder,
|
||||||
METH_VARARGS | METH_KEYWORDS, drgn_Program_add_symbol_finder_DOC},
|
METH_VARARGS | METH_KEYWORDS, drgn_Program_add_object_finder_DOC},
|
||||||
{"set_core_dump", (PyCFunction)Program_set_core_dump,
|
{"set_core_dump", (PyCFunction)Program_set_core_dump,
|
||||||
METH_VARARGS | METH_KEYWORDS, drgn_Program_set_core_dump_DOC},
|
METH_VARARGS | METH_KEYWORDS, drgn_Program_set_core_dump_DOC},
|
||||||
{"set_kernel", (PyCFunction)Program_set_kernel, METH_NOARGS,
|
{"set_kernel", (PyCFunction)Program_set_kernel, METH_NOARGS,
|
||||||
|
@ -1,302 +0,0 @@
|
|||||||
// Copyright 2018-2019 - Omar Sandoval
|
|
||||||
// SPDX-License-Identifier: GPL-3.0+
|
|
||||||
|
|
||||||
#include "drgnpy.h"
|
|
||||||
|
|
||||||
#include "../symbol_index.h"
|
|
||||||
|
|
||||||
Symbol *Symbol_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
|
|
||||||
{
|
|
||||||
static char *keywords[] = {
|
|
||||||
"type", "value", "address", "is_enumerator", "byteorder", NULL,
|
|
||||||
};
|
|
||||||
DrgnType *type_obj;
|
|
||||||
struct drgn_qualified_type qualified_type;
|
|
||||||
PyObject *value_obj = Py_None, *address_obj = Py_None;
|
|
||||||
int is_enumerator = 0;
|
|
||||||
const char *byteorder = NULL;
|
|
||||||
Symbol *sym;
|
|
||||||
int num_given;
|
|
||||||
|
|
||||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!|$OOpz:Symbol", keywords,
|
|
||||||
&DrgnType_type, &type_obj, &value_obj,
|
|
||||||
&address_obj, &is_enumerator,
|
|
||||||
&byteorder)) {
|
|
||||||
fprintf(stderr, "ya\n");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
qualified_type.type = type_obj->type;
|
|
||||||
qualified_type.qualifiers = type_obj->qualifiers;
|
|
||||||
|
|
||||||
num_given = ((value_obj != Py_None) + (address_obj != Py_None) +
|
|
||||||
is_enumerator);
|
|
||||||
if (num_given == 0) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"one of value, address, or is_enumerator is required");
|
|
||||||
return NULL;
|
|
||||||
} else if (num_given > 1) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"only one of value, address, or is_enumerator may be given");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (address_obj != Py_None && !byteorder) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"byteorder must be given with address");
|
|
||||||
return NULL;
|
|
||||||
} else if (address_obj == Py_None && byteorder) {
|
|
||||||
PyErr_SetString(PyExc_ValueError,
|
|
||||||
"byteorder may only be given with address");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
sym = (Symbol *)subtype->tp_alloc(subtype, 0);
|
|
||||||
if (!sym)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
sym->sym.type = type_obj->type;
|
|
||||||
sym->sym.qualifiers = type_obj->qualifiers;
|
|
||||||
if (value_obj != Py_None) {
|
|
||||||
enum drgn_object_kind kind;
|
|
||||||
|
|
||||||
sym->sym.kind = DRGN_SYMBOL_CONSTANT;
|
|
||||||
kind = drgn_type_object_kind(qualified_type.type);
|
|
||||||
switch (kind) {
|
|
||||||
case DRGN_OBJECT_SIGNED:
|
|
||||||
case DRGN_OBJECT_UNSIGNED: {
|
|
||||||
union {
|
|
||||||
int64_t svalue;
|
|
||||||
uint64_t uvalue;
|
|
||||||
} tmp;
|
|
||||||
|
|
||||||
if (!PyNumber_Check(value_obj)) {
|
|
||||||
set_error_type_name("'%s' value must be number",
|
|
||||||
qualified_type);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
tmp.uvalue = PyLong_AsUnsignedLongLongMask(value_obj);
|
|
||||||
if (tmp.uvalue == (unsigned long long)-1 &&
|
|
||||||
PyErr_Occurred())
|
|
||||||
goto err;
|
|
||||||
if (kind == DRGN_OBJECT_SIGNED)
|
|
||||||
sym->sym.svalue = tmp.svalue;
|
|
||||||
else
|
|
||||||
sym->sym.uvalue = tmp.uvalue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case DRGN_OBJECT_FLOAT: {
|
|
||||||
double fvalue;
|
|
||||||
|
|
||||||
if (!PyNumber_Check(value_obj)) {
|
|
||||||
set_error_type_name("'%s' value must be number",
|
|
||||||
qualified_type);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
fvalue = PyFloat_AsDouble(value_obj);
|
|
||||||
if (fvalue == -1.0 && PyErr_Occurred())
|
|
||||||
goto err;
|
|
||||||
sym->sym.fvalue = fvalue;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
set_error_type_name("cannot have '%s' constant",
|
|
||||||
qualified_type);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
} else if (address_obj != Py_None) {
|
|
||||||
sym->sym.kind = DRGN_SYMBOL_ADDRESS;
|
|
||||||
sym->sym.address =
|
|
||||||
index_arg(address_obj, "address must be integer");
|
|
||||||
if (sym->sym.address == (unsigned long long)-1 &&
|
|
||||||
PyErr_Occurred())
|
|
||||||
goto err;
|
|
||||||
if (parse_byteorder(byteorder, &sym->sym.little_endian) == -1)
|
|
||||||
goto err;
|
|
||||||
} else {
|
|
||||||
sym->sym.kind = DRGN_SYMBOL_ENUMERATOR;
|
|
||||||
}
|
|
||||||
Py_INCREF(type_obj);
|
|
||||||
sym->type_obj = type_obj;
|
|
||||||
return sym;
|
|
||||||
|
|
||||||
err:
|
|
||||||
Py_DECREF(sym);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Symbol_dealloc(Symbol *self)
|
|
||||||
{
|
|
||||||
Py_XDECREF(self->type_obj);
|
|
||||||
Py_TYPE(self)->tp_free((PyObject *)self);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct drgn_error *drgn_symbol_eq(struct drgn_symbol *a,
|
|
||||||
struct drgn_symbol *b,
|
|
||||||
bool *ret)
|
|
||||||
{
|
|
||||||
struct drgn_error *err;
|
|
||||||
struct drgn_qualified_type type_a, type_b;
|
|
||||||
|
|
||||||
if (a->kind != b->kind) {
|
|
||||||
*ret = false;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
type_a.type = a->type;
|
|
||||||
type_a.qualifiers = a->qualifiers;
|
|
||||||
type_b.type = b->type;
|
|
||||||
type_b.qualifiers = b->qualifiers;
|
|
||||||
|
|
||||||
err = drgn_qualified_type_eq(type_a, type_b, ret);
|
|
||||||
if (err || !*ret)
|
|
||||||
return err;
|
|
||||||
|
|
||||||
switch (a->kind) {
|
|
||||||
case DRGN_SYMBOL_CONSTANT:
|
|
||||||
switch (drgn_type_object_kind(a->type)) {
|
|
||||||
case DRGN_OBJECT_SIGNED:
|
|
||||||
*ret = a->svalue == b->svalue;
|
|
||||||
break;
|
|
||||||
case DRGN_OBJECT_UNSIGNED:
|
|
||||||
*ret = a->uvalue == b->uvalue;
|
|
||||||
break;
|
|
||||||
case DRGN_OBJECT_FLOAT:
|
|
||||||
*ret = a->fvalue == b->fvalue;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
return drgn_type_error("cannot create '%s' constant",
|
|
||||||
a->type);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
case DRGN_SYMBOL_ADDRESS:
|
|
||||||
*ret = (a->address == b->address &&
|
|
||||||
a->little_endian == b->little_endian);
|
|
||||||
return NULL;
|
|
||||||
case DRGN_SYMBOL_ENUMERATOR:
|
|
||||||
*ret = true;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
DRGN_UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *Symbol_richcompare(Symbol *left, PyObject *right, int op)
|
|
||||||
{
|
|
||||||
struct drgn_error *err;
|
|
||||||
bool clear, ret;
|
|
||||||
|
|
||||||
if (!PyObject_TypeCheck(right, &Symbol_type) ||
|
|
||||||
(op != Py_EQ && op != Py_NE))
|
|
||||||
Py_RETURN_NOTIMPLEMENTED;
|
|
||||||
|
|
||||||
clear = set_drgn_in_python();
|
|
||||||
err = drgn_symbol_eq(&left->sym, &((Symbol *)right)->sym, &ret);
|
|
||||||
if (clear)
|
|
||||||
clear_drgn_in_python();
|
|
||||||
if (err)
|
|
||||||
return set_drgn_error(err);
|
|
||||||
if (op == Py_NE)
|
|
||||||
ret = !ret;
|
|
||||||
if (ret)
|
|
||||||
Py_RETURN_TRUE;
|
|
||||||
else
|
|
||||||
Py_RETURN_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *Symbol_get_type(Symbol *self, void *arg)
|
|
||||||
{
|
|
||||||
Py_INCREF(self->type_obj);
|
|
||||||
return (PyObject *)self->type_obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *Symbol_get_value(Symbol *self, void *arg)
|
|
||||||
{
|
|
||||||
if (self->sym.kind != DRGN_SYMBOL_CONSTANT)
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
|
|
||||||
switch (drgn_type_object_kind(self->sym.type)) {
|
|
||||||
case DRGN_OBJECT_SIGNED:
|
|
||||||
return PyLong_FromLongLong(self->sym.svalue);
|
|
||||||
case DRGN_OBJECT_UNSIGNED:
|
|
||||||
return PyLong_FromUnsignedLongLong(self->sym.uvalue);
|
|
||||||
case DRGN_OBJECT_FLOAT:
|
|
||||||
return PyFloat_FromDouble(self->sym.fvalue);
|
|
||||||
default:
|
|
||||||
DRGN_UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *Symbol_get_address(Symbol *self, void *arg)
|
|
||||||
{
|
|
||||||
if (self->sym.kind == DRGN_SYMBOL_ADDRESS)
|
|
||||||
return PyLong_FromUnsignedLongLong(self->sym.address);
|
|
||||||
else
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *Symbol_get_is_enumerator(Symbol *self, void *arg)
|
|
||||||
{
|
|
||||||
if (self->sym.kind == DRGN_SYMBOL_ENUMERATOR)
|
|
||||||
Py_RETURN_TRUE;
|
|
||||||
else
|
|
||||||
Py_RETURN_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyObject *Symbol_get_byteorder(Symbol *self, void *arg)
|
|
||||||
{
|
|
||||||
if (self->sym.kind == DRGN_SYMBOL_ADDRESS)
|
|
||||||
return byteorder_string(self->sym.little_endian);
|
|
||||||
else
|
|
||||||
Py_RETURN_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static PyGetSetDef Symbol_getset[] = {
|
|
||||||
{"type", (getter)Symbol_get_type, NULL, drgn_Symbol_type_DOC},
|
|
||||||
{"value", (getter)Symbol_get_value, NULL, drgn_Symbol_value_DOC},
|
|
||||||
{"address", (getter)Symbol_get_address, NULL, drgn_Symbol_address_DOC},
|
|
||||||
{"is_enumerator", (getter)Symbol_get_is_enumerator, NULL,
|
|
||||||
drgn_Symbol_is_enumerator_DOC},
|
|
||||||
{"byteorder", (getter)Symbol_get_byteorder, NULL,
|
|
||||||
drgn_Symbol_byteorder_DOC},
|
|
||||||
{},
|
|
||||||
};
|
|
||||||
|
|
||||||
PyTypeObject Symbol_type = {
|
|
||||||
PyVarObject_HEAD_INIT(NULL, 0)
|
|
||||||
"_drgn.Symbol", /* tp_name */
|
|
||||||
sizeof(Symbol), /* tp_basicsize */
|
|
||||||
0, /* tp_itemsize */
|
|
||||||
(destructor)Symbol_dealloc, /* tp_dealloc */
|
|
||||||
NULL, /* tp_print */
|
|
||||||
NULL, /* tp_getattr */
|
|
||||||
NULL, /* tp_setattr */
|
|
||||||
NULL, /* tp_as_async */
|
|
||||||
NULL, /* tp_repr */
|
|
||||||
NULL, /* tp_as_number */
|
|
||||||
NULL, /* tp_as_sequence */
|
|
||||||
NULL, /* tp_as_mapping */
|
|
||||||
NULL, /* tp_hash */
|
|
||||||
NULL, /* tp_call */
|
|
||||||
NULL, /* tp_str */
|
|
||||||
NULL, /* tp_getattro */
|
|
||||||
NULL, /* tp_setattro */
|
|
||||||
NULL, /* tp_as_buffer */
|
|
||||||
Py_TPFLAGS_DEFAULT, /* tp_flags */
|
|
||||||
drgn_Symbol_DOC, /* tp_doc */
|
|
||||||
NULL, /* tp_traverse */
|
|
||||||
NULL, /* tp_clear */
|
|
||||||
(richcmpfunc)Symbol_richcompare, /* tp_richcompare */
|
|
||||||
0, /* tp_weaklistoffset */
|
|
||||||
NULL, /* tp_iter */
|
|
||||||
NULL, /* tp_iternext */
|
|
||||||
NULL, /* tp_methods */
|
|
||||||
NULL, /* tp_members */
|
|
||||||
Symbol_getset, /* tp_getset */
|
|
||||||
NULL, /* tp_base */
|
|
||||||
NULL, /* tp_dict */
|
|
||||||
NULL, /* tp_descr_get */
|
|
||||||
NULL, /* tp_descr_set */
|
|
||||||
0, /* tp_dictoffset */
|
|
||||||
NULL, /* tp_init */
|
|
||||||
NULL, /* tp_alloc */
|
|
||||||
(newfunc)Symbol_new, /* tp_new */
|
|
||||||
};
|
|
@ -1,146 +0,0 @@
|
|||||||
// Copyright 2018-2019 - Omar Sandoval
|
|
||||||
// SPDX-License-Identifier: GPL-3.0+
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "internal.h"
|
|
||||||
#include "symbol_index.h"
|
|
||||||
#include "type.h"
|
|
||||||
|
|
||||||
void drgn_symbol_index_init(struct drgn_symbol_index *sindex)
|
|
||||||
{
|
|
||||||
sindex->finders = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drgn_symbol_index_deinit(struct drgn_symbol_index *sindex)
|
|
||||||
{
|
|
||||||
struct drgn_symbol_finder *finder;
|
|
||||||
|
|
||||||
finder = sindex->finders;
|
|
||||||
while (finder) {
|
|
||||||
struct drgn_symbol_finder *next = finder->next;
|
|
||||||
|
|
||||||
free(finder);
|
|
||||||
finder = next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct drgn_error *
|
|
||||||
drgn_symbol_index_add_finder(struct drgn_symbol_index *sindex,
|
|
||||||
drgn_symbol_find_fn fn, void *arg)
|
|
||||||
{
|
|
||||||
struct drgn_symbol_finder *finder;
|
|
||||||
|
|
||||||
finder = malloc(sizeof(*finder));
|
|
||||||
if (!finder)
|
|
||||||
return &drgn_enomem;
|
|
||||||
finder->fn = fn;
|
|
||||||
finder->arg = arg;
|
|
||||||
finder->next = sindex->finders;
|
|
||||||
sindex->finders = finder;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct drgn_error *drgn_symbol_from_enumerator(struct drgn_symbol *sym,
|
|
||||||
const char *name)
|
|
||||||
{
|
|
||||||
const struct drgn_type_enumerator *enumerators;
|
|
||||||
size_t num_enumerators, i;
|
|
||||||
|
|
||||||
if (drgn_type_kind(sym->type) != DRGN_TYPE_ENUM) {
|
|
||||||
return drgn_type_error("'%s' is not an enumerated type",
|
|
||||||
sym->type);
|
|
||||||
}
|
|
||||||
enumerators = drgn_type_enumerators(sym->type);
|
|
||||||
num_enumerators = drgn_type_num_enumerators(sym->type);
|
|
||||||
for (i = 0; i < num_enumerators; i++) {
|
|
||||||
if (strcmp(enumerators[i].name, name) != 0)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (drgn_enum_type_is_signed(sym->type))
|
|
||||||
sym->svalue = enumerators[i].svalue;
|
|
||||||
else
|
|
||||||
sym->uvalue = enumerators[i].uvalue;
|
|
||||||
sym->kind = DRGN_SYMBOL_CONSTANT;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
|
||||||
"could not find '%s' in 'enum %s'", name,
|
|
||||||
drgn_type_is_anonymous(sym->type) ?
|
|
||||||
"<anonymous>" : drgn_type_tag(sym->type));
|
|
||||||
}
|
|
||||||
|
|
||||||
struct drgn_error *drgn_symbol_index_find(struct drgn_symbol_index *sindex,
|
|
||||||
const char *name,
|
|
||||||
const char *filename,
|
|
||||||
enum drgn_find_object_flags flags,
|
|
||||||
struct drgn_symbol *ret)
|
|
||||||
{
|
|
||||||
struct drgn_error *err;
|
|
||||||
size_t name_len;
|
|
||||||
struct drgn_symbol_finder *finder;
|
|
||||||
const char *kind_str;
|
|
||||||
|
|
||||||
if ((flags & ~DRGN_FIND_OBJECT_ANY) || !flags) {
|
|
||||||
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
|
||||||
"invalid find object flags");
|
|
||||||
}
|
|
||||||
|
|
||||||
name_len = strlen(name);
|
|
||||||
finder = sindex->finders;
|
|
||||||
while (finder) {
|
|
||||||
err = finder->fn(name, name_len, filename, flags, finder->arg,
|
|
||||||
ret);
|
|
||||||
if (!err) {
|
|
||||||
if (ret->kind == DRGN_SYMBOL_ENUMERATOR ||
|
|
||||||
ret->kind == DRGN_SYMBOL_CONSTANT) {
|
|
||||||
if (!(flags & DRGN_FIND_OBJECT_CONSTANT))
|
|
||||||
goto wrong_kind;
|
|
||||||
} else if (!(flags &
|
|
||||||
(DRGN_FIND_OBJECT_FUNCTION | DRGN_FIND_OBJECT_VARIABLE))) {
|
|
||||||
goto wrong_kind;
|
|
||||||
}
|
|
||||||
if (ret->kind == DRGN_SYMBOL_ENUMERATOR) {
|
|
||||||
err = drgn_symbol_from_enumerator(ret, name);
|
|
||||||
if (err)
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
if (ret->kind == DRGN_SYMBOL_CONSTANT) {
|
|
||||||
ret->little_endian = (__BYTE_ORDER__ ==
|
|
||||||
__ORDER_LITTLE_ENDIAN__);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
if (err != &drgn_not_found)
|
|
||||||
return err;
|
|
||||||
finder = finder->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (flags) {
|
|
||||||
case DRGN_FIND_OBJECT_CONSTANT:
|
|
||||||
kind_str = "constant ";
|
|
||||||
break;
|
|
||||||
case DRGN_FIND_OBJECT_FUNCTION:
|
|
||||||
kind_str = "function ";
|
|
||||||
break;
|
|
||||||
case DRGN_FIND_OBJECT_VARIABLE:
|
|
||||||
kind_str = "variable ";
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
kind_str = "";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (filename) {
|
|
||||||
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
|
||||||
"could not find %s'%s' in '%s'",
|
|
||||||
kind_str, name, filename);
|
|
||||||
} else {
|
|
||||||
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
|
||||||
"could not find %s'%s'", kind_str,
|
|
||||||
name);
|
|
||||||
}
|
|
||||||
|
|
||||||
wrong_kind:
|
|
||||||
return drgn_error_create(DRGN_ERROR_TYPE,
|
|
||||||
"symbol find callback returned wrong kind of symbol");
|
|
||||||
}
|
|
@ -1,83 +0,0 @@
|
|||||||
// Copyright 2018-2019 - Omar Sandoval
|
|
||||||
// SPDX-License-Identifier: GPL-3.0+
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @file
|
|
||||||
*
|
|
||||||
* Symbol lookup.
|
|
||||||
*
|
|
||||||
* See @ref SymbolIndex.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef DRGN_SYMBOL_INDEX_H
|
|
||||||
#define DRGN_SYMBOL_INDEX_H
|
|
||||||
|
|
||||||
#include "drgn.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @ingroup Internals
|
|
||||||
*
|
|
||||||
* @defgroup SymbolIndex Symbol index
|
|
||||||
*
|
|
||||||
* Symbol lookup.
|
|
||||||
*
|
|
||||||
* @ref drgn_symbol_index provides a common interface for finding symbols (e.g.,
|
|
||||||
* variables, constants, and functions) in a program.
|
|
||||||
*
|
|
||||||
* @{
|
|
||||||
*/
|
|
||||||
|
|
||||||
/** Registered callback in a @ref drgn_symbol_index. */
|
|
||||||
struct drgn_symbol_finder {
|
|
||||||
/** The callback. */
|
|
||||||
drgn_symbol_find_fn fn;
|
|
||||||
/** Argument to pass to @ref drgn_symbol_finder::fn. */
|
|
||||||
void *arg;
|
|
||||||
/** Next callback to try. */
|
|
||||||
struct drgn_symbol_finder *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Symbol index.
|
|
||||||
*
|
|
||||||
* A symbol index is used to find symbols (variables, constants, and functions)
|
|
||||||
* by name. The types are found using callbacks which are registered with @ref
|
|
||||||
* drgn_symbol_index_add_finder(). @ref drgn_symbol_index_find() searches for an
|
|
||||||
* symbol.
|
|
||||||
*/
|
|
||||||
struct drgn_symbol_index {
|
|
||||||
/** Callbacks for finding symbols. */
|
|
||||||
struct drgn_symbol_finder *finders;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** Initialize a @ref drgn_symbol_index. */
|
|
||||||
void drgn_symbol_index_init(struct drgn_symbol_index *sindex);
|
|
||||||
|
|
||||||
/** Deinitialize a @ref drgn_symbol_index. */
|
|
||||||
void drgn_symbol_index_deinit(struct drgn_symbol_index *sindex);
|
|
||||||
|
|
||||||
/** @sa drgn_program_add_symbol_finder() */
|
|
||||||
struct drgn_error *
|
|
||||||
drgn_symbol_index_add_finder(struct drgn_symbol_index *sindex,
|
|
||||||
drgn_symbol_find_fn fn, void *arg);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Find a symbol in a @ref drgn_symbol_index.
|
|
||||||
*
|
|
||||||
* @param[in] sindex Symbol index.
|
|
||||||
* @param[in] name Name of the symbol.
|
|
||||||
* @param[in] filename Exact filename containing the symbol definition, or @c
|
|
||||||
* NULL for any definition.
|
|
||||||
* @param[in] flags Bitmask of @ref drgn_find_object_flags.
|
|
||||||
* @param[out] ret Returned symbol.
|
|
||||||
* @return @c NULL on success, non-@c NULL on error.
|
|
||||||
*/
|
|
||||||
struct drgn_error *drgn_symbol_index_find(struct drgn_symbol_index *sindex,
|
|
||||||
const char *name,
|
|
||||||
const char *filename,
|
|
||||||
enum drgn_find_object_flags flags,
|
|
||||||
struct drgn_symbol *ret);
|
|
||||||
|
|
||||||
/** @} */
|
|
||||||
|
|
||||||
#endif /* DRGN_SYMBOL_INDEX_H */
|
|
@ -1,5 +1,5 @@
|
|||||||
import functools
|
import functools
|
||||||
from typing import NamedTuple, Optional
|
from typing import Any, NamedTuple, Optional
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from drgn import (
|
from drgn import (
|
||||||
@ -7,6 +7,7 @@ from drgn import (
|
|||||||
FindObjectFlags,
|
FindObjectFlags,
|
||||||
Object,
|
Object,
|
||||||
Program,
|
Program,
|
||||||
|
Type,
|
||||||
TypeKind,
|
TypeKind,
|
||||||
enum_type,
|
enum_type,
|
||||||
float_type,
|
float_type,
|
||||||
@ -48,7 +49,14 @@ def mock_memory_read(data, address, count, offset, physical):
|
|||||||
return data[offset:offset + count]
|
return data[offset:offset + count]
|
||||||
|
|
||||||
|
|
||||||
def mock_program(arch=MOCK_ARCH, *, segments=None, types=None, symbols=None):
|
class MockObject(NamedTuple):
|
||||||
|
name: str
|
||||||
|
type: Type
|
||||||
|
address: Optional[int] = None
|
||||||
|
value: Any = None
|
||||||
|
|
||||||
|
|
||||||
|
def mock_program(arch=MOCK_ARCH, *, segments=None, types=None, objects=None):
|
||||||
def mock_find_type(kind, name, filename):
|
def mock_find_type(kind, name, filename):
|
||||||
if filename:
|
if filename:
|
||||||
return None
|
return None
|
||||||
@ -65,22 +73,22 @@ def mock_program(arch=MOCK_ARCH, *, segments=None, types=None, symbols=None):
|
|||||||
return type
|
return type
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def mock_symbol_find(name, flags, filename):
|
def mock_object_find(prog, name, flags, filename):
|
||||||
if filename:
|
if filename:
|
||||||
return None
|
return None
|
||||||
for sym_name, sym in symbols:
|
for obj in objects:
|
||||||
if sym_name == name:
|
if obj.name == name:
|
||||||
if sym.value is not None or sym.is_enumerator:
|
if obj.value is not None:
|
||||||
if flags & FindObjectFlags.CONSTANT:
|
if flags & FindObjectFlags.CONSTANT:
|
||||||
break
|
break
|
||||||
elif sym.type.kind == TypeKind.FUNCTION:
|
elif obj.type.kind == TypeKind.FUNCTION:
|
||||||
if flags & FindObjectFlags.FUNCTION:
|
if flags & FindObjectFlags.FUNCTION:
|
||||||
break
|
break
|
||||||
elif flags & FindObjectFlags.VARIABLE:
|
elif flags & FindObjectFlags.VARIABLE:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
return None
|
return None
|
||||||
return sym
|
return Object(prog, obj.type, address=obj.address, value=obj.value)
|
||||||
|
|
||||||
prog = Program(arch)
|
prog = Program(arch)
|
||||||
if segments is not None:
|
if segments is not None:
|
||||||
@ -95,8 +103,8 @@ def mock_program(arch=MOCK_ARCH, *, segments=None, types=None, symbols=None):
|
|||||||
functools.partial(mock_memory_read, segment.buf), True)
|
functools.partial(mock_memory_read, segment.buf), True)
|
||||||
if types is not None:
|
if types is not None:
|
||||||
prog.add_type_finder(mock_find_type)
|
prog.add_type_finder(mock_find_type)
|
||||||
if symbols is not None:
|
if objects is not None:
|
||||||
prog.add_symbol_finder(mock_symbol_find)
|
prog.add_object_finder(mock_object_find)
|
||||||
return prog
|
return prog
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ from tests import (
|
|||||||
line_segment_type,
|
line_segment_type,
|
||||||
mock_program,
|
mock_program,
|
||||||
option_type,
|
option_type,
|
||||||
|
pid_type,
|
||||||
point_type,
|
point_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,7 +13,6 @@ from drgn import (
|
|||||||
Program,
|
Program,
|
||||||
ProgramFlags,
|
ProgramFlags,
|
||||||
Qualifiers,
|
Qualifiers,
|
||||||
Symbol,
|
|
||||||
array_type,
|
array_type,
|
||||||
bool_type,
|
bool_type,
|
||||||
float_type,
|
float_type,
|
||||||
@ -27,6 +26,7 @@ from tests import (
|
|||||||
MOCK_32BIT_ARCH,
|
MOCK_32BIT_ARCH,
|
||||||
MOCK_ARCH,
|
MOCK_ARCH,
|
||||||
MockMemorySegment,
|
MockMemorySegment,
|
||||||
|
MockObject,
|
||||||
ObjectTestCase,
|
ObjectTestCase,
|
||||||
color_type,
|
color_type,
|
||||||
mock_program,
|
mock_program,
|
||||||
@ -473,22 +473,23 @@ class TestTypes(unittest.TestCase):
|
|||||||
|
|
||||||
class TestObjects(ObjectTestCase):
|
class TestObjects(ObjectTestCase):
|
||||||
def test_invalid_finder(self):
|
def test_invalid_finder(self):
|
||||||
self.assertRaises(TypeError, mock_program().add_symbol_finder, 'foo')
|
self.assertRaises(TypeError, mock_program().add_object_finder, 'foo')
|
||||||
|
|
||||||
prog = mock_program()
|
prog = mock_program()
|
||||||
prog.add_symbol_finder(lambda name, flags, filename: 'foo')
|
prog.add_object_finder(lambda prog, name, flags, filename: 'foo')
|
||||||
self.assertRaises(TypeError, prog.object, 'foo')
|
self.assertRaises(TypeError, prog.object, 'foo')
|
||||||
|
|
||||||
def test_not_found(self):
|
def test_not_found(self):
|
||||||
prog = mock_program()
|
prog = mock_program()
|
||||||
self.assertRaises(LookupError, prog.object, 'foo')
|
self.assertRaises(LookupError, prog.object, 'foo')
|
||||||
prog.add_symbol_finder(lambda name, flags, filename: None)
|
prog.add_object_finder(lambda prog, name, flags, filename: None)
|
||||||
self.assertRaises(LookupError, prog.object, 'foo')
|
self.assertRaises(LookupError, prog.object, 'foo')
|
||||||
self.assertFalse('foo' in prog)
|
self.assertFalse('foo' in prog)
|
||||||
|
|
||||||
def test_constant(self):
|
def test_constant(self):
|
||||||
sym = Symbol(int_type('int', 4, True), value=4096)
|
mock_obj = MockObject('PAGE_SIZE', int_type('int', 4, True),
|
||||||
prog = mock_program(symbols=[('PAGE_SIZE', sym)])
|
value=4096)
|
||||||
|
prog = mock_program(objects=[mock_obj])
|
||||||
self.assertEqual(prog['PAGE_SIZE'],
|
self.assertEqual(prog['PAGE_SIZE'],
|
||||||
Object(prog, int_type('int', 4, True), value=4096))
|
Object(prog, int_type('int', 4, True), value=4096))
|
||||||
self.assertEqual(prog.object('PAGE_SIZE', FindObjectFlags.CONSTANT),
|
self.assertEqual(prog.object('PAGE_SIZE', FindObjectFlags.CONSTANT),
|
||||||
@ -496,9 +497,9 @@ class TestObjects(ObjectTestCase):
|
|||||||
self.assertTrue('PAGE_SIZE' in prog)
|
self.assertTrue('PAGE_SIZE' in prog)
|
||||||
|
|
||||||
def test_function(self):
|
def test_function(self):
|
||||||
sym = Symbol(function_type(void_type(), (), False), address=0xffff0000,
|
mock_obj = MockObject('func', function_type(void_type(), (), False),
|
||||||
byteorder='little')
|
address=0xffff0000)
|
||||||
prog = mock_program(symbols=[('func', sym)])
|
prog = mock_program(objects=[mock_obj])
|
||||||
self.assertEqual(prog['func'],
|
self.assertEqual(prog['func'],
|
||||||
Object(prog, function_type(void_type(), (), False),
|
Object(prog, function_type(void_type(), (), False),
|
||||||
address=0xffff0000))
|
address=0xffff0000))
|
||||||
@ -507,9 +508,9 @@ class TestObjects(ObjectTestCase):
|
|||||||
self.assertTrue('func' in prog)
|
self.assertTrue('func' in prog)
|
||||||
|
|
||||||
def test_variable(self):
|
def test_variable(self):
|
||||||
sym = Symbol(int_type('int', 4, True), address=0xffff0000,
|
mock_obj = MockObject('counter', int_type('int', 4, True),
|
||||||
byteorder='little')
|
address=0xffff0000)
|
||||||
prog = mock_program(symbols=[('counter', sym)])
|
prog = mock_program(objects=[mock_obj])
|
||||||
self.assertEqual(prog['counter'],
|
self.assertEqual(prog['counter'],
|
||||||
Object(prog, int_type('int', 4, True),
|
Object(prog, int_type('int', 4, True),
|
||||||
address=0xffff0000))
|
address=0xffff0000))
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
import unittest
|
|
||||||
|
|
||||||
from drgn import enum_type, float_type, int_type
|
|
||||||
from _drgn import Symbol
|
|
||||||
from tests import color_type, line_segment_type, point_type
|
|
||||||
|
|
||||||
|
|
||||||
class TestSymbol(unittest.TestCase):
|
|
||||||
def test_init(self):
|
|
||||||
self.assertRaisesRegex(ValueError, 'one of.*is required', Symbol,
|
|
||||||
int_type('int', 4, True))
|
|
||||||
self.assertRaisesRegex(ValueError, 'only one of', Symbol,
|
|
||||||
int_type('int', 4, True), value=1, address=0)
|
|
||||||
self.assertRaisesRegex(ValueError, 'only one of', Symbol,
|
|
||||||
int_type('int', 4, True), value=1,
|
|
||||||
is_enumerator=True)
|
|
||||||
self.assertRaisesRegex(ValueError, 'only one of', Symbol,
|
|
||||||
int_type('int', 4, True), address=0,
|
|
||||||
is_enumerator=True)
|
|
||||||
self.assertRaisesRegex(ValueError,
|
|
||||||
'byteorder must be given with address', Symbol,
|
|
||||||
int_type('int', 4, True), address=0)
|
|
||||||
self.assertRaisesRegex(ValueError,
|
|
||||||
'byteorder may only be given with address',
|
|
||||||
Symbol, int_type('int', 4, True), value=1,
|
|
||||||
byteorder='little')
|
|
||||||
|
|
||||||
def test_constant(self):
|
|
||||||
sym = Symbol(int_type('int', 4, True), value=1)
|
|
||||||
self.assertEqual(sym.type, int_type('int', 4, True))
|
|
||||||
self.assertEqual(sym.value, 1)
|
|
||||||
self.assertIsNone(sym.address)
|
|
||||||
self.assertFalse(sym.is_enumerator)
|
|
||||||
self.assertIsNone(sym.byteorder)
|
|
||||||
self.assertRaises(TypeError, Symbol, int_type('int', 4, True),
|
|
||||||
value='foo')
|
|
||||||
self.assertEqual(sym, Symbol(int_type('int', 4, True), value=1))
|
|
||||||
self.assertNotEqual(sym, Symbol(int_type('int', 4, True), value=2))
|
|
||||||
self.assertNotEqual(sym, Symbol(int_type('unsigned int', 4, False),
|
|
||||||
value=1))
|
|
||||||
|
|
||||||
sym = Symbol(float_type('double', 8), value=3.14)
|
|
||||||
self.assertEqual(sym.type, float_type('double', 8))
|
|
||||||
self.assertEqual(sym.value, 3.14)
|
|
||||||
self.assertIsNone(sym.address)
|
|
||||||
self.assertFalse(sym.is_enumerator)
|
|
||||||
self.assertIsNone(sym.byteorder)
|
|
||||||
self.assertRaises(TypeError, Symbol, float_type('double', 8),
|
|
||||||
value='foo')
|
|
||||||
self.assertNotEqual(sym, Symbol(float_type('double', 8),
|
|
||||||
address=0xffff0000,
|
|
||||||
byteorder='little'))
|
|
||||||
|
|
||||||
def test_address(self):
|
|
||||||
sym = Symbol(point_type, address=0xffff0000, byteorder='little')
|
|
||||||
self.assertEqual(sym.type, point_type)
|
|
||||||
self.assertIsNone(sym.value)
|
|
||||||
self.assertEqual(sym.address, 0xffff0000)
|
|
||||||
self.assertFalse(sym.is_enumerator)
|
|
||||||
self.assertEqual(sym.byteorder, 'little')
|
|
||||||
self.assertRaises(TypeError, Symbol, point_type, address='foo',
|
|
||||||
byteorder='little')
|
|
||||||
self.assertEqual(sym, Symbol(point_type, address=0xffff0000,
|
|
||||||
byteorder='little'))
|
|
||||||
self.assertNotEqual(sym, Symbol(line_segment_type, address=0xffff0000,
|
|
||||||
byteorder='little'))
|
|
||||||
self.assertNotEqual(sym, Symbol(point_type, address=0xfffeffe0,
|
|
||||||
byteorder='little'))
|
|
||||||
self.assertNotEqual(sym, Symbol(point_type, address=0xffff0000,
|
|
||||||
byteorder='big'))
|
|
||||||
self.assertEqual(
|
|
||||||
Symbol(point_type, address=0xffff0000, byteorder='big').byteorder,
|
|
||||||
'big')
|
|
||||||
|
|
||||||
def test_enumerator(self):
|
|
||||||
sym = Symbol(color_type, is_enumerator=True)
|
|
||||||
self.assertEqual(sym.type, color_type)
|
|
||||||
self.assertIsNone(sym.value)
|
|
||||||
self.assertIsNone(sym.value)
|
|
||||||
self.assertTrue(sym.is_enumerator)
|
|
||||||
self.assertIsNone(sym.byteorder)
|
|
||||||
self.assertEqual(sym, Symbol(color_type, is_enumerator=True))
|
|
||||||
self.assertNotEqual(sym, Symbol(enum_type('color2'), is_enumerator=True))
|
|
||||||
self.assertNotEqual(sym, Symbol(color_type, value=1))
|
|
||||||
|
|
||||||
def test_cmp(self):
|
|
||||||
self.assertNotEqual(Symbol(color_type, is_enumerator=True), 1)
|
|
||||||
self.assertNotEqual(1, Symbol(color_type, is_enumerator=True))
|
|
Loading…
Reference in New Issue
Block a user