Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
// Copyright 2018-2019 - Omar Sandoval
|
|
|
|
// SPDX-License-Identifier: GPL-3.0+
|
|
|
|
|
|
|
|
#include <byteswap.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <gelf.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <stdio.h>
|
2019-10-03 01:10:15 +01:00
|
|
|
#include <stdlib.h>
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/vfs.h>
|
|
|
|
|
|
|
|
#include "internal.h"
|
|
|
|
#include "dwarf_index.h"
|
2019-04-28 20:13:29 +01:00
|
|
|
#include "dwarf_info_cache.h"
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
#include "language.h"
|
2019-06-04 23:20:03 +01:00
|
|
|
#include "linux_kernel.h"
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
#include "memory_reader.h"
|
2019-07-24 00:26:29 +01:00
|
|
|
#include "object_index.h"
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
#include "program.h"
|
|
|
|
#include "read.h"
|
2019-05-10 07:53:16 +01:00
|
|
|
#include "string_builder.h"
|
2019-07-25 08:47:13 +01:00
|
|
|
#include "symbol.h"
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
#include "type_index.h"
|
2019-07-09 23:50:45 +01:00
|
|
|
#include "vector.h"
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-10-24 22:26:45 +01:00
|
|
|
DEFINE_HASH_TABLE_FUNCTIONS(drgn_prstatus_map, hash_pair_int_type,
|
|
|
|
hash_table_scalar_eq)
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
static Elf_Type note_header_type(GElf_Phdr *phdr)
|
|
|
|
{
|
|
|
|
if (phdr->p_align == 8)
|
|
|
|
return ELF_T_NHDR8;
|
|
|
|
return ELF_T_NHDR;
|
|
|
|
}
|
|
|
|
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
LIBDRGN_PUBLIC enum drgn_program_flags
|
|
|
|
drgn_program_flags(struct drgn_program *prog)
|
|
|
|
{
|
|
|
|
return prog->flags;
|
|
|
|
}
|
|
|
|
|
2019-07-29 08:57:28 +01:00
|
|
|
LIBDRGN_PUBLIC const struct drgn_platform *
|
|
|
|
drgn_program_platform(struct drgn_program *prog)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
{
|
2019-07-29 08:57:28 +01:00
|
|
|
return prog->has_platform ? &prog->platform : NULL;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
|
|
|
|
2019-08-02 08:00:59 +01:00
|
|
|
void drgn_program_set_platform(struct drgn_program *prog,
|
|
|
|
const struct drgn_platform *platform)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
{
|
2019-07-29 08:57:28 +01:00
|
|
|
if (!prog->has_platform) {
|
|
|
|
prog->platform = *platform;
|
|
|
|
prog->has_platform = true;
|
2019-05-10 07:53:16 +01:00
|
|
|
prog->tindex.word_size =
|
2019-07-29 08:57:28 +01:00
|
|
|
platform->flags & DRGN_PLATFORM_IS_64_BIT ? 8 : 4;
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
void drgn_program_init(struct drgn_program *prog,
|
2019-07-29 08:57:28 +01:00
|
|
|
const struct drgn_platform *platform)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
{
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
memset(prog, 0, sizeof(*prog));
|
2019-05-01 19:22:59 +01:00
|
|
|
drgn_memory_reader_init(&prog->reader);
|
|
|
|
drgn_type_index_init(&prog->tindex);
|
2019-07-24 00:26:29 +01:00
|
|
|
drgn_object_index_init(&prog->oindex);
|
2019-05-10 07:53:16 +01:00
|
|
|
prog->core_fd = -1;
|
2019-10-24 22:26:45 +01:00
|
|
|
drgn_prstatus_map_init(&prog->prstatus_cache);
|
2019-07-29 08:57:28 +01:00
|
|
|
if (platform)
|
|
|
|
drgn_program_set_platform(prog, platform);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void drgn_program_deinit(struct drgn_program *prog)
|
|
|
|
{
|
2019-10-24 22:26:45 +01:00
|
|
|
drgn_prstatus_map_deinit(&prog->prstatus_cache);
|
|
|
|
|
2019-07-24 00:26:29 +01:00
|
|
|
drgn_object_index_deinit(&prog->oindex);
|
2019-05-01 19:22:59 +01:00
|
|
|
drgn_type_index_deinit(&prog->tindex);
|
|
|
|
drgn_memory_reader_deinit(&prog->reader);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
free(prog->file_segments);
|
|
|
|
|
2019-08-02 08:00:59 +01:00
|
|
|
#ifdef WITH_LIBKDUMPFILE
|
|
|
|
if (prog->kdump_ctx)
|
|
|
|
kdump_free(prog->kdump_ctx);
|
|
|
|
#endif
|
2019-10-24 21:13:01 +01:00
|
|
|
elf_end(prog->core);
|
2019-05-10 07:53:16 +01:00
|
|
|
if (prog->core_fd != -1)
|
|
|
|
close(prog->core_fd);
|
2019-04-23 09:46:24 +01:00
|
|
|
|
2019-07-17 22:16:38 +01:00
|
|
|
drgn_dwarf_info_cache_destroy(prog->_dicache);
|
2019-04-23 09:46:24 +01:00
|
|
|
}
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
2019-07-29 08:57:28 +01:00
|
|
|
drgn_program_create(const struct drgn_platform *platform,
|
2019-05-10 07:53:16 +01:00
|
|
|
struct drgn_program **ret)
|
2019-04-23 09:46:24 +01:00
|
|
|
{
|
2019-05-10 07:53:16 +01:00
|
|
|
struct drgn_program *prog;
|
2019-04-23 09:46:24 +01:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
prog = malloc(sizeof(*prog));
|
|
|
|
if (!prog)
|
2019-04-23 09:46:24 +01:00
|
|
|
return &drgn_enomem;
|
2019-07-29 08:57:28 +01:00
|
|
|
drgn_program_init(prog, platform);
|
2019-05-10 07:53:16 +01:00
|
|
|
*ret = prog;
|
2019-04-23 09:46:24 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
LIBDRGN_PUBLIC void drgn_program_destroy(struct drgn_program *prog)
|
2019-04-23 09:46:24 +01:00
|
|
|
{
|
2019-05-10 07:53:16 +01:00
|
|
|
if (prog) {
|
|
|
|
drgn_program_deinit(prog);
|
|
|
|
free(prog);
|
2019-04-23 09:46:24 +01:00
|
|
|
}
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
2019-05-24 09:16:25 +01:00
|
|
|
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)
|
2019-05-01 19:22:59 +01:00
|
|
|
{
|
2019-05-24 09:16:25 +01:00
|
|
|
return drgn_memory_reader_add_segment(&prog->reader, address, size,
|
|
|
|
read_fn, arg, physical);
|
2019-05-01 19:22:59 +01:00
|
|
|
}
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
2019-05-01 19:22:59 +01:00
|
|
|
drgn_program_add_type_finder(struct drgn_program *prog, drgn_type_find_fn fn,
|
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
return drgn_type_index_add_finder(&prog->tindex, fn, arg);
|
|
|
|
}
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
2019-07-24 00:26:29 +01:00
|
|
|
drgn_program_add_object_finder(struct drgn_program *prog,
|
|
|
|
drgn_object_find_fn fn, void *arg)
|
2019-05-01 19:22:59 +01:00
|
|
|
{
|
2019-07-24 00:26:29 +01:00
|
|
|
return drgn_object_index_add_finder(&prog->oindex, fn, arg);
|
2019-05-01 19:22:59 +01:00
|
|
|
}
|
|
|
|
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
static struct drgn_error *
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_program_check_initialized(struct drgn_program *prog)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
{
|
2019-05-24 09:16:25 +01:00
|
|
|
if (prog->core_fd != -1 || !drgn_memory_reader_empty(&prog->reader)) {
|
2019-05-10 07:53:16 +01:00
|
|
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
2019-05-24 09:16:25 +01:00
|
|
|
"program memory was already initialized");
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-08-02 08:00:59 +01:00
|
|
|
static struct drgn_error *has_kdump_signature(const char *path, int fd,
|
|
|
|
bool *ret)
|
|
|
|
{
|
|
|
|
char signature[KDUMP_SIG_LEN];
|
|
|
|
size_t n = 0;
|
|
|
|
|
|
|
|
while (n < sizeof(signature)) {
|
|
|
|
ssize_t sret;
|
|
|
|
|
|
|
|
sret = pread(fd, signature + n, sizeof(signature) - n, n);
|
|
|
|
if (sret == -1) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
|
|
|
return drgn_error_create_os("pread", errno, path);
|
|
|
|
} else if (sret == 0) {
|
|
|
|
*ret = false;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
n += sret;
|
|
|
|
}
|
|
|
|
*ret = memcmp(signature, KDUMP_SIGNATURE, sizeof(signature)) == 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
|
|
|
drgn_program_set_core_dump(struct drgn_program *prog, const char *path)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
GElf_Ehdr ehdr_mem, *ehdr;
|
2019-07-29 08:57:28 +01:00
|
|
|
struct drgn_platform platform;
|
2019-08-02 08:00:59 +01:00
|
|
|
bool is_64_bit, is_kdump;
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
size_t phnum, i;
|
2019-10-03 01:10:15 +01:00
|
|
|
size_t num_file_segments;
|
2019-05-10 07:53:16 +01:00
|
|
|
bool have_non_zero_phys_addr = false;
|
|
|
|
struct drgn_memory_file_segment *current_file_segment;
|
2019-10-03 01:10:15 +01:00
|
|
|
const char *vmcoreinfo_note = NULL;
|
|
|
|
size_t vmcoreinfo_size = 0;
|
|
|
|
bool have_nt_taskstruct = false, is_proc_kcore;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_program_check_initialized(prog);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
prog->core_fd = open(path, O_RDONLY);
|
|
|
|
if (prog->core_fd == -1)
|
2019-07-11 23:58:23 +01:00
|
|
|
return drgn_error_create_os("open", errno, path);
|
2019-05-10 07:53:16 +01:00
|
|
|
|
2019-08-02 08:00:59 +01:00
|
|
|
err = has_kdump_signature(path, prog->core_fd, &is_kdump);
|
|
|
|
if (err)
|
|
|
|
goto out_fd;
|
|
|
|
if (is_kdump) {
|
|
|
|
err = drgn_program_set_kdump(prog);
|
|
|
|
if (err)
|
|
|
|
goto out_fd;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
elf_version(EV_CURRENT);
|
|
|
|
|
2019-10-24 21:13:01 +01:00
|
|
|
prog->core = elf_begin(prog->core_fd, ELF_C_READ, NULL);
|
|
|
|
if (!prog->core) {
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_error_libelf();
|
|
|
|
goto out_fd;
|
|
|
|
}
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-10-24 21:13:01 +01:00
|
|
|
ehdr = gelf_getehdr(prog->core, &ehdr_mem);
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
if (!ehdr || ehdr->e_type != ET_CORE) {
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT,
|
|
|
|
"not an ELF core file");
|
|
|
|
goto out_elf;
|
|
|
|
}
|
|
|
|
|
2019-07-29 08:57:28 +01:00
|
|
|
drgn_platform_from_elf(ehdr, &platform);
|
2019-05-10 07:53:16 +01:00
|
|
|
is_64_bit = ehdr->e_ident[EI_CLASS] == ELFCLASS64;
|
|
|
|
|
2019-10-24 21:13:01 +01:00
|
|
|
if (elf_getphdrnum(prog->core, &phnum) != 0) {
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_error_libelf();
|
|
|
|
goto out_elf;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2019-10-03 01:10:15 +01:00
|
|
|
* First pass: count the number of loadable segments, check if p_paddr
|
|
|
|
* is valid, and check for notes.
|
2019-05-10 07:53:16 +01:00
|
|
|
*/
|
2019-10-03 01:10:15 +01:00
|
|
|
num_file_segments = 0;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
for (i = 0; i < phnum; i++) {
|
|
|
|
GElf_Phdr phdr_mem, *phdr;
|
|
|
|
|
2019-10-24 21:13:01 +01:00
|
|
|
phdr = gelf_getphdr(prog->core, i, &phdr_mem);
|
2019-05-10 07:53:16 +01:00
|
|
|
if (!phdr) {
|
|
|
|
err = drgn_error_libelf();
|
2019-10-03 01:10:15 +01:00
|
|
|
goto out_elf;
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
if (phdr->p_type == PT_LOAD) {
|
|
|
|
if (phdr->p_paddr)
|
|
|
|
have_non_zero_phys_addr = true;
|
2019-10-03 01:10:15 +01:00
|
|
|
num_file_segments++;
|
|
|
|
} else if (phdr->p_type == PT_NOTE) {
|
|
|
|
Elf_Data *data;
|
|
|
|
size_t offset;
|
|
|
|
GElf_Nhdr nhdr;
|
|
|
|
size_t name_offset, desc_offset;
|
|
|
|
|
2019-10-24 21:13:01 +01:00
|
|
|
data = elf_getdata_rawchunk(prog->core, phdr->p_offset,
|
2019-10-03 01:10:15 +01:00
|
|
|
phdr->p_filesz,
|
|
|
|
note_header_type(phdr));
|
|
|
|
if (!data) {
|
|
|
|
err = drgn_error_libelf();
|
|
|
|
goto out_elf;
|
|
|
|
}
|
|
|
|
|
|
|
|
offset = 0;
|
|
|
|
while (offset < data->d_size &&
|
|
|
|
(offset = gelf_getnote(data, offset, &nhdr,
|
|
|
|
&name_offset,
|
|
|
|
&desc_offset))) {
|
|
|
|
const char *name, *desc;
|
|
|
|
|
|
|
|
name = (char *)data->d_buf + name_offset;
|
|
|
|
desc = (char *)data->d_buf + desc_offset;
|
|
|
|
if (strncmp(name, "CORE", nhdr.n_namesz) == 0) {
|
|
|
|
if (nhdr.n_type == NT_TASKSTRUCT)
|
|
|
|
have_nt_taskstruct = true;
|
|
|
|
} else if (strncmp(name, "VMCOREINFO",
|
|
|
|
nhdr.n_namesz) == 0) {
|
|
|
|
vmcoreinfo_note = desc;
|
|
|
|
vmcoreinfo_size = nhdr.n_descsz;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (have_nt_taskstruct) {
|
|
|
|
/*
|
|
|
|
* If the core file has an NT_TASKSTRUCT note and is in /proc,
|
|
|
|
* then it's probably /proc/kcore.
|
|
|
|
*/
|
|
|
|
struct statfs fs;
|
|
|
|
|
|
|
|
if (fstatfs(prog->core_fd, &fs) == -1) {
|
|
|
|
err = drgn_error_create_os("fstatfs", errno, path);
|
|
|
|
if (err)
|
|
|
|
goto out_elf;
|
|
|
|
}
|
|
|
|
is_proc_kcore = fs.f_type == 0x9fa0; /* PROC_SUPER_MAGIC */
|
|
|
|
} else {
|
|
|
|
is_proc_kcore = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vmcoreinfo_note && !is_proc_kcore) {
|
|
|
|
char *env;
|
|
|
|
bool use_libkdumpfile;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Use libkdumpfile for ELF vmcores if we were compiled with
|
|
|
|
* libkdumpfile support unless specified otherwise.
|
|
|
|
*/
|
|
|
|
env = getenv("DRGN_USE_LIBKDUMPFILE_FOR_ELF");
|
|
|
|
if (env) {
|
|
|
|
use_libkdumpfile = atoi(env);
|
|
|
|
} else {
|
|
|
|
#ifdef WITH_LIBKDUMPFILE
|
|
|
|
use_libkdumpfile = true;
|
|
|
|
#else
|
|
|
|
use_libkdumpfile = false;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
if (use_libkdumpfile) {
|
2019-10-24 21:13:01 +01:00
|
|
|
err = drgn_program_set_kdump(prog);
|
|
|
|
if (err)
|
|
|
|
goto out_elf;
|
|
|
|
return NULL;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
|
|
|
}
|
2019-05-10 07:53:16 +01:00
|
|
|
|
2019-10-03 01:10:15 +01:00
|
|
|
prog->file_segments = malloc_array(num_file_segments,
|
2019-05-10 07:53:16 +01:00
|
|
|
sizeof(*prog->file_segments));
|
|
|
|
if (!prog->file_segments) {
|
|
|
|
err = &drgn_enomem;
|
2019-10-03 01:10:15 +01:00
|
|
|
goto out_elf;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
2019-10-03 01:10:15 +01:00
|
|
|
prog->num_file_segments = num_file_segments;
|
2019-05-10 07:53:16 +01:00
|
|
|
current_file_segment = prog->file_segments;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-10-03 01:10:15 +01:00
|
|
|
/* Second pass: add the segments. */
|
2019-05-10 07:53:16 +01:00
|
|
|
for (i = 0; i < phnum; i++) {
|
|
|
|
GElf_Phdr phdr_mem, *phdr;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-10-24 21:13:01 +01:00
|
|
|
phdr = gelf_getphdr(prog->core, i, &phdr_mem);
|
2019-05-10 07:53:16 +01:00
|
|
|
if (!phdr) {
|
|
|
|
err = drgn_error_libelf();
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
goto out_segments;
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (phdr->p_type == PT_LOAD) {
|
|
|
|
/*
|
|
|
|
* If this happens, then the number of segments changed
|
|
|
|
* since the first pass. That's probably impossible, but
|
|
|
|
* skip it just in case.
|
|
|
|
*/
|
|
|
|
if (current_file_segment ==
|
|
|
|
prog->file_segments + prog->num_file_segments)
|
|
|
|
continue;
|
|
|
|
current_file_segment->file_offset = phdr->p_offset;
|
|
|
|
current_file_segment->file_size = phdr->p_filesz;
|
|
|
|
current_file_segment->fd = prog->core_fd;
|
|
|
|
err = drgn_program_add_memory_segment(prog,
|
|
|
|
phdr->p_vaddr,
|
|
|
|
phdr->p_memsz,
|
|
|
|
drgn_read_memory_file,
|
2019-05-24 09:16:25 +01:00
|
|
|
current_file_segment,
|
|
|
|
false);
|
2019-05-10 07:53:16 +01:00
|
|
|
if (err)
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
goto out_segments;
|
2019-05-26 22:49:48 +01:00
|
|
|
if (have_non_zero_phys_addr &&
|
|
|
|
phdr->p_paddr !=
|
|
|
|
(is_64_bit ? UINT64_MAX : UINT32_MAX)) {
|
2019-05-24 09:16:25 +01:00
|
|
|
err = drgn_program_add_memory_segment(prog,
|
|
|
|
phdr->p_paddr,
|
|
|
|
phdr->p_memsz,
|
|
|
|
drgn_read_memory_file,
|
|
|
|
current_file_segment,
|
|
|
|
true);
|
|
|
|
if (err)
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
goto out_segments;
|
2019-05-24 09:16:25 +01:00
|
|
|
}
|
2019-05-10 07:53:16 +01:00
|
|
|
current_file_segment++;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
|
|
|
}
|
2019-10-03 01:10:15 +01:00
|
|
|
if (vmcoreinfo_note) {
|
|
|
|
err = parse_vmcoreinfo(vmcoreinfo_note, vmcoreinfo_size,
|
|
|
|
&prog->vmcoreinfo);
|
|
|
|
if (err)
|
|
|
|
goto out_segments;
|
|
|
|
}
|
2019-05-10 07:53:16 +01:00
|
|
|
|
2019-10-03 01:10:15 +01:00
|
|
|
if (is_proc_kcore) {
|
|
|
|
if (!vmcoreinfo_note) {
|
|
|
|
err = read_vmcoreinfo_fallback(&prog->reader,
|
|
|
|
have_non_zero_phys_addr,
|
|
|
|
&prog->vmcoreinfo);
|
2019-05-10 07:53:16 +01:00
|
|
|
if (err)
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
goto out_segments;
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
2019-10-03 01:10:15 +01:00
|
|
|
prog->flags |= (DRGN_PROGRAM_IS_LINUX_KERNEL |
|
|
|
|
DRGN_PROGRAM_IS_LIVE);
|
2019-10-24 21:13:01 +01:00
|
|
|
elf_end(prog->core);
|
|
|
|
prog->core = NULL;
|
2019-10-03 01:10:15 +01:00
|
|
|
} else if (vmcoreinfo_note) {
|
|
|
|
prog->flags |= DRGN_PROGRAM_IS_LINUX_KERNEL;
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
|
|
|
|
2019-07-29 08:57:28 +01:00
|
|
|
drgn_program_set_platform(prog, &platform);
|
2019-05-10 07:53:16 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
|
|
out_segments:
|
2019-05-24 09:16:25 +01:00
|
|
|
drgn_memory_reader_deinit(&prog->reader);
|
|
|
|
drgn_memory_reader_init(&prog->reader);
|
2019-05-10 07:53:16 +01:00
|
|
|
free(prog->file_segments);
|
|
|
|
prog->file_segments = NULL;
|
|
|
|
prog->num_file_segments = 0;
|
|
|
|
out_elf:
|
2019-10-24 21:13:01 +01:00
|
|
|
elf_end(prog->core);
|
|
|
|
prog->core = NULL;
|
2019-05-10 07:53:16 +01:00
|
|
|
out_fd:
|
|
|
|
close(prog->core_fd);
|
|
|
|
prog->core_fd = -1;
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
|
|
|
drgn_program_set_kernel(struct drgn_program *prog)
|
|
|
|
{
|
|
|
|
return drgn_program_set_core_dump(prog, "/proc/kcore");
|
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
|
|
|
drgn_program_set_pid(struct drgn_program *prog, pid_t pid)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
{
|
2019-05-10 07:53:16 +01:00
|
|
|
struct drgn_error *err;
|
|
|
|
char buf[64];
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_program_check_initialized(prog);
|
|
|
|
if (err)
|
|
|
|
return err;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
sprintf(buf, "/proc/%ld/mem", (long)pid);
|
|
|
|
prog->core_fd = open(buf, O_RDONLY);
|
|
|
|
if (prog->core_fd == -1)
|
2019-07-11 23:58:23 +01:00
|
|
|
return drgn_error_create_os("open", errno, buf);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
prog->file_segments = malloc(sizeof(*prog->file_segments));
|
|
|
|
if (!prog->file_segments) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out_fd;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
2019-05-10 07:53:16 +01:00
|
|
|
prog->file_segments[0].file_offset = 0;
|
|
|
|
prog->file_segments[0].file_size = UINT64_MAX;
|
|
|
|
prog->file_segments[0].fd = prog->core_fd;
|
|
|
|
prog->num_file_segments = 1;
|
2019-05-24 09:16:25 +01:00
|
|
|
err = drgn_program_add_memory_segment(prog, 0, UINT64_MAX,
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_read_memory_file,
|
2019-05-24 09:16:25 +01:00
|
|
|
prog->file_segments, false);
|
2019-05-10 07:53:16 +01:00
|
|
|
if (err)
|
|
|
|
goto out_segments;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
prog->pid = pid;
|
2019-06-05 23:55:07 +01:00
|
|
|
prog->flags |= DRGN_PROGRAM_IS_LIVE;
|
2019-07-29 08:57:28 +01:00
|
|
|
drgn_program_set_platform(prog, &drgn_host_platform);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
return NULL;
|
2019-05-10 07:53:16 +01:00
|
|
|
|
|
|
|
out_segments:
|
2019-05-24 09:16:25 +01:00
|
|
|
drgn_memory_reader_deinit(&prog->reader);
|
|
|
|
drgn_memory_reader_init(&prog->reader);
|
2019-05-10 07:53:16 +01:00
|
|
|
free(prog->file_segments);
|
|
|
|
prog->file_segments = NULL;
|
|
|
|
prog->num_file_segments = 0;
|
|
|
|
out_fd:
|
|
|
|
close(prog->core_fd);
|
|
|
|
prog->core_fd = -1;
|
|
|
|
return err;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
|
|
|
|
2019-09-25 01:13:53 +01:00
|
|
|
static struct drgn_error *drgn_program_get_dindex(struct drgn_program *prog,
|
|
|
|
struct drgn_dwarf_index **ret)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
{
|
2019-09-25 01:13:53 +01:00
|
|
|
struct drgn_error *err;
|
|
|
|
|
|
|
|
if (!prog->_dicache) {
|
|
|
|
const Dwfl_Callbacks *dwfl_callbacks;
|
|
|
|
struct drgn_dwarf_info_cache *dicache;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
if (prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL)
|
|
|
|
dwfl_callbacks = &drgn_dwfl_callbacks;
|
|
|
|
else if (prog->flags & DRGN_PROGRAM_IS_LIVE)
|
2019-09-25 01:13:53 +01:00
|
|
|
dwfl_callbacks = &drgn_linux_proc_dwfl_callbacks;
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
else
|
2019-09-25 01:13:53 +01:00
|
|
|
dwfl_callbacks = &drgn_userspace_core_dump_dwfl_callbacks;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-09-25 01:13:53 +01:00
|
|
|
err = drgn_dwarf_info_cache_create(&prog->tindex,
|
|
|
|
dwfl_callbacks, &dicache);
|
2019-05-10 07:53:16 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
err = drgn_program_add_type_finder(prog, drgn_dwarf_type_find,
|
|
|
|
dicache);
|
|
|
|
if (err) {
|
|
|
|
drgn_dwarf_info_cache_destroy(dicache);
|
|
|
|
return err;
|
|
|
|
}
|
2019-07-24 00:26:29 +01:00
|
|
|
err = drgn_program_add_object_finder(prog,
|
|
|
|
drgn_dwarf_object_find,
|
2019-05-10 07:53:16 +01:00
|
|
|
dicache);
|
|
|
|
if (err) {
|
|
|
|
drgn_type_index_remove_finder(&prog->tindex);
|
|
|
|
drgn_dwarf_info_cache_destroy(dicache);
|
|
|
|
return err;
|
|
|
|
}
|
2019-07-17 22:16:38 +01:00
|
|
|
prog->_dicache = dicache;
|
|
|
|
}
|
2019-09-25 01:13:53 +01:00
|
|
|
*ret = &prog->_dicache->dindex;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct drgn_error *drgn_program_get_dwfl(struct drgn_program *prog, Dwfl **ret)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_dwarf_index *dindex;
|
|
|
|
|
|
|
|
err = drgn_program_get_dindex(prog, &dindex);
|
2019-07-17 22:16:38 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
2019-09-25 01:13:53 +01:00
|
|
|
*ret = dindex->dwfl;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-09-25 01:13:53 +01:00
|
|
|
static struct drgn_error *
|
|
|
|
userspace_report_debug_info(struct drgn_program *prog,
|
|
|
|
struct drgn_dwarf_index *dindex,
|
|
|
|
const char **paths, size_t n,
|
|
|
|
bool report_default)
|
2019-05-10 07:53:16 +01:00
|
|
|
{
|
2019-05-13 22:32:01 +01:00
|
|
|
struct drgn_error *err;
|
2019-07-17 22:16:38 +01:00
|
|
|
size_t i;
|
|
|
|
|
|
|
|
for (i = 0; i < n; i++) {
|
2019-09-25 01:13:53 +01:00
|
|
|
int fd;
|
|
|
|
Elf *elf;
|
|
|
|
|
|
|
|
err = open_elf_file(paths[i], &fd, &elf);
|
|
|
|
if (err) {
|
|
|
|
err = drgn_dwarf_index_report_error(dindex, paths[i],
|
|
|
|
NULL, err);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
continue;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
2019-09-25 01:13:53 +01:00
|
|
|
/*
|
|
|
|
* We haven't implemented a way to get the load address for
|
|
|
|
* anything reported here, so for now we report it as unloaded.
|
|
|
|
*/
|
|
|
|
err = drgn_dwarf_index_report_elf(dindex, paths[i], fd, elf, 0,
|
|
|
|
0, NULL, NULL);
|
|
|
|
if (err)
|
|
|
|
return err;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
2019-09-25 01:13:53 +01:00
|
|
|
|
|
|
|
if (report_default) {
|
|
|
|
if (prog->flags & DRGN_PROGRAM_IS_LIVE) {
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
ret = dwfl_linux_proc_report(dindex->dwfl, prog->pid);
|
|
|
|
if (ret == -1) {
|
|
|
|
return drgn_error_libdwfl();
|
|
|
|
} else if (ret) {
|
|
|
|
return drgn_error_create_os("dwfl_linux_proc_report",
|
|
|
|
ret, NULL);
|
|
|
|
}
|
2019-10-24 21:13:01 +01:00
|
|
|
} else if (dwfl_core_file_report(dindex->dwfl, prog->core,
|
|
|
|
NULL) == -1) {
|
|
|
|
return drgn_error_libdwfl();
|
2019-09-25 01:13:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int drgn_set_platform_from_dwarf(Dwfl_Module *module, void **userdatap,
|
|
|
|
const char *name, Dwarf_Addr base,
|
|
|
|
Dwarf *dwarf, Dwarf_Addr bias,
|
|
|
|
void *arg)
|
|
|
|
{
|
|
|
|
Elf *elf;
|
|
|
|
GElf_Ehdr ehdr_mem, *ehdr;
|
|
|
|
struct drgn_platform platform;
|
|
|
|
|
|
|
|
elf = dwarf_getelf(dwarf);
|
|
|
|
if (!elf)
|
|
|
|
return DWARF_CB_OK;
|
|
|
|
ehdr = gelf_getehdr(elf, &ehdr_mem);
|
|
|
|
if (!ehdr)
|
|
|
|
return DWARF_CB_OK;
|
|
|
|
drgn_platform_from_elf(ehdr, &platform);
|
|
|
|
drgn_program_set_platform(arg, &platform);
|
|
|
|
return DWARF_CB_ABORT;
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
2019-09-25 01:13:53 +01:00
|
|
|
drgn_program_load_debug_info(struct drgn_program *prog, const char **paths,
|
|
|
|
size_t n, bool load_default)
|
2019-05-10 07:53:16 +01:00
|
|
|
{
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
struct drgn_error *err;
|
2019-09-25 01:13:53 +01:00
|
|
|
struct drgn_dwarf_index *dindex;
|
|
|
|
bool report_from_dwfl;
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
|
2019-09-25 01:13:53 +01:00
|
|
|
if (!n && !load_default)
|
|
|
|
return NULL;
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
|
2019-09-25 01:13:53 +01:00
|
|
|
err = drgn_program_get_dindex(prog, &dindex);
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2019-09-25 01:13:53 +01:00
|
|
|
drgn_dwarf_index_report_begin(dindex);
|
|
|
|
if (prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) {
|
|
|
|
err = linux_kernel_report_debug_info(prog, dindex, paths, n,
|
|
|
|
load_default);
|
|
|
|
} else {
|
|
|
|
err = userspace_report_debug_info(prog, dindex, paths, n,
|
|
|
|
load_default);
|
|
|
|
}
|
|
|
|
if (err) {
|
|
|
|
drgn_dwarf_index_report_abort(dindex);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
report_from_dwfl = (!(prog->flags & DRGN_PROGRAM_IS_LINUX_KERNEL) &&
|
|
|
|
load_default);
|
|
|
|
err = drgn_dwarf_index_report_end(dindex, report_from_dwfl);
|
|
|
|
if ((!err || err->code == DRGN_ERROR_MISSING_DEBUG_INFO) &&
|
|
|
|
!prog->has_platform) {
|
|
|
|
dwfl_getdwarf(prog->_dicache->dindex.dwfl,
|
|
|
|
drgn_set_platform_from_dwarf, prog, 0);
|
libdrgn: use libdwfl
libdwfl is the elfutils "DWARF frontend library". It has high-level
functionality for looking up symbols, walking stack traces, etc. In
order to use this functionality, we need to report our debugging
information through libdwfl. For userspace programs, libdwfl has a much
better implementation than drgn for automatically finding debug
information from a core dump or PID. However, for the kernel, libdwfl
has a few issues:
- It only supports finding debug information for the running kernel, not
vmcores.
- It determines the vmlinux address range by reading /proc/kallsyms,
which is slow (~70ms on my machine).
- If separate debug information isn't available for a kernel module, it
finds it by walking /lib/modules/$(uname -r)/kernel; this is repeated
for every module.
- It doesn't find kernel modules with names containing both dashes and
underscores (e.g., aes-x86_64).
Luckily, drgn already solved all of these problems, and with some
effort, we can keep doing it ourselves and report it to libdwfl.
The conversion replaces a bunch of code for dealing with userspace core
dump notes, /proc/$pid/maps, and relocations.
2019-07-15 08:51:30 +01:00
|
|
|
}
|
|
|
|
return err;
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
|
|
|
|
2019-10-24 22:26:45 +01:00
|
|
|
static struct drgn_error *drgn_program_cache_prstatus(struct drgn_program *prog)
|
|
|
|
{
|
|
|
|
size_t phnum, i;
|
|
|
|
size_t pr_pid_offset;
|
|
|
|
bool bswap;
|
|
|
|
|
|
|
|
pr_pid_offset = drgn_program_is_64_bit(prog) ? 32 : 24;
|
|
|
|
bswap = (drgn_program_is_little_endian(prog) !=
|
|
|
|
(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__));
|
|
|
|
|
|
|
|
if (elf_getphdrnum(prog->core, &phnum) != 0)
|
|
|
|
return drgn_error_libelf();
|
|
|
|
for (i = 0; i < phnum; i++) {
|
|
|
|
GElf_Phdr phdr_mem, *phdr;
|
|
|
|
Elf_Data *data;
|
|
|
|
size_t offset;
|
|
|
|
GElf_Nhdr nhdr;
|
|
|
|
size_t name_offset, desc_offset;
|
|
|
|
|
|
|
|
phdr = gelf_getphdr(prog->core, i, &phdr_mem);
|
|
|
|
if (!phdr)
|
|
|
|
return drgn_error_libelf();
|
|
|
|
if (phdr->p_type != PT_NOTE)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
data = elf_getdata_rawchunk(prog->core, phdr->p_offset,
|
|
|
|
phdr->p_filesz,
|
|
|
|
note_header_type(phdr));
|
|
|
|
if (!data)
|
|
|
|
return drgn_error_libelf();
|
|
|
|
|
|
|
|
offset = 0;
|
|
|
|
while (offset < data->d_size &&
|
|
|
|
(offset = gelf_getnote(data, offset, &nhdr, &name_offset,
|
|
|
|
&desc_offset))) {
|
|
|
|
const char *name;
|
|
|
|
uint32_t pr_pid;
|
|
|
|
struct drgn_prstatus_map_entry entry;
|
|
|
|
|
|
|
|
name = (char *)data->d_buf + name_offset;
|
|
|
|
if (strncmp(name, "CORE", nhdr.n_namesz) != 0 ||
|
|
|
|
nhdr.n_type != NT_PRSTATUS ||
|
|
|
|
nhdr.n_descsz < pr_pid_offset + sizeof(pr_pid))
|
|
|
|
continue;
|
|
|
|
memcpy(&pr_pid,
|
|
|
|
(char *)data->d_buf + desc_offset + pr_pid_offset,
|
|
|
|
sizeof(pr_pid));
|
|
|
|
if (bswap)
|
|
|
|
pr_pid = bswap_32(pr_pid);
|
|
|
|
if (!pr_pid)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
entry.key = pr_pid;
|
|
|
|
entry.value.str = (char *)data->d_buf + desc_offset;
|
|
|
|
entry.value.len = nhdr.n_descsz;
|
|
|
|
if (drgn_prstatus_map_insert(&prog->prstatus_cache,
|
|
|
|
&entry, NULL) == -1)
|
|
|
|
return &drgn_enomem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct drgn_error *drgn_program_find_prstatus(struct drgn_program *prog,
|
|
|
|
uint32_t tid, struct string *ret)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_prstatus_map_iterator it;
|
|
|
|
|
|
|
|
if (!prog->prstatus_cached) {
|
|
|
|
err = drgn_program_cache_prstatus(prog);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
prog->prstatus_cached = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
it = drgn_prstatus_map_search(&prog->prstatus_cache, &tid);
|
|
|
|
if (!it.entry) {
|
|
|
|
ret->str = NULL;
|
|
|
|
ret->len = 0;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
*ret = it.entry->value;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
struct drgn_error *drgn_program_init_core_dump(struct drgn_program *prog,
|
|
|
|
const char *path)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_program_set_core_dump(prog, path);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2019-09-25 01:13:53 +01:00
|
|
|
err = drgn_program_load_debug_info(prog, NULL, 0, true);
|
2019-05-13 22:32:01 +01:00
|
|
|
if (err && err->code == DRGN_ERROR_MISSING_DEBUG_INFO) {
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_error_destroy(err);
|
2019-05-13 22:32:01 +01:00
|
|
|
err = NULL;
|
|
|
|
}
|
|
|
|
return err;
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
2019-05-01 19:22:59 +01:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
struct drgn_error *drgn_program_init_kernel(struct drgn_program *prog)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
2019-05-01 19:22:59 +01:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_program_set_kernel(prog);
|
2019-05-01 19:22:59 +01:00
|
|
|
if (err)
|
2019-05-10 07:53:16 +01:00
|
|
|
return err;
|
2019-09-25 01:13:53 +01:00
|
|
|
err = drgn_program_load_debug_info(prog, NULL, 0, true);
|
2019-05-13 22:32:01 +01:00
|
|
|
if (err && err->code == DRGN_ERROR_MISSING_DEBUG_INFO) {
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_error_destroy(err);
|
2019-05-13 22:32:01 +01:00
|
|
|
err = NULL;
|
|
|
|
}
|
|
|
|
return err;
|
2019-05-10 07:53:16 +01:00
|
|
|
}
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
struct drgn_error *drgn_program_init_pid(struct drgn_program *prog, pid_t pid)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
2019-04-28 16:42:28 +01:00
|
|
|
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_program_set_pid(prog, pid);
|
2019-04-23 09:46:24 +01:00
|
|
|
if (err)
|
2019-05-10 07:53:16 +01:00
|
|
|
return err;
|
2019-09-25 01:13:53 +01:00
|
|
|
err = drgn_program_load_debug_info(prog, NULL, 0, true);
|
2019-05-13 22:32:01 +01:00
|
|
|
if (err && err->code == DRGN_ERROR_MISSING_DEBUG_INFO) {
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_error_destroy(err);
|
2019-05-13 22:32:01 +01:00
|
|
|
err = NULL;
|
|
|
|
}
|
|
|
|
return err;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_program_from_core_dump(const char *path, struct drgn_program **ret)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_program *prog;
|
|
|
|
|
|
|
|
prog = malloc(sizeof(*prog));
|
|
|
|
if (!prog)
|
|
|
|
return &drgn_enomem;
|
|
|
|
|
2019-07-29 08:57:28 +01:00
|
|
|
drgn_program_init(prog, NULL);
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_program_init_core_dump(prog, path);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
if (err) {
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_program_deinit(prog);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
free(prog);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ret = prog;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_program_from_kernel(struct drgn_program **ret)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_program *prog;
|
|
|
|
|
|
|
|
prog = malloc(sizeof(*prog));
|
|
|
|
if (!prog)
|
|
|
|
return &drgn_enomem;
|
|
|
|
|
2019-07-29 08:57:28 +01:00
|
|
|
drgn_program_init(prog, NULL);
|
2019-05-10 07:53:16 +01:00
|
|
|
err = drgn_program_init_kernel(prog);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
if (err) {
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_program_deinit(prog);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
free(prog);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ret = prog;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
|
|
|
drgn_program_from_pid(pid_t pid, struct drgn_program **ret)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_program *prog;
|
|
|
|
|
|
|
|
prog = malloc(sizeof(*prog));
|
|
|
|
if (!prog)
|
|
|
|
return &drgn_enomem;
|
|
|
|
|
2019-07-29 08:57:28 +01:00
|
|
|
drgn_program_init(prog, NULL);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
err = drgn_program_init_pid(prog, pid);
|
|
|
|
if (err) {
|
2019-05-10 07:53:16 +01:00
|
|
|
drgn_program_deinit(prog);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
free(prog);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
*ret = prog;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
|
|
|
drgn_program_read_memory(struct drgn_program *prog, void *buf, uint64_t address,
|
|
|
|
size_t count, bool physical)
|
|
|
|
{
|
2019-05-01 19:22:59 +01:00
|
|
|
return drgn_memory_reader_read(&prog->reader, buf, address, count,
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
physical);
|
|
|
|
}
|
|
|
|
|
2019-07-09 23:50:45 +01:00
|
|
|
DEFINE_VECTOR(char_vector, char)
|
|
|
|
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
LIBDRGN_PUBLIC 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 *err;
|
2019-07-09 23:50:45 +01:00
|
|
|
struct char_vector str;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-07-09 23:50:45 +01:00
|
|
|
char_vector_init(&str);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
for (;;) {
|
2019-07-09 23:50:45 +01:00
|
|
|
char *c;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
|
2019-07-09 23:50:45 +01:00
|
|
|
c = char_vector_append_entry(&str);
|
|
|
|
if (!c) {
|
|
|
|
char_vector_deinit(&str);
|
|
|
|
return &drgn_enomem;
|
|
|
|
}
|
|
|
|
if (str.size <= max_size) {
|
|
|
|
err = drgn_memory_reader_read(&prog->reader, c, address,
|
|
|
|
1, physical);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
if (err) {
|
2019-07-09 23:50:45 +01:00
|
|
|
char_vector_deinit(&str);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
return err;
|
|
|
|
}
|
2019-07-09 23:50:45 +01:00
|
|
|
if (!*c)
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
break;
|
|
|
|
} else {
|
2019-07-09 23:50:45 +01:00
|
|
|
*c = '\0';
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
address++;
|
|
|
|
}
|
2019-07-09 23:50:45 +01:00
|
|
|
char_vector_shrink_to_fit(&str);
|
|
|
|
*ret = str.data;
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
|
|
|
drgn_program_find_type(struct drgn_program *prog, const char *name,
|
|
|
|
const char *filename, struct drgn_qualified_type *ret)
|
|
|
|
{
|
2019-05-01 19:22:59 +01:00
|
|
|
return drgn_type_index_find(&prog->tindex, name, filename,
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
&drgn_language_c, ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC 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)
|
|
|
|
{
|
2019-06-29 00:02:52 +01:00
|
|
|
if (ret && ret->prog != prog) {
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
|
|
|
"object is from wrong program");
|
|
|
|
}
|
2019-07-24 00:26:29 +01:00
|
|
|
return drgn_object_index_find(&prog->oindex, name, filename, flags,
|
|
|
|
ret);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
}
|
|
|
|
|
2019-07-25 08:47:13 +01:00
|
|
|
struct drgn_error *drgn_program_find_symbol_internal(struct drgn_program *prog,
|
2019-10-18 10:42:02 +01:00
|
|
|
Dwfl_Module *module,
|
2019-07-25 08:47:13 +01:00
|
|
|
uint64_t address,
|
|
|
|
struct drgn_symbol *sym)
|
|
|
|
{
|
|
|
|
const char *name;
|
|
|
|
GElf_Off offset;
|
|
|
|
GElf_Sym elf_sym;
|
|
|
|
|
|
|
|
name = dwfl_module_addrinfo(module, address, &offset, &elf_sym, NULL,
|
|
|
|
NULL, NULL);
|
|
|
|
if (!name)
|
|
|
|
return &drgn_not_found;
|
|
|
|
sym->name = name;
|
|
|
|
sym->address = address - offset;
|
|
|
|
sym->size = elf_sym.st_size;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-10-18 10:42:02 +01:00
|
|
|
struct drgn_error *
|
|
|
|
drgn_program_find_symbol_in_module(struct drgn_program *prog,
|
|
|
|
Dwfl_Module *module, uint64_t address,
|
|
|
|
struct drgn_symbol **ret)
|
2019-07-25 08:47:13 +01:00
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_symbol *sym;
|
|
|
|
|
2019-10-18 10:42:02 +01:00
|
|
|
if (!module)
|
|
|
|
goto not_found;
|
2019-07-25 08:47:13 +01:00
|
|
|
sym = malloc(sizeof(*sym));
|
|
|
|
if (!sym)
|
|
|
|
return &drgn_enomem;
|
2019-10-18 10:42:02 +01:00
|
|
|
err = drgn_program_find_symbol_internal(prog, module, address, sym);
|
2019-07-25 08:47:13 +01:00
|
|
|
if (err) {
|
|
|
|
free(sym);
|
2019-10-18 10:42:02 +01:00
|
|
|
if (err == &drgn_not_found)
|
|
|
|
goto not_found;
|
2019-07-25 08:47:13 +01:00
|
|
|
return err;
|
|
|
|
}
|
|
|
|
*ret = sym;
|
|
|
|
return NULL;
|
2019-10-18 10:42:02 +01:00
|
|
|
|
|
|
|
not_found:
|
|
|
|
return drgn_error_format(DRGN_ERROR_LOOKUP,
|
|
|
|
"could not find symbol containing 0x%" PRIx64,
|
|
|
|
address);
|
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
|
|
|
drgn_program_find_symbol(struct drgn_program *prog, uint64_t address,
|
|
|
|
struct drgn_symbol **ret)
|
|
|
|
{
|
|
|
|
Dwfl_Module *module;
|
|
|
|
|
|
|
|
if (prog->_dicache)
|
|
|
|
module = dwfl_addrmodule(prog->_dicache->dindex.dwfl, address);
|
|
|
|
else
|
|
|
|
module = NULL;
|
|
|
|
return drgn_program_find_symbol_in_module(prog, module, address, ret);
|
2019-07-25 08:47:13 +01:00
|
|
|
}
|
|
|
|
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
|
|
|
drgn_program_element_info(struct drgn_program *prog, struct drgn_type *type,
|
|
|
|
struct drgn_element_info *ret)
|
|
|
|
{
|
|
|
|
struct drgn_type *underlying_type;
|
|
|
|
bool is_pointer, is_array;
|
|
|
|
|
|
|
|
underlying_type = drgn_underlying_type(type);
|
|
|
|
is_pointer = drgn_type_kind(underlying_type) == DRGN_TYPE_POINTER;
|
|
|
|
is_array = drgn_type_kind(underlying_type) == DRGN_TYPE_ARRAY;
|
|
|
|
if (!is_pointer && !is_array)
|
|
|
|
return drgn_type_error("'%s' is not an array or pointer", type);
|
|
|
|
|
|
|
|
ret->qualified_type = drgn_type_type(underlying_type);
|
|
|
|
return drgn_type_bit_size(ret->qualified_type.type, &ret->bit_size);
|
|
|
|
}
|
|
|
|
|
|
|
|
LIBDRGN_PUBLIC struct drgn_error *
|
|
|
|
drgn_program_member_info(struct drgn_program *prog, struct drgn_type *type,
|
|
|
|
const char *member_name, struct drgn_member_info *ret)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_member_value *member;
|
|
|
|
|
2019-05-01 19:22:59 +01:00
|
|
|
err = drgn_type_index_find_member(&prog->tindex, type, member_name,
|
2019-04-22 22:21:25 +01:00
|
|
|
strlen(member_name), &member);
|
Rewrite drgn core in C
The current mixed Python/C implementation works well, but it has a
couple of important limitations:
- It's too slow for some common use cases, like iterating over large
data structures.
- It can't be reused in utilities written in other languages.
This replaces the internals with a new library written in C, libdrgn. It
includes Python bindings with mostly the same public interface as
before, with some important improvements:
- Types are now represented by a single Type class rather than the messy
polymorphism in the Python implementation.
- Qualifiers are a bitmask instead of a set of strings.
- Bit fields are not considered a separate type.
- The lvalue/rvalue terminology is replaced with reference/value.
- Structure, union, and array values are better supported.
- Function objects are supported.
- Program distinguishes between lookups of variables, constants, and
functions.
The C rewrite is about 6x as fast as the original Python when using the
Python bindings, and about 8x when using the C API directly.
Currently, the exposed API in C is fairly conservative. In the future,
the memory reader, type index, and object index APIs will probably be
exposed for more flexibility.
2019-03-22 23:27:46 +00:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
err = drgn_lazy_type_evaluate(member->type, &ret->qualified_type);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
ret->bit_offset = member->bit_offset;
|
|
|
|
ret->bit_field_size = member->bit_field_size;
|
|
|
|
return NULL;
|
|
|
|
}
|