Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,9 @@ Some of drgn's behavior can be modified through environment variables:
``DRGN_USE_LIBKDUMPFILE_FOR_ELF``
Whether drgn should use libkdumpfile for ELF vmcores (0 or 1). The default
is 0. This functionality will be removed in the future.

``DRGN_USE_PROC_AND_SYS_MODULES``
Whether drgn should use ``/proc/modules`` and ``/sys/module`` to find
loaded kernel modules for the running kernel instead of getting them from
the core dump (0 or 1). The default is 1. This environment variable is
mainly intended for testing and may be ignored in the future.
294 changes: 176 additions & 118 deletions libdrgn/Doxyfile

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions libdrgn/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ ARCH_INS = arch_x86_64.c.in

libdrgnimpl_la_SOURCES = $(ARCH_INS:.c.in=.c) \
binary_search_tree.h \
bitops.h \
cityhash.h \
debug_info.c \
debug_info.h \
Expand All @@ -38,6 +39,7 @@ libdrgnimpl_la_SOURCES = $(ARCH_INS:.c.in=.c) \
linux_kernel_helpers.c \
memory_reader.c \
memory_reader.h \
minmax.h \
mread.h \
object.c \
object.h \
Expand All @@ -47,6 +49,7 @@ libdrgnimpl_la_SOURCES = $(ARCH_INS:.c.in=.c) \
path.h \
platform.c \
platform.h \
pp.h \
program.c \
program.h \
serialize.c \
Expand Down
134 changes: 134 additions & 0 deletions libdrgn/bitops.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright (c) Facebook, Inc. and its affiliates.
// SPDX-License-Identifier: GPL-3.0+

/**
* @file
*
* Bitwise operations.
*
* See @ref BitwiseOperations.
*/

#ifndef DRGN_BITOPS_H
#define DRGN_BITOPS_H

#include "pp.h"

/**
* @ingroup Internals
*
* @defgroup BitwiseOperations Bitwise operations
*
* Generic bitwise operations.
*
* @{
*/

/**
* Count Trailing Zero bits.
*
* Return the number of trailing least significant 0-bits in @p x. This is
* undefined if @p x is zero.
*
* ```
* ctz(1) == ctz(0b1) == 0
* ctz(2) == ctz(0b10) == 1
* ctz(12) == ctz(0b1100) == 2
* ```
*
* @param[in] x Integer.
*/
#define ctz(x) generic_bitop(x, PP_UNIQUE(_x), __builtin_ctz)

/**
* Find Last Set bit.
*
* Return the one-based index of the most significant 1-bit of @p x or 0 if @p x
* is 0.
*
* ```
* fls(0) == fls(0b0) == 0
* fls(1) == fls(0b1) == 1
* fls(13) == fls(0b1101) == 4
* ```
*
* For unsigned integers,
* ```
* fls(x) = floor(log2(x)) + 1, if x > 0
* 0, if x == 0
* ```
*
* @param[in] x Integer.
*/
#define fls(x) generic_bitop(x, PP_UNIQUE(_x), fls_)
/** @cond */
/*
* The straightfoward implementation is bits - clz. However, as noted by the
* folly implementation: "If X is a power of two, X - Y = 1 + ((X - 1) ^ Y).
* Doing this transformation allows GCC to remove its own xor that it adds to
* implement clz using bsr."
*
* This doesn't do the normal macro argument safety stuff because it should only
* be used via generic_bitop() which already does it.
*/
#define fls_impl(x, type, suffix) \
(x ? 1 + ((8 * sizeof(type) - 1) ^ __builtin_clz##suffix(x)) : 0)
#define fls_(x) fls_impl(x, unsigned int,)
#define fls_l(x) fls_impl(x, unsigned long, l)
#define fls_ll(x) fls_impl(x, unsigned long long, ll)

#define generic_bitop(x, unique_x, op) ({ \
__auto_type unique_x = (x); \
_Static_assert(sizeof(unique_x) <= sizeof(unsigned long long), \
"type is too large"); \
(unsigned int)(sizeof(unique_x) <= sizeof(unsigned int) ? \
op(unique_x) : \
sizeof(unique_x) <= sizeof(unsigned long) ? \
op##l(unique_x) : \
op##ll(unique_x)); \
})
/** @endcond */

/**
* Return the smallest power of two greater than or equal to @p x.
*
* ```
* next_power_of_two(0) == 1 // Zero is not a power of two
* next_power_of_two(1) == 1
* next_power_of_two(13) == 16
* ```
*
* @param[in] x Integer.
*/
#define next_power_of_two(x) next_power_of_two_impl(x, PP_UNIQUE(_x))
/** @cond */
#define next_power_of_two_impl(x, unique_x) ({ \
__auto_type unique_x = (x); \
unique_x ? (typeof(unique_x))1 << fls(unique_x - 1) : \
(typeof(unique_x))1; \
})
/** @endcond */

/**
* Iterate over each 1-bit in @p mask.
*
* On each iteration, this sets @p i to the zero-based index of the least
* significant 1-bit in @p mask and clears that bit in @p mask. It stops
* iterating when @p mask is zero.
*
* ```
* // Outputs 0 2 3
* unsigned int mask = 13, i;
* for_each_bit(i, mask)
* printf("%u ", i);
* ```
*
* @param[out] i Iteration variable name.
* @param[in,out] mask Integer to iterate over. This is modified.
*/
#define for_each_bit(i, mask) \
while (mask && (i = ctz(mask), mask &= mask - 1, 1))

/** @} */

#endif /* DRGN_BITOPS_H */
22 changes: 11 additions & 11 deletions libdrgn/debug_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#include <string.h>
#include <unistd.h>

#include "cityhash.h"
#include "debug_info.h"
#include "error.h"
#include "hash_table.h"
Expand All @@ -32,26 +31,27 @@
DEFINE_VECTOR_FUNCTIONS(drgn_debug_info_module_vector)

static inline struct hash_pair
drgn_debug_info_module_hash(const struct drgn_debug_info_module_key *key)
drgn_debug_info_module_key_hash_pair(const struct drgn_debug_info_module_key *key)
{
size_t hash = cityhash_size_t(key->build_id, key->build_id_len);
size_t hash = hash_bytes(key->build_id, key->build_id_len);
hash = hash_combine(hash, key->start);
hash = hash_combine(hash, key->end);
return hash_pair_from_avalanching_hash(hash);
}
static inline bool
drgn_debug_info_module_eq(const struct drgn_debug_info_module_key *a,
const struct drgn_debug_info_module_key *b)
drgn_debug_info_module_key_eq(const struct drgn_debug_info_module_key *a,
const struct drgn_debug_info_module_key *b)
{
return (a->build_id_len == b->build_id_len &&
memcmp(a->build_id, b->build_id, a->build_id_len) == 0 &&
a->start == b->start && a->end == b->end);
}
DEFINE_HASH_TABLE_FUNCTIONS(drgn_debug_info_module_table,
drgn_debug_info_module_hash,
drgn_debug_info_module_eq)
drgn_debug_info_module_key_hash_pair,
drgn_debug_info_module_key_eq)

DEFINE_HASH_TABLE_FUNCTIONS(c_string_set, c_string_hash, c_string_eq)
DEFINE_HASH_TABLE_FUNCTIONS(c_string_set, c_string_key_hash_pair,
c_string_key_eq)

/**
* @c Dwfl_Callbacks::find_elf() implementation.
Expand Down Expand Up @@ -338,7 +338,7 @@ drgn_debug_info_report_module(struct drgn_debug_info_load_state *load,
.start = start,
.end = end,
};
hp = drgn_debug_info_module_hash(&key);
hp = drgn_debug_info_module_table_hash(&key);
it = drgn_debug_info_module_table_search_hashed(&dbinfo->modules,
&key, hp);
if (it.entry &&
Expand Down Expand Up @@ -1019,8 +1019,8 @@ bool drgn_debug_info_is_indexed(struct drgn_debug_info *dbinfo,
return c_string_set_search(&dbinfo->module_names, &name).entry != NULL;
}

DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_type_map, hash_pair_ptr_type,
hash_table_scalar_eq)
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_type_map, ptr_key_hash_pair,
scalar_key_eq)

struct drgn_type_from_dwarf_thunk {
struct drgn_type_thunk thunk;
Expand Down
6 changes: 3 additions & 3 deletions libdrgn/debug_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
/**
* @ingroup Internals
*
* @defgroup DebugInfo Debugging information cache
* @defgroup DebugInfo Debugging information
*
* Caching of debugging information.
*
Expand Down Expand Up @@ -141,8 +141,8 @@ struct drgn_debug_info {
/**
* Names of indexed modules.
*
* The entries in this set are @ref drgn_dwarf_module::name, so they
* should not be freed.
* The entries in this set are @ref drgn_debug_info_module::name, so
* they should not be freed.
*/
struct c_string_set module_names;
/** Index of DWARF debugging information. */
Expand Down
13 changes: 6 additions & 7 deletions libdrgn/drgn.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ struct drgn_error {
* 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.
*/
Expand Down Expand Up @@ -1665,7 +1665,6 @@ struct drgn_object {
bool is_reference;
/** Whether this object is a bit field. */
bool is_bit_field;
/** Reference to this object in @ref drgn_object::prog, or its value. */
union {
/** Value. */
union drgn_value value;
Expand Down Expand Up @@ -1986,7 +1985,7 @@ drgn_object_dereference_offset(struct drgn_object *res,
*
* 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 @res to the value.
* sets @p res to the value.
*
* @param[out] res Object to set.
* @param[in] obj Object to read.
Expand Down Expand Up @@ -2366,9 +2365,9 @@ struct drgn_error *drgn_object_member_dereference(struct drgn_object *res,
*
* @param[out] res Returned object. May be the same as @p obj.
* @param[in] obj Pointer to a member.
* @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.
* @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.
*/
Expand Down
5 changes: 3 additions & 2 deletions libdrgn/dwarf_index.c
Original file line number Diff line number Diff line change
Expand Up @@ -121,10 +121,11 @@ static inline const char *section_end(Elf_Data *data)
return (const char *)data->d_buf + data->d_size;
}

DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_index_die_map, string_hash, string_eq)
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_index_die_map, string_hash_pair,
string_eq)
DEFINE_VECTOR_FUNCTIONS(drgn_dwarf_index_die_vector)
DEFINE_HASH_TABLE_FUNCTIONS(drgn_dwarf_index_specification_map,
hash_pair_int_type, hash_table_scalar_eq)
int_key_hash_pair, scalar_key_eq)

static inline size_t hash_pair_to_shard(struct hash_pair hp)
{
Expand Down
4 changes: 2 additions & 2 deletions libdrgn/dwarf_index.h
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,10 @@ struct drgn_dwarf_index_iterator {
};

/**
* Create an iterator over DIEs in a DWARF index.
* Create an iterator over DIEs in a DWARF index namespace.
*
* @param[out] it DWARF index iterator to initialize.
* @param[in] dindex DWARF index.
* @param[in] ns DWARF index namespace.
* @param[in] name Name of DIE to search for, or @c NULL for any name.
* @param[in] name_len Length of @c name.
* @param[in] tags List of DIE tags to search for.
Expand Down
Loading