mirror of
https://github.com/JakeHillion/drgn.git
synced 2024-12-23 01:33:06 +00:00
d27204260e
The only relocation type I saw in Debian's kernel module debug info was R_ARM_ABS32. R_ARM_REL32 is easy. The Linux kernel supports a bunch of other ones that don't seem relevant to debug info. Unfortunately, I wasn't able to test this because /proc/kcore doesn't exist on Arm. This apparently goes all the way back to 2003: https://lwn.net/Articles/45315/. Signed-off-by: Omar Sandoval <osandov@osandov.com>
2943 lines
90 KiB
C
2943 lines
90 KiB
C
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
/**
|
|
* @file
|
|
*
|
|
* libdrgn public interface.
|
|
*/
|
|
|
|
#ifndef DRGN_H
|
|
#define DRGN_H
|
|
|
|
// IWYU pragma: begin_exports
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
// IWYU pragma: end_exports
|
|
|
|
#include <assert.h>
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
|
|
/**
|
|
* @mainpage
|
|
*
|
|
* libdrgn implements the core of <a
|
|
* href="https://github.com/osandov/drgn">drgn</a>, a debugger-as-a-library. It
|
|
* implements the main drgn abstractions: @ref Programs, @ref Types, and @ref
|
|
* Objects. See <a href="modules.html">Modules</a> for detailed documentation.
|
|
*/
|
|
|
|
/** Major version of drgn. */
|
|
#define DRGN_VERSION_MAJOR @DRGN_VERSION_MAJOR@
|
|
/** Minor version of drgn. */
|
|
#define DRGN_VERSION_MINOR @DRGN_VERSION_MINOR@
|
|
/** Patch level of drgn. */
|
|
#define DRGN_VERSION_PATCH @DRGN_VERSION_PATCH@
|
|
|
|
/**
|
|
* @defgroup ErrorHandling Error handling
|
|
*
|
|
* Error handling in libdrgn.
|
|
*
|
|
* Operations in libdrgn can fail for various reasons. libdrgn returns errors as
|
|
* @ref drgn_error.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/** Error code for a @ref drgn_error. */
|
|
enum drgn_error_code {
|
|
/** Cannot allocate memory. */
|
|
DRGN_ERROR_NO_MEMORY,
|
|
/** Stop iteration. */
|
|
DRGN_ERROR_STOP,
|
|
/** Miscellaneous error. */
|
|
DRGN_ERROR_OTHER,
|
|
/** Invalid argument. */
|
|
DRGN_ERROR_INVALID_ARGUMENT,
|
|
/** Integer overflow. */
|
|
DRGN_ERROR_OVERFLOW,
|
|
/** Maximum recursion depth exceeded. */
|
|
DRGN_ERROR_RECURSION,
|
|
/** System call error. */
|
|
DRGN_ERROR_OS,
|
|
/** One or more files do not have debug information. */
|
|
DRGN_ERROR_MISSING_DEBUG_INFO,
|
|
/** Syntax error while parsing. */
|
|
DRGN_ERROR_SYNTAX,
|
|
/** Entry not found. */
|
|
DRGN_ERROR_LOOKUP,
|
|
/** Bad memory access. */
|
|
DRGN_ERROR_FAULT,
|
|
/** Type error in expression. */
|
|
DRGN_ERROR_TYPE,
|
|
/** Division by zero. */
|
|
DRGN_ERROR_ZERO_DIVISION,
|
|
/** Array out of bounds */
|
|
DRGN_ERROR_OUT_OF_BOUNDS,
|
|
/** Operation was attempted with absent object. */
|
|
DRGN_ERROR_OBJECT_ABSENT,
|
|
/** Number of defined error codes. */
|
|
DRGN_NUM_ERROR_CODES,
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* libdrgn error.
|
|
*
|
|
* All functions in libdrgn that can return an error return this type.
|
|
*/
|
|
struct drgn_error {
|
|
/** Error code. */
|
|
enum drgn_error_code code;
|
|
/**
|
|
* @private
|
|
*
|
|
* Whether this error needs to be passed to @ref drgn_error_destroy().
|
|
*
|
|
* This is @c true for the error codes returned from @ref
|
|
* drgn_error_create() and its related functions. Certain errors are
|
|
* statically allocated and do not need to be passed to @ref
|
|
* drgn_error_destroy() (but they can be).
|
|
*/
|
|
bool needs_destroy;
|
|
/**
|
|
* If @c code is @c DRGN_ERROR_OS, then the error number returned from
|
|
* the system call.
|
|
*/
|
|
int errnum;
|
|
/**
|
|
* If @c code is @c DRGN_ERROR_OS, then the path of the file which
|
|
* encountered the error if applicable. Otherwise, @c NULL.
|
|
*/
|
|
char *path;
|
|
/**
|
|
* If @c code is @c DRGN_ERROR_FAULT, then the address of the read
|
|
* which encountered the error.
|
|
*/
|
|
uint64_t address;
|
|
/** Human-readable error message. */
|
|
char *message;
|
|
};
|
|
|
|
/**
|
|
* Out of memory @ref drgn_error.
|
|
*
|
|
* This has a code of @ref DRGN_ERROR_NO_MEMORY. It can be returned if a memory
|
|
* allocation fails in order to avoid doing another memory allocation. It does
|
|
* not need to be passed to @ref drgn_error_destroy() (but it can be).
|
|
*/
|
|
extern struct drgn_error drgn_enomem;
|
|
|
|
/**
|
|
* Non-fatal lookup @ref drgn_error.
|
|
*
|
|
* This has a code of @ref DRGN_ERROR_LOOKUP. It does not need to be passed to
|
|
* @ref drgn_error_destroy() (but it can be).
|
|
*/
|
|
extern struct drgn_error drgn_not_found;
|
|
|
|
/**
|
|
* Create a @ref drgn_error.
|
|
*
|
|
* @param[in] code Error code.
|
|
* @param[in] message Human-readable error message. This string is copied.
|
|
* @return A new error with the given code and message. If there is a failure to
|
|
* allocate memory for the error or the message, @ref drgn_enomem is returned
|
|
* instead.
|
|
*/
|
|
struct drgn_error *drgn_error_create(enum drgn_error_code code,
|
|
const char *message)
|
|
__attribute__((__returns_nonnull__));
|
|
|
|
/**
|
|
* Create a @ref drgn_error from a printf-style format.
|
|
*
|
|
* @param[in] code Error code.
|
|
* @param[in] format printf-style format string.
|
|
* @param[in] ... Arguments for the format string.
|
|
* @return A new error with the given code and formatted message. If there is a
|
|
* failure to allocate memory for the error or the message, @ref drgn_enomem is
|
|
* returned instead.
|
|
*/
|
|
struct drgn_error *drgn_error_format(enum drgn_error_code code,
|
|
const char *format, ...)
|
|
__attribute__((__returns_nonnull__, __format__(__printf__, 2, 3)));
|
|
|
|
/**
|
|
* Create a @ref DRGN_ERROR_OS @ref drgn_error.
|
|
*
|
|
* @sa drgn_error_create().
|
|
*
|
|
* @param[in] errnum Error number (i.e., @c errno).
|
|
* @param[in] path If not @c NULL, the path of the file which encountered the
|
|
* error. This string is copied.
|
|
*/
|
|
struct drgn_error *drgn_error_create_os(const char *message, int errnum,
|
|
const char *path)
|
|
__attribute__((__returns_nonnull__));
|
|
|
|
/**
|
|
* Create a @ref DRGN_ERROR_OS @ref drgn_error with a printf-style formatted
|
|
* path.
|
|
*
|
|
* @param[in] errnum Error number (i.e., @c errno).
|
|
* @param[in] path_format printf-style format string for path.
|
|
* @param[in] ... Arguments for the format string.
|
|
*/
|
|
struct drgn_error *drgn_error_format_os(const char *message, int errnum,
|
|
const char *path_format, ...)
|
|
__attribute__((__returns_nonnull__, __format__(__printf__, 3, 4)));
|
|
|
|
/**
|
|
* Create a @ref DRGN_ERROR_FAULT @ref drgn_error.
|
|
*
|
|
* @param[in] message Human-readable error message. This string is copied.
|
|
* @param[in] address Address where the fault happened.
|
|
*/
|
|
struct drgn_error *drgn_error_create_fault(const char *message, uint64_t address)
|
|
__attribute__((__returns_nonnull__));
|
|
|
|
/**
|
|
*
|
|
* Create a @ref DRGN_ERROR_FAULT @ref drgn_error with a printf-style formatted
|
|
* message.
|
|
*
|
|
* @param[in] address Address where the fault happened.
|
|
* @param[in] format printf-style format string for message.
|
|
* @param[in] ... Arguments for the format string.
|
|
*/
|
|
struct drgn_error *drgn_error_format_fault(uint64_t address,
|
|
const char *format, ...)
|
|
__attribute__((__returns_nonnull__, __format__(__printf__, 2, 3)));
|
|
|
|
/*
|
|
* Create a copy of a @ref drgn_error.
|
|
*
|
|
* The source's error message and path are copied if necessary, so the source
|
|
* error can be destroyed without affecting the new error and vice versa.
|
|
*
|
|
* @param[in] src Error to copy.
|
|
* @return A new error with the same fields. If there is a failure to allocate
|
|
* memory, @ref drgn_enomem is returned instead.
|
|
*/
|
|
struct drgn_error *drgn_error_copy(struct drgn_error *src)
|
|
__attribute__((__returns_nonnull__));
|
|
|
|
/**
|
|
* Write a @ref drgn_error to a @c stdio stream.
|
|
*
|
|
* For @ref DRGN_ERROR_OS errors, this concatenates @ref drgn_error::message,
|
|
* @ref drgn_error::path, and @c strerror() of @ref drgn_error::errnum.
|
|
* Otherwise, this just writes @c message.
|
|
*
|
|
* @param[in] file File to write to (usually @c stderr).
|
|
* @param[in] err Error to write.
|
|
* @return Non-negative on success, @c EOF on failure.
|
|
*/
|
|
int drgn_error_fwrite(FILE *file, struct drgn_error *err);
|
|
|
|
/**
|
|
* Free a @ref drgn_error.
|
|
*
|
|
* This must be called on any error returned from libdrgn unless otherwise
|
|
* noted.
|
|
*
|
|
* @param[in] err Error to destroy. If @c NULL, this is a no-op.
|
|
*/
|
|
void drgn_error_destroy(struct drgn_error *err);
|
|
|
|
/** @} */
|
|
|
|
|
|
/**
|
|
* @defgroup Languages Languages
|
|
*
|
|
* Programming languages.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/** C */
|
|
extern const struct drgn_language drgn_language_c;
|
|
/** C++ */
|
|
extern const struct drgn_language drgn_language_cpp;
|
|
|
|
/** Get the name of a @ref drgn_language. */
|
|
const char *drgn_language_name(const struct drgn_language *lang);
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @ingroup Types
|
|
*
|
|
* Kinds of types.
|
|
*
|
|
* Every type in a program supported by libdrgn falls into one of these
|
|
* categories.
|
|
*/
|
|
enum drgn_type_kind {
|
|
/** Void type. */
|
|
DRGN_TYPE_VOID = 1,
|
|
/** Integer type. */
|
|
DRGN_TYPE_INT,
|
|
/** Boolean type. */
|
|
DRGN_TYPE_BOOL,
|
|
/** Floating-point type. */
|
|
DRGN_TYPE_FLOAT,
|
|
/** Structure type. */
|
|
DRGN_TYPE_STRUCT,
|
|
/** Union type. */
|
|
DRGN_TYPE_UNION,
|
|
/** Class type. */
|
|
DRGN_TYPE_CLASS,
|
|
/** Enumerated type. */
|
|
DRGN_TYPE_ENUM,
|
|
/** Type definition (a.k.a.\ alias) type. */
|
|
DRGN_TYPE_TYPEDEF,
|
|
/** Pointer type. */
|
|
DRGN_TYPE_POINTER,
|
|
/** Array type. */
|
|
DRGN_TYPE_ARRAY,
|
|
/** Function type. */
|
|
DRGN_TYPE_FUNCTION,
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* @ingroup Types
|
|
*
|
|
* Type qualifiers.
|
|
*
|
|
* Some languages, like C, have the notion of qualifiers which add properties to
|
|
* a type. Qualifiers are represented as a bitmask; each qualifier is a bit.
|
|
*/
|
|
enum drgn_qualifiers {
|
|
/** Constant type. */
|
|
DRGN_QUALIFIER_CONST = (1 << 0),
|
|
/** Volatile type. */
|
|
DRGN_QUALIFIER_VOLATILE = (1 << 1),
|
|
/** Restrict type. */
|
|
DRGN_QUALIFIER_RESTRICT = (1 << 2),
|
|
/** Atomic type. */
|
|
DRGN_QUALIFIER_ATOMIC = (1 << 3),
|
|
/** Bitmask of all valid qualifiers. */
|
|
DRGN_ALL_QUALIFIERS = (1 << 4) - 1,
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* @ingroup Types
|
|
*
|
|
* Qualified type.
|
|
*
|
|
* A type with qualifiers.
|
|
*
|
|
* @sa drgn_qualifiers
|
|
*/
|
|
struct drgn_qualified_type {
|
|
/** Unqualified type. */
|
|
struct drgn_type *type;
|
|
/** Bitmask of qualifiers on this type. */
|
|
enum drgn_qualifiers qualifiers;
|
|
};
|
|
|
|
static inline struct drgn_program *
|
|
drgn_type_program(struct drgn_type *type);
|
|
|
|
static inline const struct drgn_language *
|
|
drgn_type_language(struct drgn_type *type);
|
|
|
|
/**
|
|
* @defgroup Platforms Platforms
|
|
*
|
|
* Program platforms (i.e., architecture and ABI).
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/** An instruction set architecture. */
|
|
enum drgn_architecture {
|
|
DRGN_ARCH_UNKNOWN,
|
|
DRGN_ARCH_X86_64,
|
|
DRGN_ARCH_I386,
|
|
DRGN_ARCH_AARCH64,
|
|
DRGN_ARCH_ARM,
|
|
DRGN_ARCH_PPC64,
|
|
};
|
|
|
|
/** Flags describing a @ref drgn_platform. */
|
|
enum drgn_platform_flags {
|
|
/** Platform is 64-bit. */
|
|
DRGN_PLATFORM_IS_64_BIT = (1 << 0),
|
|
/** Platform is little-endian. */
|
|
DRGN_PLATFORM_IS_LITTLE_ENDIAN = (1 << 1),
|
|
/** All valid platform flags. */
|
|
DRGN_ALL_PLATFORM_FLAGS = (1 << 2) - 1,
|
|
/** Use the default flags for the architecture. */
|
|
DRGN_PLATFORM_DEFAULT_FLAGS = UINT_MAX,
|
|
};
|
|
|
|
/**
|
|
* @struct drgn_platform
|
|
*
|
|
* The environment that a program runs on.
|
|
*/
|
|
struct drgn_platform;
|
|
|
|
/**
|
|
* @struct drgn_register
|
|
*
|
|
* A processor register.
|
|
*/
|
|
struct drgn_register;
|
|
|
|
/**
|
|
* Create a @ref drgn_platform.
|
|
*
|
|
* The returned platform should be destroyed with @ref drgn_platform_destroy().
|
|
*/
|
|
struct drgn_error *drgn_platform_create(enum drgn_architecture arch,
|
|
enum drgn_platform_flags flags,
|
|
struct drgn_platform **ret);
|
|
|
|
/** Destroy a @ref drgn_platform. */
|
|
void drgn_platform_destroy(struct drgn_platform *platform);
|
|
|
|
/** Get the instruction set architecture of a @ref drgn_platform. */
|
|
enum drgn_architecture drgn_platform_arch(const struct drgn_platform *platform);
|
|
|
|
/** Get the flags of a @ref drgn_platform. */
|
|
enum drgn_platform_flags
|
|
drgn_platform_flags(const struct drgn_platform *platform);
|
|
|
|
/** Get the number of @ref drgn_register's on a @ref drgn_platform. */
|
|
size_t drgn_platform_num_registers(const struct drgn_platform *platform);
|
|
|
|
/** Get the @p n-th @ref drgn_register of a @ref drgn_platform. */
|
|
const struct drgn_register *
|
|
drgn_platform_register(const struct drgn_platform *platform, size_t n);
|
|
|
|
/** Get a @ref drgn_register in a @ref drgn_platform by its name. */
|
|
const struct drgn_register *
|
|
drgn_platform_register_by_name(const struct drgn_platform *platform,
|
|
const char *name);
|
|
|
|
/** Return whether two platforms are identical. */
|
|
bool drgn_platform_eq(struct drgn_platform *a, struct drgn_platform *b);
|
|
|
|
/** Platform that drgn was compiled for. */
|
|
extern const struct drgn_platform drgn_host_platform;
|
|
|
|
/**
|
|
* Get the names of a @ref drgn_register.
|
|
*
|
|
* @param[out] num_names_ret Returned number of names.
|
|
* @return Array of names.
|
|
*/
|
|
const char * const *drgn_register_names(const struct drgn_register *reg,
|
|
size_t *num_names_ret);
|
|
|
|
/** @} */
|
|
|
|
struct drgn_object;
|
|
struct drgn_thread;
|
|
|
|
/**
|
|
* @defgroup Programs Programs
|
|
*
|
|
* Debugging programs.
|
|
*
|
|
* A program being debugged is represented by a @ref drgn_program.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @struct drgn_program
|
|
*
|
|
* Program being debugged.
|
|
*
|
|
* A @ref drgn_program represents a crashed or running program. It supports
|
|
* looking up objects (@ref drgn_program_find_object()) and types (@ref
|
|
* drgn_program_find_type()) by name and reading arbitrary memory from the
|
|
* program (@ref drgn_program_read_memory()).
|
|
*
|
|
* A @ref drgn_program is created with @ref drgn_program_from_core_dump(), @ref
|
|
* drgn_program_from_kernel(), or @ref drgn_program_from_pid(). It must be freed
|
|
* with @ref drgn_program_destroy().
|
|
*/
|
|
struct drgn_program;
|
|
|
|
/** Flags which apply to a @ref drgn_program. */
|
|
enum drgn_program_flags {
|
|
/** The program is the Linux kernel. */
|
|
DRGN_PROGRAM_IS_LINUX_KERNEL = (1 << 0),
|
|
/** The program is currently running. */
|
|
DRGN_PROGRAM_IS_LIVE = (1 << 1),
|
|
};
|
|
|
|
/**
|
|
* Create a @ref drgn_program.
|
|
*
|
|
* Usually, @ref drgn_program_from_core_dump(), @ref drgn_program_from_kernel(),
|
|
* and @ref drgn_program_from_pid() are more convenient to use. However, this
|
|
* can be used if more flexibility is required.
|
|
*
|
|
* @param[in] platform Platform that this program runs on, or @c NULL if it
|
|
* should be determined automatically. This is copied.
|
|
* @param[out] ret Returned program.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_create(const struct drgn_platform *platform,
|
|
struct drgn_program **ret);
|
|
|
|
/**
|
|
* Free a @ref drgn_program.
|
|
*
|
|
* @param[in] prog Program to free.
|
|
*/
|
|
void drgn_program_destroy(struct drgn_program *prog);
|
|
|
|
/**
|
|
* Callback implementing a memory read.
|
|
*
|
|
* @param[out] buf Buffer to read into.
|
|
* @param[in] address Address which we are reading from.
|
|
* @param[in] count Number of bytes to read.
|
|
* @param[in] offset Offset in bytes of @p address from the beginning of the
|
|
* segment.
|
|
* @param[in] arg Argument passed to @ref drgn_program_add_memory_segment().
|
|
* @param[in] physical Whether @c address is physical.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
typedef struct drgn_error *(*drgn_memory_read_fn)(void *buf, uint64_t address,
|
|
size_t count, uint64_t offset,
|
|
void *arg, bool physical);
|
|
|
|
/**
|
|
* Register a segment of memory in a @ref drgn_program.
|
|
*
|
|
* If the segment overlaps a previously registered segment, the new segment
|
|
* takes precedence. If any part of the segment is beyond the maximum address,
|
|
* that part is ignored.
|
|
*
|
|
* @param[in] address Address of the segment.
|
|
* @param[in] size Size of the segment in bytes.
|
|
* @param[in] read_fn Callback to read from segment.
|
|
* @param[in] arg Argument to pass to @p read_fn.
|
|
* @param[in] physical Whether to add a physical memory segment.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_program_add_memory_segment(struct drgn_program *prog, uint64_t address,
|
|
uint64_t size, drgn_memory_read_fn read_fn,
|
|
void *arg, bool physical);
|
|
|
|
/**
|
|
* Return whether a filename containing a definition (@p haystack) matches a
|
|
* filename being searched for (@p needle).
|
|
*
|
|
* The path is matched from right to left, so a definition in
|
|
* <tt>/usr/include/stdio.h</tt> will match <tt>stdio.h</tt>,
|
|
* <tt>include/stdio.h</tt>, <tt>usr/include/stdio.h</tt>, and
|
|
* <tt>/usr/include/stdio.h</tt>. An empty or @c NULL @p needle matches any @p
|
|
* haystack.
|
|
*/
|
|
bool drgn_filename_matches(const char *haystack, const char *needle);
|
|
|
|
/**
|
|
* Callback for finding a type.
|
|
*
|
|
* @param[in] kind Kind of type.
|
|
* @param[in] name Name of type (or tag, for structs, unions, and enums). This
|
|
* is @em not null-terminated.
|
|
* @param[in] name_len Length of @p name.
|
|
* @param[in] filename Filename containing the type definition or @c NULL. This
|
|
* should be matched with @ref drgn_filename_matches().
|
|
* @param[in] arg Argument passed to @ref drgn_program_add_type_finder().
|
|
* @param[out] ret Returned type.
|
|
* @return @c NULL on success, non-@c NULL on error. In particular, if the type
|
|
* is not found, this should return &@ref drgn_not_found; any other errors are
|
|
* considered fatal.
|
|
*/
|
|
typedef struct drgn_error *
|
|
(*drgn_type_find_fn)(enum drgn_type_kind kind, const char *name,
|
|
size_t name_len, const char *filename, void *arg,
|
|
struct drgn_qualified_type *ret);
|
|
|
|
/**
|
|
* Register a type finding callback.
|
|
*
|
|
* Callbacks are called in reverse order of the order they were added until the
|
|
* type is found. So, more recently added callbacks take precedence.
|
|
*
|
|
* @param[in] fn The callback.
|
|
* @param[in] arg Argument to pass to @p fn.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_program_add_type_finder(struct drgn_program *prog, drgn_type_find_fn fn,
|
|
void *arg);
|
|
|
|
/** Flags for @ref drgn_program_find_object(). */
|
|
enum drgn_find_object_flags {
|
|
/** Find a constant (e.g., enumeration constant or macro). */
|
|
DRGN_FIND_OBJECT_CONSTANT = 1 << 0,
|
|
/** Find a function. */
|
|
DRGN_FIND_OBJECT_FUNCTION = 1 << 1,
|
|
/** Find a variable. */
|
|
DRGN_FIND_OBJECT_VARIABLE = 1 << 2,
|
|
/** Find any kind of object. */
|
|
DRGN_FIND_OBJECT_ANY = (1 << 3) - 1,
|
|
};
|
|
|
|
/**
|
|
* Callback for finding an object.
|
|
*
|
|
* @param[in] name Name of object. This is @em not null-terminated.
|
|
* @param[in] name_len Length of @p name.
|
|
* @param[in] filename Filename containing the object definition or @c NULL.
|
|
* This should be matched with @ref drgn_filename_matches().
|
|
* @param[in] flags Flags indicating what kind of object to look for.
|
|
* @param[in] arg Argument passed to @ref drgn_program_add_object_finder().
|
|
* @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
|
|
* object is not found, this should return &@ref drgn_not_found; any other
|
|
* errors are considered fatal.
|
|
*/
|
|
typedef struct drgn_error *
|
|
(*drgn_object_find_fn)(const char *name, size_t name_len, const char *filename,
|
|
enum drgn_find_object_flags flags, void *arg,
|
|
struct drgn_object *ret);
|
|
|
|
/**
|
|
* Register a object finding callback.
|
|
*
|
|
* Callbacks are called in reverse order of the order they were added until the
|
|
* object is found. So, more recently added callbacks take precedence.
|
|
*
|
|
* @param[in] fn The callback.
|
|
* @param[in] arg Argument to pass to @p fn.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_program_add_object_finder(struct drgn_program *prog,
|
|
drgn_object_find_fn fn, void *arg);
|
|
|
|
/**
|
|
* Set a @ref drgn_program to a core dump.
|
|
*
|
|
* @sa drgn_program_from_core_dump()
|
|
*
|
|
* @param[in] path Core dump file path.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_set_core_dump(struct drgn_program *prog,
|
|
const char *path);
|
|
|
|
/**
|
|
* Set a @ref drgn_program to the running operating system kernel.
|
|
*
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_set_kernel(struct drgn_program *prog);
|
|
|
|
/**
|
|
* Set a @ref drgn_program to a running process.
|
|
*
|
|
* @sa drgn_program_from_pid()
|
|
*
|
|
* @param[in] pid Process ID.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_set_pid(struct drgn_program *prog, pid_t pid);
|
|
|
|
/**
|
|
* Load debugging information for a list of executable or library files.
|
|
*
|
|
* @param[in] load_default Whether to also load debugging information which can
|
|
* automatically be determined from the program. This implies @p load_main.
|
|
* @param[in] load_main Whether to also load information for the main
|
|
* executable.
|
|
*/
|
|
struct drgn_error *drgn_program_load_debug_info(struct drgn_program *prog,
|
|
const char **paths, size_t n,
|
|
bool load_default,
|
|
bool load_main);
|
|
|
|
/**
|
|
* Create a @ref drgn_program from a core dump file.
|
|
*
|
|
* The type of program (e.g., userspace or kernel) is determined automatically.
|
|
*
|
|
* @param[in] path Core dump file path.
|
|
* @param[out] ret Returned program.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_from_core_dump(const char *path,
|
|
struct drgn_program **ret);
|
|
|
|
/**
|
|
* Create a @ref drgn_program from the running operating system kernel.
|
|
*
|
|
* This requires root privileges.
|
|
*
|
|
* @param[out] ret Returned program.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_from_kernel(struct drgn_program **ret);
|
|
|
|
/**
|
|
* Create a @ref drgn_program from the a running program.
|
|
*
|
|
* On Linux, this requires @c PTRACE_MODE_ATTACH_FSCREDS permissions (see
|
|
* <tt>ptrace(2)</tt>).
|
|
*
|
|
* @param[in] pid Process ID of the program to debug.
|
|
* @param[out] ret Returned program.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_from_pid(pid_t pid, struct drgn_program **ret);
|
|
|
|
/** Get the set of @ref drgn_program_flags applying to a @ref drgn_program. */
|
|
enum drgn_program_flags drgn_program_flags(struct drgn_program *prog);
|
|
|
|
/**
|
|
* Get the platform of a @ref drgn_program.
|
|
*
|
|
* This remains valid until the program is destroyed. It should @em not be
|
|
* destroyed with @ref drgn_platform_destroy().
|
|
* @return non-@c NULL on success, @c NULL if the platform is not known yet.
|
|
*/
|
|
const struct drgn_platform *drgn_program_platform(struct drgn_program *prog);
|
|
|
|
/** Get the default language of a @ref drgn_program. */
|
|
const struct drgn_language *drgn_program_language(struct drgn_program *prog);
|
|
|
|
/** Set the default language of a @ref drgn_program. */
|
|
void drgn_program_set_language(struct drgn_program *prog,
|
|
const struct drgn_language *lang);
|
|
|
|
/**
|
|
* Read from a program's memory.
|
|
*
|
|
* @param[in] prog Program to read from.
|
|
* @param[out] buf Buffer to read into.
|
|
* @param[in] address Starting address in memory to read.
|
|
* @param[in] count Number of bytes to read.
|
|
* @param[in] physical Whether @c address is physical. A program may support
|
|
* only virtual or physical addresses or both.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_read_memory(struct drgn_program *prog,
|
|
void *buf, uint64_t address,
|
|
size_t count, bool physical);
|
|
|
|
/**
|
|
* Read a C string from a program's memory.
|
|
*
|
|
* This reads up to and including the terminating null byte.
|
|
*
|
|
* @param[in] prog Program to read from.
|
|
* @param[in] address Starting address in memory to read.
|
|
* @param[in] physical Whether @c address is physical. See @ref
|
|
* drgn_program_read_memory().
|
|
* @param[in] max_size Stop after this many bytes are read, not including the
|
|
* null byte. A null byte is appended to @p ret in this case.
|
|
* @param[out] ret Returned string. On success, it must be freed with @c free().
|
|
* On error, its contents are undefined.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_read_c_string(struct drgn_program *prog,
|
|
uint64_t address, bool physical,
|
|
size_t max_size, char **ret);
|
|
|
|
struct drgn_error *drgn_program_read_u8(struct drgn_program *prog,
|
|
uint64_t address, bool physical,
|
|
uint8_t *ret);
|
|
|
|
struct drgn_error *drgn_program_read_u16(struct drgn_program *prog,
|
|
uint64_t address, bool physical,
|
|
uint16_t *ret);
|
|
|
|
struct drgn_error *drgn_program_read_u32(struct drgn_program *prog,
|
|
uint64_t address, bool physical,
|
|
uint32_t *ret);
|
|
|
|
struct drgn_error *drgn_program_read_u64(struct drgn_program *prog,
|
|
uint64_t address, bool physical,
|
|
uint64_t *ret);
|
|
|
|
struct drgn_error *drgn_program_read_word(struct drgn_program *prog,
|
|
uint64_t address, bool physical,
|
|
uint64_t *ret);
|
|
|
|
/**
|
|
* Find a type in a program by name.
|
|
*
|
|
* The returned type is valid for the lifetime of the @ref drgn_program.
|
|
*
|
|
* @param[in] prog Program.
|
|
* @param[in] name Name of the type.
|
|
* @param[in] filename Filename containing the type definition. This is matched
|
|
* with @ref drgn_filename_matches(). If multiple definitions match, one is
|
|
* returned arbitrarily.
|
|
* @param[out] ret Returned type.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_find_type(struct drgn_program *prog,
|
|
const char *name,
|
|
const char *filename,
|
|
struct drgn_qualified_type *ret);
|
|
|
|
/**
|
|
* Find an object in a program by name.
|
|
*
|
|
* The object can be a variable, constant, or function depending on @p flags.
|
|
*
|
|
* @param[in] prog Program.
|
|
* @param[in] name Name of the object.
|
|
* @param[in] filename Filename containing the object definition. This is
|
|
* matched with @ref drgn_filename_matches(). If multiple definitions match, one
|
|
* is returned arbitrarily.
|
|
* @param[in] flags Flags indicating what kind of object to look for.
|
|
* @param[out] ret Returned object. This must have already been initialized with
|
|
* @ref drgn_object_init().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_find_object(struct drgn_program *prog,
|
|
const char *name,
|
|
const char *filename,
|
|
enum drgn_find_object_flags flags,
|
|
struct drgn_object *ret);
|
|
|
|
/**
|
|
* @ingroup Symbols
|
|
*
|
|
* @struct drgn_symbol
|
|
*
|
|
* A @ref drgn_symbol represents an entry in a program's symbol table.
|
|
*/
|
|
struct drgn_symbol;
|
|
|
|
/**
|
|
* Get the symbol containing the given address.
|
|
*
|
|
* @param[out] ret The returned symbol. It should be freed with @ref
|
|
* drgn_symbol_destroy().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_program_find_symbol_by_address(struct drgn_program *prog, uint64_t address,
|
|
struct drgn_symbol **ret);
|
|
|
|
/**
|
|
* Get the symbol corresponding to the given name.
|
|
*
|
|
* @param[out] ret The returned symbol. It should be freed with @ref
|
|
* drgn_symbol_destroy().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_find_symbol_by_name(struct drgn_program *prog,
|
|
const char *name,
|
|
struct drgn_symbol **ret);
|
|
|
|
/**
|
|
* Get all global and local symbols, optionally with the given name.
|
|
*
|
|
* @param[in] prog Program.
|
|
* @param[in] name Name to match. If @c NULL, returns all symbols.
|
|
* @param[out] syms_ret Returned array of symbols. On success, this must be
|
|
* freed with @ref drgn_symbols_destroy().
|
|
* @param[out] count_ret Returned number of symbols in @p syms_ret.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_find_symbols_by_name(struct drgn_program *prog,
|
|
const char *name,
|
|
struct drgn_symbol ***syms_ret,
|
|
size_t *count_ret);
|
|
|
|
/**
|
|
* Get all symbols containing the given address.
|
|
*
|
|
* @param[in] prog Program.
|
|
* @param[in] address Address to search for.
|
|
* @param[out] syms_ret Returned array of symbols. On success, this must be
|
|
* freed with @ref drgn_symbols_destroy().
|
|
* @param[out] count_ret Returned number of symbols in @p syms_ret.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_find_symbols_by_address(struct drgn_program *prog,
|
|
uint64_t address,
|
|
struct drgn_symbol ***syms_ret,
|
|
size_t *count_ret);
|
|
|
|
/** Element type and size. */
|
|
struct drgn_element_info {
|
|
/** Type of the element. */
|
|
struct drgn_qualified_type qualified_type;
|
|
/**
|
|
* Size in bits of one element.
|
|
*
|
|
* Element @c i is at bit offset <tt>i * bit_size</tt>.
|
|
*/
|
|
uint64_t bit_size;
|
|
};
|
|
|
|
/**
|
|
* Get the element type and size of an array or pointer @ref drgn_type.
|
|
*
|
|
* @param[in] prog Program.
|
|
* @param[in] type Array or pointer. After this function is called, this type
|
|
* must remain valid until the program is destroyed.
|
|
* @param[out] ret Returned element information.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_element_info(struct drgn_program *prog,
|
|
struct drgn_type *type,
|
|
struct drgn_element_info *ret);
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @defgroup Objects Objects
|
|
*
|
|
* Objects in a program.
|
|
*
|
|
* A @ref drgn_object represents an object (e.g., variable, constant, or
|
|
* function) in a program.
|
|
*
|
|
* Various operators and helpers are defined on objects; see @ref
|
|
* ObjectOperators and @ref ObjectHelpers.
|
|
*
|
|
* Many operations are language-specific. C is currently the only supported
|
|
* language.
|
|
*
|
|
* In drgn's emulation of C:
|
|
*
|
|
* - Signed and unsigned integer arithmetic is reduced modulo 2^width.
|
|
* - Integer division truncates towards zero.
|
|
* - Modulo has the sign of the dividend.
|
|
* - Division or modulo by 0 returns an error.
|
|
* - Shifts are reduced modulo 2^width. In particular, a shift by a value
|
|
* greater than the width returns 0.
|
|
* - Shifts by a negative number return an error.
|
|
* - Bitwise operators on signed integers act on the two's complement
|
|
* representation.
|
|
* - Pointer arithmetic is supported.
|
|
* - Integer literal have the first type of @c int, @c long, <tt>long long</tt>,
|
|
* and <tt>unsigned long long</tt> which can represent the value.
|
|
* - Boolean literals have type @c int (@b not @c _Bool).
|
|
* - Floating-point literals have type @c double.
|
|
* @{
|
|
*/
|
|
|
|
/** Kinds of objects. */
|
|
enum drgn_object_kind {
|
|
/** Constant or temporary computed value. */
|
|
DRGN_OBJECT_VALUE,
|
|
/** In program memory. */
|
|
DRGN_OBJECT_REFERENCE,
|
|
/** Absent (e.g. optimized out). */
|
|
DRGN_OBJECT_ABSENT,
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* Object encodings.
|
|
*
|
|
* The value of a @ref drgn_object may be encoded in various ways depending on
|
|
* its type. This determines which field of a @ref drgn_value is used.
|
|
*
|
|
* The incomplete encodings are only possible for reference objects; values have
|
|
* a complete type.
|
|
*/
|
|
enum drgn_object_encoding {
|
|
/**
|
|
* Memory buffer.
|
|
*
|
|
* This is used for objects with a structure, union, class, or array
|
|
* type. The value is a buffer of the contents of that object's memory
|
|
* in the program.
|
|
*/
|
|
DRGN_OBJECT_ENCODING_BUFFER,
|
|
/**
|
|
* Signed integer.
|
|
*
|
|
* This is used for objects with a signed integer or signed enumerated
|
|
* type.
|
|
*/
|
|
DRGN_OBJECT_ENCODING_SIGNED,
|
|
/**
|
|
* Unsigned integer.
|
|
*
|
|
* This is used for objects with a unsigned integer, boolean, or pointer
|
|
* type.
|
|
*/
|
|
DRGN_OBJECT_ENCODING_UNSIGNED,
|
|
/**
|
|
* Floating-point value.
|
|
*
|
|
* This used for objects with a floating-point type.
|
|
*/
|
|
DRGN_OBJECT_ENCODING_FLOAT,
|
|
/**
|
|
* No value.
|
|
*
|
|
* This is used for reference objects with a void or function type.
|
|
*/
|
|
DRGN_OBJECT_ENCODING_NONE = -1,
|
|
/**
|
|
* Incomplete buffer value.
|
|
*
|
|
* This is used for reference objects with an incomplete structure,
|
|
* union, class, or array type.
|
|
*/
|
|
DRGN_OBJECT_ENCODING_INCOMPLETE_BUFFER = -2,
|
|
/**
|
|
* Incomplete integer value.
|
|
*
|
|
* This is used for reference objects with an incomplete enumerated
|
|
* types.
|
|
*/
|
|
DRGN_OBJECT_ENCODING_INCOMPLETE_INTEGER = -3,
|
|
} __attribute__((__packed__));
|
|
|
|
/**
|
|
* Return whether a type corresponding to an object encoding is complete.
|
|
*
|
|
* @sa drgn_type_is_complete()
|
|
*/
|
|
static inline bool
|
|
drgn_object_encoding_is_complete(enum drgn_object_encoding encoding)
|
|
{
|
|
return encoding >= 0;
|
|
}
|
|
|
|
/** Value of a @ref drgn_object. */
|
|
union drgn_value {
|
|
/**
|
|
* Pointer to an external buffer for a @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_BUFFER value.
|
|
*/
|
|
char *bufp;
|
|
/**
|
|
* Inline buffer for a @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_BUFFER value.
|
|
*
|
|
* Tiny buffers (see @ref drgn_value_is_inline()) are stored inline here
|
|
* instead of in a separate allocation.
|
|
*/
|
|
char ibuf[8];
|
|
/** @ref drgn_object_encoding::DRGN_OBJECT_ENCODING_SIGNED value. */
|
|
int64_t svalue;
|
|
/** @ref drgn_object_encoding::DRGN_OBJECT_ENCODING_UNSIGNED value. */
|
|
uint64_t uvalue;
|
|
/** @ref drgn_object_encoding::DRGN_OBJECT_ENCODING_FLOAT value. */
|
|
double fvalue;
|
|
};
|
|
|
|
/**
|
|
* Return the number of bytes needed to store the given number of bits.
|
|
*
|
|
* @param[in] bits Number of bits.
|
|
*/
|
|
static inline uint64_t drgn_value_size(uint64_t bits)
|
|
{
|
|
return bits / CHAR_BIT + (bits % CHAR_BIT ? 1 : 0);
|
|
}
|
|
|
|
/**
|
|
* Return whether the given number of bits can be stored in the inline buffer of
|
|
* a @ref drgn_value (@ref drgn_value::ibuf).
|
|
*
|
|
* @param[in] bits Number of bits.
|
|
*/
|
|
static inline bool drgn_value_is_inline(uint64_t bits)
|
|
{
|
|
return bits <= CHAR_BIT * sizeof(((union drgn_value *)0)->ibuf);
|
|
}
|
|
|
|
/**
|
|
* Object in a program.
|
|
*
|
|
* A @ref drgn_object represents a symbol or value in a program. It can be in
|
|
* the memory of the program (a "reference"), a temporary computed value (a
|
|
* "value"), or "absent".
|
|
*
|
|
* A @ref drgn_object must be initialized with @ref drgn_object_init() before it
|
|
* is used. It can then be set and otherwise changed repeatedly. When the object
|
|
* is no longer needed, it must be deinitialized @ref drgn_object_deinit().
|
|
*
|
|
* It is more effecient to initialize an object once and reuse it rather than
|
|
* creating a new one repeatedly (e.g., in a loop).
|
|
*
|
|
* Members of a @ref drgn_object should not be modified except through the
|
|
* provided functions.
|
|
*/
|
|
struct drgn_object {
|
|
/** Type of this object. */
|
|
struct drgn_type *type;
|
|
/**
|
|
* Size of this object in bits.
|
|
*
|
|
* This is usually the size of @ref drgn_object::type, but it may be
|
|
* smaller if this is a bit field (@ref drgn_object::is_bit_field).
|
|
*/
|
|
uint64_t bit_size;
|
|
/** Qualifiers on @ref drgn_object::type. */
|
|
enum drgn_qualifiers qualifiers;
|
|
/** How this object is encoded. */
|
|
enum drgn_object_encoding encoding;
|
|
/** Kind of this object. */
|
|
enum drgn_object_kind kind;
|
|
/** Whether this object is a bit field. */
|
|
bool is_bit_field;
|
|
/**
|
|
* Whether this object is little-endian.
|
|
*
|
|
* Valid only for scalars (i.e., @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_SIGNED, @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_UNSIGNED, @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_FLOAT, or @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_INCOMPLETE_INTEGER).
|
|
*/
|
|
bool little_endian;
|
|
/**
|
|
* Offset in bits from @c address.
|
|
*
|
|
* Valid only for reference objects.
|
|
*/
|
|
uint8_t bit_offset;
|
|
union {
|
|
/** Value of value object. */
|
|
union drgn_value value;
|
|
/** Address of reference object. */
|
|
uint64_t address;
|
|
};
|
|
};
|
|
|
|
/** Return the number of bytes needed to store an object's value. */
|
|
static inline uint64_t drgn_object_size(const struct drgn_object *obj)
|
|
{
|
|
return drgn_value_size(obj->bit_size);
|
|
}
|
|
|
|
/**
|
|
* Return whether an object's value can be stored in the inline buffer of a @ref
|
|
* drgn_value (@ref drgn_value::ibuf).
|
|
*/
|
|
static inline bool drgn_object_is_inline(const struct drgn_object *obj)
|
|
{
|
|
return drgn_value_is_inline(obj->bit_size);
|
|
}
|
|
|
|
/** Return an object's buffer. */
|
|
#define drgn_object_buffer(obj) ({ \
|
|
__auto_type _obj = (obj); \
|
|
drgn_object_is_inline(_obj) ? _obj->value.ibuf : _obj->value.bufp; \
|
|
})
|
|
|
|
/** Get the type of a @ref drgn_object. */
|
|
static inline struct drgn_qualified_type
|
|
drgn_object_qualified_type(const struct drgn_object *obj)
|
|
{
|
|
return (struct drgn_qualified_type){
|
|
.type = obj->type,
|
|
.qualifiers = obj->qualifiers,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Initialize a @ref drgn_object.
|
|
*
|
|
* The object is initialized to a @c NULL reference with a void type. This must
|
|
* be paired with a call to @ref drgn_object_deinit().
|
|
*
|
|
* @param[in] obj Object to initialize.
|
|
* @param[in] prog Program containing the object.
|
|
*/
|
|
void drgn_object_init(struct drgn_object *obj, struct drgn_program *prog);
|
|
|
|
/**
|
|
* Deinitialize a @ref drgn_object.
|
|
*
|
|
* The object cannot be used after this unless it is reinitialized with @ref
|
|
* drgn_object_init().
|
|
*
|
|
* @param[in] obj Object to deinitialize.
|
|
*/
|
|
void drgn_object_deinit(struct drgn_object *obj);
|
|
|
|
/** Get the program that a @ref drgn_object is from. */
|
|
static inline struct drgn_program *
|
|
drgn_object_program(const struct drgn_object *obj)
|
|
{
|
|
return drgn_type_program(obj->type);
|
|
}
|
|
|
|
/** Get the language of a @ref drgn_object from its type. */
|
|
static inline const struct drgn_language *
|
|
drgn_object_language(const struct drgn_object *obj)
|
|
{
|
|
return drgn_type_language(obj->type);
|
|
}
|
|
|
|
/**
|
|
* @defgroup ObjectSetters Setters
|
|
*
|
|
* Object setters.
|
|
*
|
|
* Once a @ref drgn_object is initialized with @ref drgn_object_init(), it may
|
|
* be set any number of times.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Set a @ref drgn_object to a signed value.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] qualified_type Type to set to.
|
|
* @param[in] svalue Value to set to.
|
|
* @param[in] bit_field_size If the object should be a bit field, its size in
|
|
* bits. Otherwise, 0.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_object_set_signed(struct drgn_object *res,
|
|
struct drgn_qualified_type qualified_type,
|
|
int64_t svalue, uint64_t bit_field_size);
|
|
|
|
/**
|
|
* Set a @ref drgn_object to an unsigned value.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] qualified_type Type to set to.
|
|
* @param[in] uvalue Value to set to.
|
|
* @param[in] bit_field_size If the object should be a bit field, its size in
|
|
* bits. Otherwise, 0.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_object_set_unsigned(struct drgn_object *res,
|
|
struct drgn_qualified_type qualified_type,
|
|
uint64_t uvalue, uint64_t bit_field_size);
|
|
|
|
/**
|
|
* Set a @ref drgn_object to a floating-point value.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] qualified_type Type to set to.
|
|
* @param[in] fvalue Value to set to.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_object_set_float(struct drgn_object *res,
|
|
struct drgn_qualified_type qualified_type, double fvalue);
|
|
|
|
/**
|
|
* Set a @ref drgn_object from a buffer.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] qualified_type Type to set to.
|
|
* @param[in] buf Buffer to set to. It is copied, so it need not remain valid
|
|
* after this function returns.
|
|
* @param[in] buf_size Size of @p buf, in bytes. `buf_size * 8` must be at least
|
|
* `bit_size + bit_offset`, where @c bit_size is @p bit_field_size if non-zero
|
|
* and the size of @p qualified_type in bits otherwise.
|
|
* @param[in] bit_offset Offset of the value from the beginning of the buffer,
|
|
* in bits. This is usually 0. It must be aligned to a byte unless the type is
|
|
* scalar.
|
|
* @param[in] bit_field_size If the object should be a bit field, its size in
|
|
* bits. Otherwise, 0.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_object_set_from_buffer(struct drgn_object *res,
|
|
struct drgn_qualified_type qualified_type,
|
|
const void *buf, size_t buf_size,
|
|
uint64_t bit_offset, uint64_t bit_field_size);
|
|
|
|
/**
|
|
* Set a @ref drgn_object to a reference.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] qualified_type Type to set to.
|
|
* @param[in] address Address of the object.
|
|
* @param[in] bit_offset Offset of the value from @p address, in bits. This is
|
|
* usually 0.
|
|
* @param[in] bit_field_size If the object should be a bit field, its size in
|
|
* bits. Otherwise, 0.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_object_set_reference(struct drgn_object *res,
|
|
struct drgn_qualified_type qualified_type,
|
|
uint64_t address, uint64_t bit_offset,
|
|
uint64_t bit_field_size);
|
|
|
|
/**
|
|
* Set a @ref drgn_object as absent.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] qualified_type Type to set to.
|
|
* @param[in] bit_field_size If the object should be a bit field, its size in
|
|
* bits. Otherwise, 0.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_object_set_absent(struct drgn_object *res,
|
|
struct drgn_qualified_type qualified_type,
|
|
uint64_t bit_field_size);
|
|
|
|
/**
|
|
* Set a @ref drgn_object to a integer literal.
|
|
*
|
|
* This determines the type based on the programming language of the program
|
|
* that the object belongs to.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] uvalue Integer value.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_integer_literal(struct drgn_object *res,
|
|
uint64_t uvalue);
|
|
|
|
/**
|
|
* Set a @ref drgn_object to a boolean literal.
|
|
*
|
|
* This determines the type based on the programming language of the program
|
|
* that the object belongs to.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] bvalue Boolean value.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_bool_literal(struct drgn_object *res,
|
|
bool bvalue);
|
|
|
|
/**
|
|
* Set a @ref drgn_object to a floating-point literal.
|
|
*
|
|
* This determines the type based on the programming language of the program
|
|
* that the object belongs to.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] fvalue Floating-point value.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_float_literal(struct drgn_object *res,
|
|
double fvalue);
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @defgroup ObjectHelpers Helpers
|
|
*
|
|
* Object helpers.
|
|
*
|
|
* Several helpers are provided for working with @ref drgn_object%s.
|
|
*
|
|
* Helpers which return a @ref drgn_object have the same calling convention: the
|
|
* result object is the first argument, which must be initialized and may be the
|
|
* same as the input object argument; the result is only modified if the helper
|
|
* succeeds.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Set a @ref drgn_object to another object.
|
|
*
|
|
* This copies @c obj to @c res. If @c obj is a value, then @c res is set to a
|
|
* value with the same type and value, and similarly if @c obj was a reference,
|
|
* @c res is set to the same reference.
|
|
*
|
|
* @param[out] res Destination object.
|
|
* @param[in] obj Source object.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_copy(struct drgn_object *res,
|
|
const struct drgn_object *obj);
|
|
|
|
/**
|
|
* Get a @ref drgn_object from a slice of a @ref DRGN_OBJECT_ENCODING_BUFFER
|
|
* object.
|
|
*
|
|
* This is a low-level interface used to implement @ref drgn_object_subscript()
|
|
* and @ref drgn_object_member(). Those functions are usually more convenient.
|
|
*
|
|
* If multiple elements of an array are accessed (e.g., when iterating through
|
|
* it), it can be more efficient to call @ref drgn_program_element_info() once
|
|
* to get the required information and this function with the computed bit
|
|
* offset for each element.
|
|
*
|
|
* If the same member of a type is accessed repeatedly (e.g., in a loop), it can
|
|
* be more efficient to call @ref drgn_type_find_member() once to get the
|
|
* required information and this function to access the member each time.
|
|
*
|
|
* @sa drgn_object_dereference_offset
|
|
*
|
|
* @param[out] res Destination object.
|
|
* @param[in] obj Source object.
|
|
* @param[in] qualified_type Result type.
|
|
* @param[in] bit_offset Offset in bits from the beginning of @p obj.
|
|
* @param[in] bit_field_size If the object should be a bit field, its size in
|
|
* bits. Otherwise, 0.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_slice(struct drgn_object *res,
|
|
const struct drgn_object *obj,
|
|
struct drgn_qualified_type qualified_type,
|
|
uint64_t bit_offset,
|
|
uint64_t bit_field_size);
|
|
|
|
/**
|
|
* Get a @ref drgn_object from dereferencing a pointer object with an offset.
|
|
*
|
|
* This is a low-level interface used to implement @ref drgn_object_subscript()
|
|
* and @ref drgn_object_member_dereference(). Those functions are usually more
|
|
* convenient, but this function can be more efficient if accessing multiple
|
|
* elements or the same member multiple times.
|
|
*
|
|
* @sa drgn_object_slice
|
|
*
|
|
* @param[out] res Dereferenced object.
|
|
* @param[in] obj Pointer object.
|
|
* @param[in] qualified_type Result type.
|
|
* @param[in] bit_offset Offset in bits from the address given by the value of
|
|
* @p obj.
|
|
* @param[in] bit_field_size If the object should be a bit field, its size in
|
|
* bits. Otherwise, 0.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_object_dereference_offset(struct drgn_object *res,
|
|
const struct drgn_object *obj,
|
|
struct drgn_qualified_type qualified_type,
|
|
int64_t bit_offset, uint64_t bit_field_size);
|
|
|
|
/**
|
|
* Read a @ref drgn_object.
|
|
*
|
|
* If @c obj is already a value, then this is equivalent to @ref
|
|
* drgn_object_copy(). If @c is a reference, then this reads the reference and
|
|
* sets @p res to the value.
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] obj Object to read.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_read(struct drgn_object *res,
|
|
const struct drgn_object *obj);
|
|
|
|
/**
|
|
* Read the value of a @ref drgn_object.
|
|
*
|
|
* If @p obj is a value, that value is returned directly. If @p is a reference,
|
|
* the value is read into the provided temporary buffer.
|
|
*
|
|
* This must be paired with @ref drgn_object_deinit_value().
|
|
*
|
|
* @param[in] obj Object to read.
|
|
* @param[in] value Temporary value to use if necessary.
|
|
* @param[out] ret Pointer to the returned value, which is <tt>&obj->value</tt>
|
|
* if @p obj is a value, or @p value if @p obj is a reference.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_read_value(const struct drgn_object *obj,
|
|
union drgn_value *value,
|
|
const union drgn_value **ret);
|
|
|
|
/**
|
|
* Deinitialize a value which was read with @ref drgn_object_read_value().
|
|
*
|
|
* @param[in] obj Object which was read.
|
|
* @param[in] value Value returned from @ref drgn_object_read_value() in @p ret.
|
|
*/
|
|
void drgn_object_deinit_value(const struct drgn_object *obj,
|
|
const union drgn_value *value);
|
|
|
|
/**
|
|
* Get the binary representation of the value of a @ref drgn_object.
|
|
*
|
|
* @param[out] Buffer to read into. Size must be at least
|
|
* `drgn_object_size(obj)`.
|
|
*/
|
|
struct drgn_error *drgn_object_read_bytes(const struct drgn_object *obj,
|
|
void *buf);
|
|
|
|
/**
|
|
* Get the value of an object encoded with @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_SIGNED.
|
|
*
|
|
* If the object is not a signed integer, an error is returned.
|
|
*
|
|
* @param[in] obj Object to read.
|
|
* @param[out] ret Returned value.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_read_signed(const struct drgn_object *obj,
|
|
int64_t *ret);
|
|
|
|
/**
|
|
* Get the value of an object encoded with @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_UNSIGNED.
|
|
*
|
|
* If the object is not an unsigned integer, an error is returned.
|
|
*
|
|
* @param[in] obj Object to read.
|
|
* @param[out] ret Returned value.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_read_unsigned(const struct drgn_object *obj,
|
|
uint64_t *ret);
|
|
|
|
/**
|
|
* Get the value of an object encoded with @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_SIGNED or @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_UNSIGNED.
|
|
*
|
|
* If the object is not an integer, an error is returned.
|
|
*
|
|
* @param[in] obj Object to read.
|
|
* @param[out] ret Returned value.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_read_integer(const struct drgn_object *obj,
|
|
union drgn_value *ret);
|
|
|
|
/**
|
|
* Get the value of an object encoded with @ref
|
|
* drgn_object_encoding::DRGN_OBJECT_ENCODING_FLOAT.
|
|
*
|
|
* If the object does not have a floating-point type, an error is returned.
|
|
*
|
|
* @param[in] obj Object to read.
|
|
* @param[out] ret Returned value.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_read_float(const struct drgn_object *obj,
|
|
double *ret);
|
|
|
|
/**
|
|
* Read the null-terminated string pointed to by a @ref drgn_object.
|
|
*
|
|
* This is only valid for pointers and arrays. The element type is ignored; this
|
|
* operates byte-by-byte.
|
|
*
|
|
* For pointers and flexible arrays, this stops at the first null byte.
|
|
*
|
|
* For complete arrays, this stops at the first null byte or at the end of the
|
|
* array.
|
|
*
|
|
* The returned string is always null-terminated.
|
|
*
|
|
* @param[in] obj Object to read.
|
|
* @param[out] ret Returned string. On success, it must be freed with @c free().
|
|
* On error, its contents are undefined.
|
|
*/
|
|
struct drgn_error *drgn_object_read_c_string(const struct drgn_object *obj,
|
|
char **ret);
|
|
|
|
/** Flags to control @ref drgn_format_object() output. */
|
|
enum drgn_format_object_flags {
|
|
DRGN_FORMAT_OBJECT_DEREFERENCE = 1 << 0,
|
|
DRGN_FORMAT_OBJECT_SYMBOLIZE = 1 << 1,
|
|
DRGN_FORMAT_OBJECT_STRING = 1 << 2,
|
|
DRGN_FORMAT_OBJECT_CHAR = 1 << 3,
|
|
DRGN_FORMAT_OBJECT_TYPE_NAME = 1 << 4,
|
|
DRGN_FORMAT_OBJECT_MEMBER_TYPE_NAMES = 1 << 5,
|
|
DRGN_FORMAT_OBJECT_ELEMENT_TYPE_NAMES = 1 << 6,
|
|
DRGN_FORMAT_OBJECT_MEMBERS_SAME_LINE = 1 << 7,
|
|
DRGN_FORMAT_OBJECT_ELEMENTS_SAME_LINE = 1 << 8,
|
|
DRGN_FORMAT_OBJECT_MEMBER_NAMES = 1 << 9,
|
|
DRGN_FORMAT_OBJECT_ELEMENT_INDICES = 1 << 10,
|
|
DRGN_FORMAT_OBJECT_IMPLICIT_MEMBERS = 1 << 11,
|
|
DRGN_FORMAT_OBJECT_IMPLICIT_ELEMENTS = 1 << 12,
|
|
/** Default "pretty" flags. */
|
|
DRGN_FORMAT_OBJECT_PRETTY = (DRGN_FORMAT_OBJECT_DEREFERENCE |
|
|
DRGN_FORMAT_OBJECT_SYMBOLIZE |
|
|
DRGN_FORMAT_OBJECT_STRING |
|
|
DRGN_FORMAT_OBJECT_TYPE_NAME |
|
|
DRGN_FORMAT_OBJECT_MEMBER_TYPE_NAMES |
|
|
DRGN_FORMAT_OBJECT_ELEMENTS_SAME_LINE |
|
|
DRGN_FORMAT_OBJECT_MEMBER_NAMES |
|
|
DRGN_FORMAT_OBJECT_IMPLICIT_MEMBERS),
|
|
DRGN_FORMAT_OBJECT_VALID_FLAGS = (1 << 13) - 1,
|
|
};
|
|
|
|
/**
|
|
* Format a @ref drgn_object as a string.
|
|
*
|
|
* This will format the object similarly to an expression in its programming
|
|
* language.
|
|
*
|
|
* @param[in] obj Object to format.
|
|
* @param[in] columns Number of columns to limit output to when the expression
|
|
* can be reasonably wrapped.
|
|
* param[in] flags Flags to change output.
|
|
* @param[out] ret Returned string. On success, it must be freed with @c free().
|
|
* On error, its contents are undefined.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_format_object(const struct drgn_object *obj,
|
|
size_t columns,
|
|
enum drgn_format_object_flags flags,
|
|
char **ret);
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @defgroup ObjectOperators Operators
|
|
*
|
|
* Object operators.
|
|
*
|
|
* Various operators are defined on @ref drgn_object%s. These operators obey the
|
|
* rules of the programming language of the given objects.
|
|
*
|
|
* Operators which return a @ref drgn_object have the same calling convention:
|
|
* the result object is the first argument, which must be initialized and may be
|
|
* the same as one or more of the operands; the result is only modified if the
|
|
* operator succeeds.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* Set a @ref drgn_object to the value of an object casted to a another type.
|
|
*
|
|
* Objects with a scalar type can be casted to a different scalar type. Other
|
|
* objects can only be casted to the same type. @p res is always set to a value
|
|
* object.
|
|
*
|
|
* @sa drgn_object_reinterpret()
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] qualified_type New type.
|
|
* @param[in] obj Object to read.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_cast(struct drgn_object *res,
|
|
struct drgn_qualified_type qualified_type,
|
|
const struct drgn_object *obj);
|
|
|
|
/**
|
|
* Set a @ref drgn_object to the value of an object reinterpreted as another
|
|
* type.
|
|
*
|
|
* This reinterprets the raw memory of the object, so an object can be
|
|
* reinterpreted as any other type. However, value objects with a scalar type
|
|
* cannot be reinterpreted, as their memory layout is not known.
|
|
*
|
|
* If @c obj is a value, then @c res is set to a value; if @c obj was a
|
|
* reference, then @c res is set to a reference.
|
|
*
|
|
* @sa drgn_object_cast()
|
|
*
|
|
* @param[out] res Object to set.
|
|
* @param[in] qualified_type New type.
|
|
* @param[in] obj Object to reinterpret.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_object_reinterpret(struct drgn_object *res,
|
|
struct drgn_qualified_type qualified_type,
|
|
const struct drgn_object *obj);
|
|
|
|
/**
|
|
* @ref drgn_object binary operator.
|
|
*
|
|
* Binary operators apply any language-specific conversions to @p lhs and @p
|
|
* rhs, apply the operator, and store the result in @p res.
|
|
*
|
|
* @param[out] res Operator result. May be the same as @p lhs and/or @p rhs.
|
|
* @param[in] lhs Operator left hand side.
|
|
* @param[in] rhs Operator right hand side.
|
|
* @return @c NULL on success, non-@c NULL on error. @p res is not modified on
|
|
* error.
|
|
*/
|
|
typedef struct drgn_error *drgn_binary_op(struct drgn_object *res,
|
|
const struct drgn_object *lhs,
|
|
const struct drgn_object *rhs);
|
|
|
|
/**
|
|
* @ref drgn_object unary operator.
|
|
*
|
|
* Unary operators apply any language-specific conversions to @p obj, apply the
|
|
* operator, and store the result in @p res.
|
|
*
|
|
* @param[out] res Operator result. May be the same as @p obj.
|
|
* @param[in] obj Operand.
|
|
* @return @c NULL on success, non-@c NULL on error. @p res is not modified on
|
|
* error.
|
|
*/
|
|
typedef struct drgn_error *drgn_unary_op(struct drgn_object *res,
|
|
const struct drgn_object *obj);
|
|
|
|
/**
|
|
* Convert a @ref drgn_object to a boolean value.
|
|
*
|
|
* This gets the "truthiness" of an object according to its programming
|
|
* language.
|
|
*
|
|
* @param[in] obj Object.
|
|
* @param[out] ret Returned boolean value.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_bool(const struct drgn_object *obj, bool *ret);
|
|
|
|
/**
|
|
* Compare the value of two @ref drgn_object%s.
|
|
*
|
|
* This applies any language-specific conversions to @p lhs and @p rhs and
|
|
* compares the resulting values.
|
|
*
|
|
* @param[in] lhs Comparison left hand side.
|
|
* @param[in] rhs Comparison right hand side.
|
|
* @param[out] ret 0 if the operands are equal, < 0 if @p lhs < @p rhs, and > 0
|
|
* if @p lhs > @p rhs.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_cmp(const struct drgn_object *lhs,
|
|
const struct drgn_object *rhs, int *ret);
|
|
|
|
/** Add (@c +) two @ref drgn_object%s. */
|
|
drgn_binary_op drgn_object_add;
|
|
/** Subtract (@c -) a @ref drgn_object from another. */
|
|
drgn_binary_op drgn_object_sub;
|
|
/** Multiply (@c *) two @ref drgn_object%s. */
|
|
drgn_binary_op drgn_object_mul;
|
|
/** Divide (@c /) a @ref drgn_object by another. */
|
|
drgn_binary_op drgn_object_div;
|
|
/** Calculate the modulus (@c %) of two @ref drgn_object%s. */
|
|
drgn_binary_op drgn_object_mod;
|
|
/** Left shift (@c <<) a @ref drgn_object by another. */
|
|
drgn_binary_op drgn_object_lshift;
|
|
/** Right shift (@c >>) a @ref drgn_object by another. */
|
|
drgn_binary_op drgn_object_rshift;
|
|
/** Calculate the bitwise and (@c &) of two @ref drgn_object%s. */
|
|
drgn_binary_op drgn_object_and;
|
|
/** Calculate the bitwise or (@c |) of two @ref drgn_object%s. */
|
|
drgn_binary_op drgn_object_or;
|
|
/** Calculate the bitwise exclusive or (@c ^) of two @ref drgn_object%s. */
|
|
drgn_binary_op drgn_object_xor;
|
|
/** Apply unary plus (@c +) to a @ref drgn_object. */
|
|
drgn_unary_op drgn_object_pos;
|
|
/** Calculate the arithmetic negation (@c -) of a @ref drgn_object. */
|
|
drgn_unary_op drgn_object_neg;
|
|
/** Calculate the bitwise negation (@c ~) of a @ref drgn_object. */
|
|
drgn_unary_op drgn_object_not;
|
|
|
|
/**
|
|
* Get the address of (@c &) a @ref drgn_object as an object.
|
|
*
|
|
* This is only possible for reference objects, as value objects don't have an
|
|
* address in the program.
|
|
*
|
|
* @param[out] res Resulting pointer value. May be the same as @p obj.
|
|
* @param[in] obj Reference object.
|
|
* @return @c NULL on success, non-@c NULL on error. @p res is not modified on
|
|
* error.
|
|
*/
|
|
struct drgn_error *drgn_object_address_of(struct drgn_object *res,
|
|
const struct drgn_object *obj);
|
|
|
|
/**
|
|
* Subscript (@c []) a @ref drgn_object.
|
|
*
|
|
* This is applicable to pointers and arrays.
|
|
*
|
|
* @param[out] res Resulting element. May be the same as @p obj.
|
|
* @param[in] obj Object to subscript.
|
|
* @param[in] index Element index.
|
|
* @return @c NULL on success, non-@c NULL on error. @p res is not modified on
|
|
* error.
|
|
*/
|
|
struct drgn_error *drgn_object_subscript(struct drgn_object *res,
|
|
const struct drgn_object *obj,
|
|
int64_t index);
|
|
|
|
/**
|
|
* Deference (@c *) a @ref drgn_object.
|
|
*
|
|
* This is equivalent to @ref drgn_object_subscript with an index of 0.
|
|
*
|
|
* @param[out] res Deferenced object. May be the same as @p obj.
|
|
* @param[in] obj Object to dereference.
|
|
* @return @c NULL on success, non-@c NULL on error. @p res is not modified on
|
|
* error.
|
|
*/
|
|
static inline struct drgn_error *
|
|
drgn_object_dereference(struct drgn_object *res, const struct drgn_object *obj)
|
|
{
|
|
return drgn_object_subscript(res, obj, 0);
|
|
}
|
|
|
|
/**
|
|
* Get a member of a structure, union, or class @ref drgn_object (@c .).
|
|
*
|
|
* @param[out] res Returned member. May be the same as @p obj.
|
|
* @param[in] obj Object.
|
|
* @param[in] member_name Name of member.
|
|
* @return @c NULL on success, non-@c NULL on error. @p res is not modified on
|
|
* error.
|
|
*/
|
|
struct drgn_error *drgn_object_member(struct drgn_object *res,
|
|
const struct drgn_object *obj,
|
|
const char *member_name);
|
|
|
|
/**
|
|
* Get a member of a pointer @ref drgn_object (@c ->).
|
|
*
|
|
* This is applicable to pointers to structures and pointers to unions.
|
|
*
|
|
* @param[out] res Returned member. May be the same as @p obj.
|
|
* @param[in] obj Object.
|
|
* @param[in] member_name Name of member.
|
|
* @return @c NULL on success, non-@c NULL on error. @p res is not modified on
|
|
* error.
|
|
*/
|
|
struct drgn_error *drgn_object_member_dereference(struct drgn_object *res,
|
|
const struct drgn_object *obj,
|
|
const char *member_name);
|
|
|
|
|
|
/**
|
|
* Get the containing object of a member @ref drgn_object.
|
|
*
|
|
* This corresponds to the @c container_of() macro commonly used in C.
|
|
*
|
|
* @param[out] res Returned object. May be the same as @p obj.
|
|
* @param[in] obj Pointer to a member.
|
|
* @param[in] qualified_type Type which contains the member.
|
|
* @param[in] member_designator Name of the member in @p qualified_type. This
|
|
* can include one or more member references and zero or more array subscripts.
|
|
* @return @c NULL on success, non-@c NULL on error. @p res is not modified on
|
|
* error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_object_container_of(struct drgn_object *res, const struct drgn_object *obj,
|
|
struct drgn_qualified_type qualified_type,
|
|
const char *member_designator);
|
|
|
|
/**
|
|
* Get the size of a @ref drgn_object in bytes.
|
|
*
|
|
* @param[in] obj Object.
|
|
* @param[out] ret Returned size.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_object_sizeof(const struct drgn_object *obj,
|
|
uint64_t *ret);
|
|
|
|
/** @} */
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @ingroup LazyObjects
|
|
*
|
|
* Callback to evaluate and/or free a @ref drgn_lazy_object.
|
|
*
|
|
* If @p res is not @c NULL, then this should return the object in @p res and
|
|
* free @p arg if necessary. If this returns an error, it may be called again
|
|
* (so @p arg must remain valid).
|
|
*
|
|
* If @p res is @c NULL, then this should free @p arg if necessary; it must not
|
|
* return an error.
|
|
*
|
|
* @param[out] res Result object (if evaluating) or @c NULL (if freeing). This
|
|
* is already initialized and should not be deinitialized on error.
|
|
* @param[in] arg Callback argument passed to @ref
|
|
* drgn_lazy_object_init_thunk().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
typedef struct drgn_error *drgn_object_thunk_fn(struct drgn_object *res,
|
|
void *arg);
|
|
|
|
/**
|
|
* @ingroup LazyObjects
|
|
*
|
|
* Lazily-evaluated object.
|
|
*
|
|
* A lazy object may be in two states: unevaluated, in which case a callback
|
|
* must be called to evaluate the object, or evaluated, in which case the object
|
|
* is cached. To evaluate an object, the callback is called, and the result is
|
|
* cached.
|
|
*
|
|
* This is for internal use only.
|
|
*/
|
|
union drgn_lazy_object {
|
|
/** Object if it has already been evaluated. */
|
|
struct drgn_object obj;
|
|
/** Thunk if the object has not been evaluated yet. */
|
|
struct {
|
|
/**
|
|
* Always @c NULL to indicate an unevaluated lazy object.
|
|
*
|
|
* This must be at the same offset as @ref drgn_object::type.
|
|
*/
|
|
struct drgn_type *dummy_type;
|
|
/** Program owning this thunk. */
|
|
struct drgn_program *prog;
|
|
/** Callback. */
|
|
drgn_object_thunk_fn *fn;
|
|
/** Argument passed to @ref drgn_lazy_object::thunk::fn. */
|
|
void *arg;
|
|
} thunk;
|
|
};
|
|
|
|
/**
|
|
* @defgroup Types Types
|
|
*
|
|
* Type descriptors.
|
|
*
|
|
* Types in a program are represented by @ref drgn_type.
|
|
*
|
|
* Type descriptors have various fields depending on the kind of type. For each
|
|
* field @c foo, there is a @c drgn_type_kind_has_foo() helper which returns
|
|
* whether the given kind of type has the field @c foo; a @c drgn_type_has_foo()
|
|
* helper which does the same but takes a type; and a @c drgn_type_foo() helper
|
|
* which returns the field. For members, enumerators, and parameters, there is
|
|
* also a @c drgn_type_num_foo() helper.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/** Primitive types known to drgn. */
|
|
enum drgn_primitive_type {
|
|
/* Primitive C types. */
|
|
DRGN_C_TYPE_VOID,
|
|
DRGN_C_TYPE_CHAR,
|
|
DRGN_C_TYPE_SIGNED_CHAR,
|
|
DRGN_C_TYPE_UNSIGNED_CHAR,
|
|
DRGN_C_TYPE_SHORT,
|
|
DRGN_C_TYPE_UNSIGNED_SHORT,
|
|
DRGN_C_TYPE_INT,
|
|
DRGN_C_TYPE_UNSIGNED_INT,
|
|
DRGN_C_TYPE_LONG,
|
|
DRGN_C_TYPE_UNSIGNED_LONG,
|
|
DRGN_C_TYPE_LONG_LONG,
|
|
DRGN_C_TYPE_UNSIGNED_LONG_LONG,
|
|
DRGN_C_TYPE_BOOL,
|
|
DRGN_C_TYPE_FLOAT,
|
|
DRGN_C_TYPE_DOUBLE,
|
|
DRGN_C_TYPE_LONG_DOUBLE,
|
|
DRGN_C_TYPE_SIZE_T,
|
|
DRGN_C_TYPE_PTRDIFF_T,
|
|
DRGN_PRIMITIVE_TYPE_NUM,
|
|
DRGN_NOT_PRIMITIVE_TYPE = DRGN_PRIMITIVE_TYPE_NUM,
|
|
/*
|
|
* Make sure to update api_reference.rst and type.c when adding anything
|
|
* here.
|
|
*/
|
|
} __attribute__((__packed__));
|
|
|
|
/** Member of a structure, union, or class type. */
|
|
struct drgn_type_member {
|
|
/**
|
|
* Member as an object.
|
|
*
|
|
* Access this with @ref drgn_member_object() or @ref
|
|
* drgn_member_type().
|
|
*/
|
|
union drgn_lazy_object object;
|
|
/** Member name or @c NULL if it is unnamed. */
|
|
const char *name;
|
|
/**
|
|
* Offset in bits from the beginning of the type to the beginning of
|
|
* this member (i.e., for little-endian machines, the least significant
|
|
* bit, and for big-endian machines, the most significant bit). Members
|
|
* are usually aligned to at least a byte, so this is usually a multiple
|
|
* of 8 (but that may not be the case for bit fields).
|
|
*/
|
|
uint64_t bit_offset;
|
|
};
|
|
|
|
/** Value of an enumerated type. */
|
|
struct drgn_type_enumerator {
|
|
/** Enumerator name. */
|
|
const char *name;
|
|
union {
|
|
/** Enumerator value if the type is signed. */
|
|
int64_t svalue;
|
|
/** Enumerator value if the type is unsigned. */
|
|
uint64_t uvalue;
|
|
};
|
|
};
|
|
|
|
/** Parameter of a function type. */
|
|
struct drgn_type_parameter {
|
|
/**
|
|
* Parameter type and default argument.
|
|
*
|
|
* Access this with @ref drgn_parameter_default_argument() or @ref
|
|
* drgn_parameter_type().
|
|
*/
|
|
union drgn_lazy_object default_argument;
|
|
/** Parameter name or @c NULL if it is unnamed. */
|
|
const char *name;
|
|
};
|
|
|
|
/** Template parameter of a structure, union, class, or function type. */
|
|
struct drgn_type_template_parameter {
|
|
/**
|
|
* Template parameter type or value.
|
|
*
|
|
* Access this with @ref drgn_template_parameter_type() and @ref
|
|
* drgn_template_parameter_object().
|
|
*/
|
|
union drgn_lazy_object argument;
|
|
/** Template parameter name or @c NULL if it is unnamed. */
|
|
const char *name;
|
|
/** Whether the argument is the default. */
|
|
bool is_default;
|
|
};
|
|
|
|
/**
|
|
* Language-agnostic type descriptor.
|
|
*
|
|
* This structure should not be accessed directly; see @ref Types.
|
|
*/
|
|
struct drgn_type {
|
|
/** @privatesection */
|
|
struct {
|
|
enum drgn_type_kind kind;
|
|
bool is_complete;
|
|
enum drgn_primitive_type primitive;
|
|
/* These are the qualifiers for the wrapped type, not this type. */
|
|
enum drgn_qualifiers qualifiers;
|
|
struct drgn_program *program;
|
|
const struct drgn_language *language;
|
|
/*
|
|
* This mess of unions is used to make this as compact as possible. Use
|
|
* the provided helpers and don't think about it.
|
|
*/
|
|
union {
|
|
const char *name;
|
|
const char *tag;
|
|
size_t num_parameters;
|
|
};
|
|
union {
|
|
uint64_t size;
|
|
uint64_t length;
|
|
size_t num_enumerators;
|
|
bool is_variadic;
|
|
};
|
|
union {
|
|
bool is_signed;
|
|
size_t num_members;
|
|
struct drgn_type *type;
|
|
};
|
|
union {
|
|
bool little_endian;
|
|
struct drgn_type_member *members;
|
|
struct drgn_type_enumerator *enumerators;
|
|
struct drgn_type_parameter *parameters;
|
|
};
|
|
struct drgn_type_template_parameter *template_parameters;
|
|
size_t num_template_parameters;
|
|
} _private;
|
|
};
|
|
|
|
/** Get the kind of a type. */
|
|
static inline enum drgn_type_kind drgn_type_kind(struct drgn_type *type)
|
|
{
|
|
return type->_private.kind;
|
|
}
|
|
|
|
/** Get the primitive type corresponding to a @ref drgn_type. */
|
|
static inline enum drgn_primitive_type
|
|
drgn_type_primitive(struct drgn_type *type)
|
|
{
|
|
return type->_private.primitive;
|
|
}
|
|
|
|
/**
|
|
* Get whether a type is complete (i.e., the type definition is known).
|
|
*
|
|
* This is always @c false for the void type. It may be @c false for structure,
|
|
* union, class, enumerated, and array types, as well as typedef types where the
|
|
* underlying type is one of those. Otherwise, it is always @c true.
|
|
*/
|
|
static inline bool drgn_type_is_complete(struct drgn_type *type)
|
|
{
|
|
return type->_private.is_complete;
|
|
}
|
|
|
|
static inline struct drgn_program *
|
|
drgn_type_program(struct drgn_type *type)
|
|
{
|
|
return type->_private.program;
|
|
}
|
|
|
|
/** Get the language of a type. */
|
|
static inline const struct drgn_language *
|
|
drgn_type_language(struct drgn_type *type)
|
|
{
|
|
return type->_private.language;
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type has a name. This is true for integer, boolean,
|
|
* floating-point, and typedef types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_name(enum drgn_type_kind kind)
|
|
{
|
|
return (kind == DRGN_TYPE_INT ||
|
|
kind == DRGN_TYPE_BOOL ||
|
|
kind == DRGN_TYPE_FLOAT ||
|
|
kind == DRGN_TYPE_TYPEDEF);
|
|
}
|
|
/** Get whether a type has a name. @sa drgn_type_kind_has_name() */
|
|
static inline bool drgn_type_has_name(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_name(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the name of a type. @ref drgn_type_has_name() must be true for this type.
|
|
*/
|
|
static inline const char *drgn_type_name(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_name(type));
|
|
return type->_private.name;
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type has a size. This is true for integer, boolean,
|
|
* floating-point, structure, union, class, and pointer types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_size(enum drgn_type_kind kind)
|
|
{
|
|
return (kind == DRGN_TYPE_INT ||
|
|
kind == DRGN_TYPE_BOOL ||
|
|
kind == DRGN_TYPE_FLOAT ||
|
|
kind == DRGN_TYPE_STRUCT ||
|
|
kind == DRGN_TYPE_UNION ||
|
|
kind == DRGN_TYPE_CLASS ||
|
|
kind == DRGN_TYPE_POINTER);
|
|
}
|
|
/** Get whether a type has a size. @sa drgn_type_kind_has_size() */
|
|
static inline bool drgn_type_has_size(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_size(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the size of a type in bytes. @ref drgn_type_has_size() must be true for
|
|
* this type.
|
|
*/
|
|
static inline uint64_t drgn_type_size(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_size(type));
|
|
return type->_private.size;
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type has a signedness. This is true for integer types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_is_signed(enum drgn_type_kind kind)
|
|
{
|
|
return kind == DRGN_TYPE_INT;
|
|
}
|
|
/** Get whether a type has a signedness. @sa drgn_type_kind_has_is_signed() */
|
|
static inline bool drgn_type_has_is_signed(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_is_signed(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the signedness of a type. @ref drgn_type_has_is_signed() must be true for
|
|
* this type.
|
|
*/
|
|
static inline bool drgn_type_is_signed(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_is_signed(type));
|
|
return type->_private.is_signed;
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type has a byte order. This is true for integer,
|
|
* boolean, floating-point, and pointer types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_little_endian(enum drgn_type_kind kind)
|
|
{
|
|
return (kind == DRGN_TYPE_INT ||
|
|
kind == DRGN_TYPE_BOOL ||
|
|
kind == DRGN_TYPE_FLOAT ||
|
|
kind == DRGN_TYPE_POINTER);
|
|
}
|
|
/**
|
|
* Get whether a type has a byte order. @sa drgn_type_kind_has_little_endian()
|
|
*/
|
|
static inline bool drgn_type_has_little_endian(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_little_endian(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the byte order of a type. @ref drgn_type_has_little_endian() must be true
|
|
* for this type.
|
|
*
|
|
* @return @c true if the type is little-endian, @c false if it is big-endian.
|
|
*/
|
|
static inline bool drgn_type_little_endian(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_little_endian(type));
|
|
return type->_private.little_endian;
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type has a tag. This is true for structure, union,
|
|
* class, and enumerated types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_tag(enum drgn_type_kind kind)
|
|
{
|
|
return (kind == DRGN_TYPE_STRUCT ||
|
|
kind == DRGN_TYPE_UNION ||
|
|
kind == DRGN_TYPE_CLASS ||
|
|
kind == DRGN_TYPE_ENUM);
|
|
}
|
|
/** Get whether a type has a tag. @sa drgn_type_kind_has_tag() */
|
|
static inline bool drgn_type_has_tag(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_tag(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the tag of a type. @ref drgn_type_has_tag() must be true for this type.
|
|
*/
|
|
static inline const char *drgn_type_tag(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_tag(type));
|
|
return type->_private.tag;
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type has members. This is true for structure, union,
|
|
* and class types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_members(enum drgn_type_kind kind)
|
|
{
|
|
return (kind == DRGN_TYPE_STRUCT ||
|
|
kind == DRGN_TYPE_UNION ||
|
|
kind == DRGN_TYPE_CLASS);
|
|
}
|
|
/** Get whether a type has members. @sa drgn_type_kind_has_members() */
|
|
static inline bool drgn_type_has_members(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_members(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the members of a type. @ref drgn_type_has_members() must be true for this
|
|
* type.
|
|
*/
|
|
static inline struct drgn_type_member *drgn_type_members(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_members(type));
|
|
return type->_private.members;
|
|
}
|
|
/**
|
|
* Get the number of members of a type. @ref drgn_type_has_members() must be
|
|
* true for this type. If the type is incomplete, this is always zero.
|
|
*/
|
|
static inline size_t drgn_type_num_members(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_members(type));
|
|
return type->_private.num_members;
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type has a wrapped type. This is true for enumerated,
|
|
* typedef, pointer, array, and function types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_type(enum drgn_type_kind kind)
|
|
{
|
|
return (kind == DRGN_TYPE_ENUM ||
|
|
kind == DRGN_TYPE_TYPEDEF ||
|
|
kind == DRGN_TYPE_POINTER ||
|
|
kind == DRGN_TYPE_ARRAY ||
|
|
kind == DRGN_TYPE_FUNCTION);
|
|
}
|
|
/** Get whether a type has a wrapped type. @sa drgn_type_kind_has_type() */
|
|
static inline bool drgn_type_has_type(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_type(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the type wrapped by this type.
|
|
*
|
|
* For an enumerated type, this is the compatible integer type. It is @c NULL if
|
|
* the enumerated type is incomplete.
|
|
*
|
|
* For a typedef type, this is the aliased type.
|
|
*
|
|
* For a pointer type, this is the referenced type.
|
|
*
|
|
* For an array type, this is the element type.
|
|
*
|
|
* For a function type, this is the return type.
|
|
*/
|
|
static inline struct drgn_qualified_type
|
|
drgn_type_type(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_type(type));
|
|
return (struct drgn_qualified_type){
|
|
.type = type->_private.type,
|
|
.qualifiers = type->_private.qualifiers,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type has enumerators. This is true for enumerated
|
|
* types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_enumerators(enum drgn_type_kind kind)
|
|
{
|
|
return kind == DRGN_TYPE_ENUM;
|
|
}
|
|
/** Get whether a type has enumerators. @sa drgn_type_kind_has_enumerators() */
|
|
static inline bool drgn_type_has_enumerators(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_enumerators(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the enumerators of a type. @ref drgn_type_has_enumerators() must be true
|
|
* for this type.
|
|
*/
|
|
static inline struct drgn_type_enumerator *
|
|
drgn_type_enumerators(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_enumerators(type));
|
|
return type->_private.enumerators;
|
|
}
|
|
/**
|
|
* Get the number of enumerators of a type. @ref drgn_type_has_enumerators()
|
|
* must be true for this type. If the type is incomplete, this is always zero.
|
|
*/
|
|
static inline size_t drgn_type_num_enumerators(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_enumerators(type));
|
|
return type->_private.num_enumerators;
|
|
}
|
|
|
|
/** Get whether a kind of type has a length. This is true for array types. */
|
|
static inline bool drgn_type_kind_has_length(enum drgn_type_kind kind)
|
|
{
|
|
return kind == DRGN_TYPE_ARRAY;
|
|
}
|
|
/** Get whether a type has a length. @sa drgn_type_kind_has_length() */
|
|
static inline bool drgn_type_has_length(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_length(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the length of a type. @ref drgn_type_has_length() must be true for this
|
|
* type. If the type is incomplete, this is always zero.
|
|
*/
|
|
static inline uint64_t drgn_type_length(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_length(type));
|
|
return type->_private.length;
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type has parameters. This is true for function types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_parameters(enum drgn_type_kind kind)
|
|
{
|
|
return kind == DRGN_TYPE_FUNCTION;
|
|
}
|
|
/** Get whether a type has parameters. @sa drgn_type_kind_has_parameters() */
|
|
static inline bool drgn_type_has_parameters(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_parameters(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get the parameters of a type. @ref drgn_type_has_parameters() must be true
|
|
* for this type.
|
|
*/
|
|
static inline struct drgn_type_parameter *drgn_type_parameters(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_parameters(type));
|
|
return type->_private.parameters;
|
|
}
|
|
/**
|
|
* Get the number of parameters of a type. @ref drgn_type_has_parameters() must
|
|
* be true for this type.
|
|
*/
|
|
static inline size_t drgn_type_num_parameters(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_parameters(type));
|
|
return type->_private.num_parameters;
|
|
}
|
|
|
|
/**
|
|
* Get whether a kind of type can be variadic. This is true for function types.
|
|
*/
|
|
static inline bool drgn_type_kind_has_is_variadic(enum drgn_type_kind kind)
|
|
{
|
|
return kind == DRGN_TYPE_FUNCTION;
|
|
}
|
|
/** Get whether a type can be variadic. @sa drgn_type_kind_has_is_variadic() */
|
|
static inline bool drgn_type_has_is_variadic(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_is_variadic(drgn_type_kind(type));
|
|
}
|
|
/**
|
|
* Get whether a type is variadic. @ref drgn_type_has_is_variadic() must be true
|
|
* for this type.
|
|
*/
|
|
static inline bool drgn_type_is_variadic(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_is_variadic(type));
|
|
return type->_private.is_variadic;
|
|
}
|
|
|
|
/** Get whether a kind of type can have template parameters. */
|
|
static inline bool
|
|
drgn_type_kind_has_template_parameters(enum drgn_type_kind kind)
|
|
{
|
|
return (kind == DRGN_TYPE_STRUCT ||
|
|
kind == DRGN_TYPE_UNION ||
|
|
kind == DRGN_TYPE_CLASS ||
|
|
kind == DRGN_TYPE_FUNCTION);
|
|
}
|
|
|
|
/** Get whether a type can have template parameters. */
|
|
static inline bool drgn_type_has_template_parameters(struct drgn_type *type)
|
|
{
|
|
return drgn_type_kind_has_template_parameters(drgn_type_kind(type));
|
|
}
|
|
|
|
/**
|
|
* Get the template parameters of a type. @ref
|
|
* drgn_type_has_template_parameters() must be true for this type.
|
|
*/
|
|
static inline struct drgn_type_template_parameter *
|
|
drgn_type_template_parameters(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_template_parameters(type));
|
|
return type->_private.template_parameters;
|
|
}
|
|
|
|
/**
|
|
* Get the number of template parameters of a type. @ref
|
|
* drgn_type_has_template_parameters() must be true for this type.
|
|
*/
|
|
static inline size_t drgn_type_num_template_parameters(struct drgn_type *type)
|
|
{
|
|
assert(drgn_type_has_template_parameters(type));
|
|
return type->_private.num_template_parameters;
|
|
}
|
|
|
|
/**
|
|
* Get the object corresponding to a @ref drgn_type_member.
|
|
*
|
|
* @param[in] member Member.
|
|
* @param[out] ret Returned object.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_member_object(struct drgn_type_member *member,
|
|
const struct drgn_object **ret)
|
|
__attribute__((__nonnull__(1, 2)));
|
|
|
|
/**
|
|
* Get the type of a @ref drgn_type_member.
|
|
*
|
|
* @param[in] member Member.
|
|
* @param[out] type_ret Returned type.
|
|
* @param[out] bit_field_size_ret If the member is a bit field, returned size of
|
|
* the field in bits. Otherwise, returned as 0. Can be @c NULL if not needed.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_member_type(struct drgn_type_member *member,
|
|
struct drgn_qualified_type *type_ret,
|
|
uint64_t *bit_field_size_ret)
|
|
__attribute__((__nonnull__(1, 2)));
|
|
|
|
/**
|
|
* Get the default argument of a @ref drgn_type_parameter.
|
|
*
|
|
* @param[in] parameter Parameter.
|
|
* @param[out] ret Returned object.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_parameter_default_argument(struct drgn_type_parameter *parameter,
|
|
const struct drgn_object **ret)
|
|
__attribute__((__nonnull__(1, 2)));
|
|
|
|
/**
|
|
* Get the type of a @ref drgn_type_parameter.
|
|
*
|
|
* @param[in] parameter Parameter.
|
|
* @param[out] ret Returned type.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_parameter_type(struct drgn_type_parameter *parameter,
|
|
struct drgn_qualified_type *ret)
|
|
__attribute__((__nonnull__(1, 2)));
|
|
|
|
/**
|
|
* Get the type of a @ref drgn_type_template_parameter.
|
|
*
|
|
* If the template parameter is a non-type template parameter, this is the type
|
|
* of its value.
|
|
*
|
|
* @param[in] parameter Template parameter.
|
|
* @param[out] ret Returned type.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_template_parameter_type(struct drgn_type_template_parameter *parameter,
|
|
struct drgn_qualified_type *ret)
|
|
__attribute__((__nonnull__(1, 2)));
|
|
|
|
/**
|
|
* Get the value of a @ref drgn_type_template_parameter.
|
|
*
|
|
* @param[in] parameter Template parameter.
|
|
* @param[out] ret Returned object. If @p parameter is a type template
|
|
* parameter, this is returned as @c NULL.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_template_parameter_object(struct drgn_type_template_parameter *parameter,
|
|
const struct drgn_object **ret)
|
|
__attribute__((__nonnull__(1, 2)));
|
|
|
|
/**
|
|
* Get the size of a type in bytes.
|
|
*
|
|
* Unlike @ref drgn_type_size(), this is applicable to any type which has a
|
|
* meaningful size, including typedefs and arrays. Void, function, and
|
|
* incomplete types do not have a size; an error is returned for those types.
|
|
*
|
|
* @param[in] type Type.
|
|
* @param[out] ret Returned size.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_type_sizeof(struct drgn_type *type, uint64_t *ret);
|
|
|
|
/**
|
|
* Get the offset in bytes of a member from the start of a structure, union, or
|
|
* class type.
|
|
*
|
|
* This corresponds to @c offsetof() in C.
|
|
*
|
|
* @param[in] type Type which contains the member.
|
|
* @param[in] member_designator Name of the member in @p type. This can include
|
|
* one or more member references and zero or more array subscripts.
|
|
*/
|
|
struct drgn_error *drgn_type_offsetof(struct drgn_type *type,
|
|
const char *member_designator,
|
|
uint64_t *ret);
|
|
|
|
/**
|
|
* Like @ref drgn_type_find_member(), but takes the length of @p member_name.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_type_find_member_len(struct drgn_type *type, const char *member_name,
|
|
size_t member_name_len,
|
|
struct drgn_type_member **member_ret,
|
|
uint64_t *bit_offset_ret);
|
|
|
|
/**
|
|
* Find a member in a @ref drgn_type by name.
|
|
*
|
|
* If the type has any unnamed members, this also matches members of those
|
|
* unnamed members, recursively.
|
|
*
|
|
* @param[in] type Structure, union, or class type.
|
|
* @param[in] member_name Name of member.
|
|
* @param[out] member_ret Returned member.
|
|
* @param[out] bit_offset_ret Returned offset in bits from the beginning of @p
|
|
* type to the beginning of the member. This can be different from @ref
|
|
* drgn_type_member::bit_offset if the returned member was found in an unnamed
|
|
* member of @p type.
|
|
*/
|
|
static inline struct drgn_error *
|
|
drgn_type_find_member(struct drgn_type *type, const char *member_name,
|
|
struct drgn_type_member **member_ret,
|
|
uint64_t *bit_offset_ret)
|
|
{
|
|
return drgn_type_find_member_len(type, member_name, strlen(member_name),
|
|
member_ret, bit_offset_ret);
|
|
}
|
|
|
|
/** Like @ref drgn_type_has_member(), but takes the length of @p member_name. */
|
|
struct drgn_error *drgn_type_has_member_len(struct drgn_type *type,
|
|
const char *member_name,
|
|
size_t member_name_len, bool *ret);
|
|
|
|
/**
|
|
* Return whether a @ref drgn_type has a member with the given name.
|
|
*
|
|
* @param[in] type Structure, union, or class type.
|
|
* @param[in] member_name Name of member.
|
|
*/
|
|
static inline struct drgn_error *drgn_type_has_member(struct drgn_type *type,
|
|
const char *member_name,
|
|
bool *ret)
|
|
{
|
|
return drgn_type_has_member_len(type, member_name, strlen(member_name),
|
|
ret);
|
|
}
|
|
|
|
/**
|
|
* Format the name of a type as a string.
|
|
*
|
|
* This will format the name of the type as it would be referred to in its
|
|
* programming language.
|
|
*
|
|
* @param[in] qualified_type Type to format.
|
|
* @param[out] ret Returned string. On success, it must be freed with @c free().
|
|
* On error, its contents are undefined.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_format_type_name(struct drgn_qualified_type qualified_type, char **ret);
|
|
|
|
/**
|
|
* Format the definition of a type as a string.
|
|
*
|
|
* This will format the type as it would be defined in its programming language.
|
|
*
|
|
* @param[in] qualified_type Type to format.
|
|
* @param[out] ret Returned string. On success, it must be freed with @c free().
|
|
* On error, its contents are undefined.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_format_type(struct drgn_qualified_type qualified_type,
|
|
char **ret);
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @defgroup Symbols Symbols
|
|
*
|
|
* Symbol table entries.
|
|
*
|
|
* @sa drgn_program_find_symbol_by_address()
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/** Symbol linkage behavior and visibility. */
|
|
enum drgn_symbol_binding {
|
|
DRGN_SYMBOL_BINDING_UNKNOWN,
|
|
/*
|
|
* These values match the ELF STB_* definitions (offset by 1). This is
|
|
* an implementation detail; future values may not correspond 1:1 with
|
|
* ELF definitions.
|
|
*/
|
|
DRGN_SYMBOL_BINDING_LOCAL,
|
|
DRGN_SYMBOL_BINDING_GLOBAL,
|
|
DRGN_SYMBOL_BINDING_WEAK,
|
|
DRGN_SYMBOL_BINDING_UNIQUE = 11, /* STB_GNU_UNIQUE + 1 */
|
|
};
|
|
|
|
/** Kind of entity represented by a symbol. */
|
|
enum drgn_symbol_kind {
|
|
/*
|
|
* Like enum drgn_symbol_binding, these values match the ELF STT_*
|
|
* definitions, but this will not necessarily be true for future values.
|
|
*/
|
|
DRGN_SYMBOL_KIND_UNKNOWN,
|
|
DRGN_SYMBOL_KIND_OBJECT,
|
|
DRGN_SYMBOL_KIND_FUNC,
|
|
DRGN_SYMBOL_KIND_SECTION,
|
|
DRGN_SYMBOL_KIND_FILE,
|
|
DRGN_SYMBOL_KIND_COMMON,
|
|
DRGN_SYMBOL_KIND_TLS,
|
|
DRGN_SYMBOL_KIND_IFUNC = 10, /* STT_GNU_IFUNC */
|
|
};
|
|
|
|
/** Destroy a @ref drgn_symbol. */
|
|
void drgn_symbol_destroy(struct drgn_symbol *sym);
|
|
|
|
/**
|
|
* Destroy each @ref drgn_symbol in @syms, and free the array.
|
|
*
|
|
* This will ignore any @c NULL entry in the array, allowing you to take
|
|
* ownership of any symbol from the array prior to freeing the rest. For each
|
|
* symbol you take ownership of, you must free it with @ref
|
|
* drgn_symbol_destroy().
|
|
*/
|
|
void drgn_symbols_destroy(struct drgn_symbol **syms, size_t count);
|
|
|
|
/**
|
|
* Get the name of a @ref drgn_symbol.
|
|
*
|
|
* The returned string is valid until @p sym is destroyed. It should not be
|
|
* freed.
|
|
*/
|
|
const char *drgn_symbol_name(struct drgn_symbol *sym);
|
|
|
|
/** Get the start address of a @ref drgn_symbol. */
|
|
uint64_t drgn_symbol_address(struct drgn_symbol *sym);
|
|
|
|
/** Get the size in bytes of a @ref drgn_symbol. */
|
|
uint64_t drgn_symbol_size(struct drgn_symbol *sym);
|
|
|
|
/** Get the binding of a @ref drgn_symbol. */
|
|
enum drgn_symbol_binding drgn_symbol_binding(struct drgn_symbol *sym);
|
|
|
|
/** Get the kind of a @ref drgn_symbol. */
|
|
enum drgn_symbol_kind drgn_symbol_kind(struct drgn_symbol *sym);
|
|
|
|
/** Return whether two symbols are identical. */
|
|
bool drgn_symbol_eq(struct drgn_symbol *a, struct drgn_symbol *b);
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @defgroup StackTraces Stack traces
|
|
*
|
|
* Call stacks and stack frames.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
struct drgn_stack_trace;
|
|
|
|
/** Destroy a @ref drgn_stack_trace. */
|
|
void drgn_stack_trace_destroy(struct drgn_stack_trace *trace);
|
|
|
|
/** Get the number of stack frames in a stack trace. */
|
|
size_t drgn_stack_trace_num_frames(struct drgn_stack_trace *trace);
|
|
|
|
/**
|
|
* Format a stack trace as a string.
|
|
*
|
|
* @param[out] ret Returned string. On success, it must be freed with @c free().
|
|
* On error, its contents are undefined.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_format_stack_trace(struct drgn_stack_trace *trace,
|
|
char **ret);
|
|
|
|
/** Return whether a stack frame was interrupted (e.g., by a signal). */
|
|
bool drgn_stack_frame_interrupted(struct drgn_stack_trace *trace, size_t frame);
|
|
|
|
/**
|
|
* Format a stack frame as a string.
|
|
*
|
|
* @param[out] ret Returned string. On success, it must be freed with @c free().
|
|
* On error, its contents are undefined.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_format_stack_frame(struct drgn_stack_trace *trace,
|
|
size_t frame, char **ret);
|
|
|
|
/**
|
|
* Get the name of the function at a stack frame.
|
|
*
|
|
* @return Function name. This is valid until the stack trace is destroyed; it
|
|
* should not be freed. @c NULL if the name could not be determined.
|
|
*/
|
|
const char *drgn_stack_frame_name(struct drgn_stack_trace *trace, size_t frame);
|
|
|
|
/** Return whether a stack frame is for an inlined call. */
|
|
bool drgn_stack_frame_is_inline(struct drgn_stack_trace *trace, size_t frame);
|
|
|
|
/**
|
|
* Get the source code location of a stack frame.
|
|
*
|
|
* @param[out] line_ret Returned line number. Returned as 0 if unknown. May be
|
|
* @c NULL if not needed.
|
|
* @param[out] column_ret Returned column number. Returned as 0 if unknown. May
|
|
* be @c NULL if not needed.
|
|
* @return Filename. This is valid until the stack trace is destroyed; it should
|
|
* not be freed. @c NULL if the location could not be determined (in which case
|
|
* `*line_ret` and `*column_ret` are undefined).
|
|
*/
|
|
const char *drgn_stack_frame_source(struct drgn_stack_trace *trace,
|
|
size_t frame, int *line_ret,
|
|
int *column_ret);
|
|
|
|
/**
|
|
* Get the program counter at a stack frame.
|
|
*
|
|
* @param[out] ret Returned program counter.
|
|
* @return @c true if the program counter is known, @c false if it is not.
|
|
*/
|
|
bool drgn_stack_frame_pc(struct drgn_stack_trace *trace, size_t frame,
|
|
uint64_t *ret);
|
|
|
|
/**
|
|
* Get the function symbol at a stack frame.
|
|
*
|
|
* @param[out] ret Returned symbol. On success, it should be freed with @ref
|
|
* drgn_symbol_destroy(). On error, its contents are undefined.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_stack_frame_symbol(struct drgn_stack_trace *trace,
|
|
size_t frame,
|
|
struct drgn_symbol **ret);
|
|
|
|
/**
|
|
* Find an object in the scope of a stack frame.
|
|
*
|
|
* @param[in] name Object name.
|
|
* @param[out] ret Returned object. This must have already been initialized with
|
|
* @ref drgn_object_init().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_stack_frame_find_object(struct drgn_stack_trace *trace, size_t frame,
|
|
const char *name, struct drgn_object *ret);
|
|
|
|
/**
|
|
* Get the value of a register in a stack frame.
|
|
*
|
|
* @param[in] reg Register to get. Must be from the platform of the program that
|
|
* the trace was taken from.
|
|
* @param[out] ret Returned register value.
|
|
* @return @c true on success, @c false if the value is not known or the
|
|
* register is too large to return in a @c uint64_t.
|
|
*/
|
|
bool drgn_stack_frame_register(struct drgn_stack_trace *trace, size_t frame,
|
|
const struct drgn_register *reg, uint64_t *ret);
|
|
|
|
/**
|
|
* Get a stack trace for the thread with the given thread ID.
|
|
*
|
|
* @param[out] ret Returned stack trace. On success, it should be freed with
|
|
* @ref drgn_stack_trace_destroy(). On error, its contents are undefined.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_stack_trace(struct drgn_program *prog,
|
|
uint32_t tid,
|
|
struct drgn_stack_trace **ret);
|
|
|
|
/**
|
|
* Get a stack trace for the thread represented by @p obj.
|
|
*
|
|
* @sa drgn_program_stack_trace().
|
|
*/
|
|
struct drgn_error *drgn_object_stack_trace(const struct drgn_object *obj,
|
|
struct drgn_stack_trace **ret);
|
|
|
|
/** @} */
|
|
|
|
/**
|
|
* @defgroup Threads Threads
|
|
*
|
|
* Threads in a program.
|
|
*
|
|
* @{
|
|
*/
|
|
|
|
/**
|
|
* @struct drgn_thread
|
|
*
|
|
* A thread in a program.
|
|
*/
|
|
struct drgn_thread;
|
|
|
|
/**
|
|
* Create a copy of a @ref drgn_thread.
|
|
*
|
|
* @param[in] thread Thread to copy.
|
|
* @param[out] ret Returned copy. On success, must be destroyed with @ref
|
|
* drgn_thread_destroy().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_thread_dup(const struct drgn_thread *thread,
|
|
struct drgn_thread **ret);
|
|
|
|
/** Free a @ref drgn_thread. */
|
|
void drgn_thread_destroy(struct drgn_thread *thread);
|
|
|
|
/**
|
|
* @struct drgn_thread_iterator
|
|
*
|
|
* An iterator over all the threads in a program.
|
|
*/
|
|
struct drgn_thread_iterator;
|
|
|
|
/**
|
|
* Get an iterator over all of the threads in the program.
|
|
*
|
|
* @param[out] ret Returned iterator, which can be advanced with @ref
|
|
* drgn_thread_iterator_next, and must be destroyed with @ref
|
|
* drgn_thread_iterator_destroy.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *
|
|
drgn_thread_iterator_create(struct drgn_program *prog,
|
|
struct drgn_thread_iterator **ret);
|
|
|
|
/** Free a @ref drgn_thread_iterator. */
|
|
void drgn_thread_iterator_destroy(struct drgn_thread_iterator *it);
|
|
|
|
/**
|
|
* Get the next thread from a @ref drgn_thread_iterator.
|
|
*
|
|
* @param[out] ret Borrowed thread handle, or @c NULL if there are no more
|
|
* threads. This is valid until until the next call to @ref
|
|
* drgn_thread_iterator_next() with the same @p it, or until @p it is destroyed.
|
|
* It may be copied with @ref drgn_thread_dup() if it is needed for longer. This
|
|
* must NOT be destroyed with @ref drgn_thread_destroy().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_thread_iterator_next(struct drgn_thread_iterator *it,
|
|
struct drgn_thread **ret);
|
|
|
|
/**
|
|
* Get the thread with the given thread ID.
|
|
*
|
|
* @param[in] tid Thread ID.
|
|
* @param[out] ret New thread handle, or @c NULL if not found. On success, must
|
|
* be destroyed with @ref drgn_thread_destroy().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_find_thread(struct drgn_program *prog,
|
|
uint32_t tid,
|
|
struct drgn_thread **ret);
|
|
|
|
/**
|
|
* Get the main program thread.
|
|
*
|
|
* @param[out] ret Borrowed thread handle. This is valid for the lifetime of @p
|
|
* prog. This must NOT be destroyed with @ref drgn_thread_destroy().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_main_thread(struct drgn_program *prog,
|
|
struct drgn_thread **ret);
|
|
|
|
/**
|
|
* Get the thread that caused the program to crash.
|
|
*
|
|
* @param[out] ret Borrowed thread handle. This is valid for the lifetime of @p
|
|
* prog. This must NOT be destroyed with @ref drgn_thread_destroy().
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_program_crashed_thread(struct drgn_program *prog,
|
|
struct drgn_thread **ret);
|
|
|
|
/**
|
|
* Get the object for the given thread. This is currently only defined for the
|
|
* Linux kernel.
|
|
*
|
|
* @param[out] ret Returned object. This must not be modified and is valid for
|
|
* the lifetime of @p thread. It can be copied with @ref drgn_object_copy() if
|
|
* it is needed for longer.
|
|
* @return @c NULL on success, non-@c NULL on error.
|
|
*/
|
|
struct drgn_error *drgn_thread_object(struct drgn_thread *thread,
|
|
const struct drgn_object **ret);
|
|
|
|
/**
|
|
* Get a stack trace for the thread represented by @p thread.
|
|
*
|
|
* @sa drgn_program_stack_trace().
|
|
*/
|
|
struct drgn_error *drgn_thread_stack_trace(struct drgn_thread *thread,
|
|
struct drgn_stack_trace **ret);
|
|
|
|
/** @} */
|
|
|
|
#endif /* DRGN_H */
|