2021-11-21 23:59:44 +00:00
|
|
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
|
2022-11-02 00:05:16 +00:00
|
|
|
// SPDX-License-Identifier: LGPL-2.1-or-later
|
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
|
|
|
|
2020-09-24 00:02:02 +01:00
|
|
|
#include <assert.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 <ctype.h>
|
|
|
|
#include <float.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <limits.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdlib.h>
|
2020-09-24 00:02:02 +01:00
|
|
|
#include <string.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
|
|
|
|
2021-08-24 01:07:26 +01:00
|
|
|
#include "array.h"
|
2020-10-10 01:17:10 +01:00
|
|
|
#include "bitops.h"
|
2020-09-24 00:02:02 +01:00
|
|
|
#include "error.h"
|
|
|
|
#include "language.h" // IWYU pragma: associated
|
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 "lexer.h"
|
2020-10-10 01:59:23 +01:00
|
|
|
#include "minmax.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 "object.h"
|
|
|
|
#include "program.h"
|
|
|
|
#include "string_builder.h"
|
2019-12-12 22:30:04 +00: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.h"
|
2020-09-24 00:02:02 +01:00
|
|
|
#include "util.h"
|
|
|
|
#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
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_declare_variable(struct drgn_qualified_type qualified_type,
|
|
|
|
struct string_callback *name, size_t indent,
|
2021-11-23 08:52:39 +00:00
|
|
|
bool define_anonymous_type, struct string_builder *sb);
|
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 *
|
|
|
|
c_define_type(struct drgn_qualified_type qualified_type, size_t indent,
|
|
|
|
struct string_builder *sb);
|
|
|
|
|
2019-05-14 18:07:50 +01:00
|
|
|
static bool append_tabs(int n, struct string_builder *sb)
|
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
|
|
|
{
|
|
|
|
while (n-- > 0) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, '\t'))
|
|
|
|
return false;
|
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-14 18:07:50 +01:00
|
|
|
return true;
|
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 *c_variable_name(struct string_callback *name,
|
|
|
|
void *arg, struct string_builder *sb)
|
|
|
|
{
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, arg))
|
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *c_append_qualifiers(enum drgn_qualifiers qualifiers,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
static const char *qualifier_names[] = {
|
|
|
|
"const", "volatile", "restrict", "_Atomic",
|
|
|
|
};
|
|
|
|
bool first = true;
|
|
|
|
unsigned int i;
|
|
|
|
|
2021-08-24 01:07:26 +01:00
|
|
|
static_assert((1 << array_size(qualifier_names)) - 1 ==
|
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_ALL_QUALIFIERS, "missing C qualifier name");
|
|
|
|
|
|
|
|
for (i = 0; (1U << i) & DRGN_ALL_QUALIFIERS; i++) {
|
|
|
|
if (!(qualifiers & (1U << i)))
|
|
|
|
continue;
|
|
|
|
if (!first) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ' '))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, qualifier_names[i]))
|
|
|
|
return &drgn_enomem;
|
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
|
|
|
first = false;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_declare_basic(struct drgn_qualified_type qualified_type,
|
|
|
|
struct string_callback *name, size_t indent,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!append_tabs(indent, sb))
|
|
|
|
return &drgn_enomem;
|
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 (qualified_type.qualifiers) {
|
|
|
|
err = c_append_qualifiers(qualified_type.qualifiers, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ' '))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb,
|
|
|
|
drgn_type_kind(qualified_type.type) == DRGN_TYPE_VOID ?
|
|
|
|
"void" : drgn_type_name(qualified_type.type)))
|
|
|
|
return &drgn_enomem;
|
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 (name) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ' '))
|
|
|
|
return &drgn_enomem;
|
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 = string_callback_call(name, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_append_tagged_name(struct drgn_qualified_type qualified_type, size_t indent,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
const char *keyword, *tag;
|
|
|
|
|
|
|
|
switch (drgn_type_kind(qualified_type.type)) {
|
|
|
|
case DRGN_TYPE_STRUCT:
|
|
|
|
keyword = "struct";
|
|
|
|
break;
|
|
|
|
case DRGN_TYPE_UNION:
|
|
|
|
keyword = "union";
|
|
|
|
break;
|
2019-11-15 01:12:47 +00:00
|
|
|
case DRGN_TYPE_CLASS:
|
|
|
|
keyword = "class";
|
|
|
|
break;
|
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
|
|
|
case DRGN_TYPE_ENUM:
|
|
|
|
keyword = "enum";
|
|
|
|
break;
|
|
|
|
default:
|
2020-05-07 23:02:33 +01:00
|
|
|
UNREACHABLE();
|
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-14 18:07:50 +01:00
|
|
|
if (!append_tabs(indent, sb))
|
|
|
|
return &drgn_enomem;
|
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 (qualified_type.qualifiers) {
|
|
|
|
err = c_append_qualifiers(qualified_type.qualifiers, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ' '))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, keyword))
|
|
|
|
return &drgn_enomem;
|
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
|
|
|
|
|
|
|
tag = drgn_type_tag(qualified_type.type);
|
|
|
|
if (tag) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ' ') ||
|
|
|
|
!string_builder_append(sb, tag))
|
|
|
|
return &drgn_enomem;
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_declare_tagged(struct drgn_qualified_type qualified_type,
|
|
|
|
struct string_callback *name, size_t indent,
|
2021-11-23 08:52:39 +00:00
|
|
|
bool define_anonymous_type, struct string_builder *sb)
|
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;
|
|
|
|
|
2021-11-23 08:52:39 +00:00
|
|
|
bool anonymous = drgn_type_is_anonymous(qualified_type.type);
|
|
|
|
if (anonymous && define_anonymous_type)
|
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 = c_define_type(qualified_type, indent, sb);
|
|
|
|
else
|
|
|
|
err = c_append_tagged_name(qualified_type, indent, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2021-11-23 08:52:39 +00:00
|
|
|
if (anonymous && !define_anonymous_type &&
|
|
|
|
!string_builder_append(sb, " <anonymous>"))
|
|
|
|
return &drgn_enomem;
|
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 (name) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ' '))
|
|
|
|
return &drgn_enomem;
|
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 = string_callback_call(name, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *c_pointer_name(struct string_callback *name,
|
|
|
|
void *arg, struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_qualified_type *qualified_type = arg;
|
|
|
|
struct drgn_qualified_type referenced_type;
|
|
|
|
enum drgn_type_kind referenced_kind;
|
|
|
|
bool parenthesize;
|
|
|
|
|
|
|
|
referenced_type = drgn_type_type(qualified_type->type);
|
|
|
|
referenced_kind = drgn_type_kind(referenced_type.type);
|
|
|
|
parenthesize = (referenced_kind == DRGN_TYPE_ARRAY ||
|
|
|
|
referenced_kind == DRGN_TYPE_FUNCTION);
|
2019-05-14 18:07:50 +01:00
|
|
|
if (parenthesize && !string_builder_appendc(sb, '('))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, '*'))
|
|
|
|
return &drgn_enomem;
|
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 (qualified_type->qualifiers) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ' '))
|
|
|
|
return &drgn_enomem;
|
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 = c_append_qualifiers(qualified_type->qualifiers, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (name) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ' '))
|
|
|
|
return &drgn_enomem;
|
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 = string_callback_call(name, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2019-05-14 18:07:50 +01:00
|
|
|
if (parenthesize && !string_builder_appendc(sb, ')'))
|
|
|
|
return &drgn_enomem;
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_declare_pointer(struct drgn_qualified_type qualified_type,
|
|
|
|
struct string_callback *name, size_t indent,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct string_callback pointer_name = {
|
|
|
|
.fn = c_pointer_name,
|
|
|
|
.str = name,
|
|
|
|
.arg = &qualified_type,
|
|
|
|
};
|
|
|
|
struct drgn_qualified_type referenced_type;
|
|
|
|
|
|
|
|
referenced_type = drgn_type_type(qualified_type.type);
|
2021-11-23 08:52:39 +00:00
|
|
|
return c_declare_variable(referenced_type, &pointer_name, indent, false,
|
|
|
|
sb);
|
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 *c_array_name(struct string_callback *name, void *arg,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_qualified_type *qualified_type = arg;
|
|
|
|
|
|
|
|
err = string_callback_call(name, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (drgn_type_is_complete(qualified_type->type)) {
|
|
|
|
uint64_t length = drgn_type_length(qualified_type->type);
|
|
|
|
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendf(sb, "[%" PRIu64 "]", length))
|
|
|
|
return &drgn_enomem;
|
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
|
|
|
} else {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, "[]"))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_declare_array(struct drgn_qualified_type qualified_type,
|
|
|
|
struct string_callback *name, size_t indent,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct string_callback array_name = {
|
|
|
|
.fn = c_array_name,
|
|
|
|
.str = name,
|
|
|
|
.arg = &qualified_type,
|
|
|
|
};
|
|
|
|
struct drgn_qualified_type element_type;
|
|
|
|
|
|
|
|
element_type = drgn_type_type(qualified_type.type);
|
2021-11-23 08:52:39 +00:00
|
|
|
return c_declare_variable(element_type, &array_name, indent, false, sb);
|
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 *
|
|
|
|
c_declare_function(struct drgn_qualified_type qualified_type,
|
|
|
|
struct string_callback *name, size_t indent,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_type_parameter *parameters;
|
|
|
|
size_t num_parameters, i;
|
|
|
|
struct drgn_qualified_type return_type;
|
|
|
|
|
|
|
|
if (!name) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
|
|
|
"function must have name");
|
|
|
|
}
|
|
|
|
|
|
|
|
parameters = drgn_type_parameters(qualified_type.type);
|
|
|
|
num_parameters = drgn_type_num_parameters(qualified_type.type);
|
|
|
|
|
|
|
|
return_type = drgn_type_type(qualified_type.type);
|
2021-11-23 08:52:39 +00:00
|
|
|
err = c_declare_variable(return_type, name, indent, false, sb);
|
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;
|
|
|
|
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, '('))
|
|
|
|
return &drgn_enomem;
|
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 < num_parameters; i++) {
|
|
|
|
const char *parameter_name = parameters[i].name;
|
|
|
|
struct drgn_qualified_type parameter_type;
|
|
|
|
struct string_callback name_cb = {
|
|
|
|
.fn = c_variable_name,
|
|
|
|
.arg = (void *)parameter_name,
|
|
|
|
};
|
|
|
|
|
|
|
|
err = drgn_parameter_type(¶meters[i], ¶meter_type);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (i > 0) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, ", "))
|
|
|
|
return &drgn_enomem;
|
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 = c_declare_variable(parameter_type,
|
|
|
|
parameter_name && parameter_name[0] ?
|
2021-11-23 08:52:39 +00:00
|
|
|
&name_cb : NULL, 0, false, sb);
|
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;
|
|
|
|
}
|
|
|
|
if (num_parameters && drgn_type_is_variadic(qualified_type.type)) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, ", ..."))
|
|
|
|
return &drgn_enomem;
|
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
|
|
|
} else if (!num_parameters &&
|
|
|
|
!drgn_type_is_variadic(qualified_type.type)) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, "void"))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ')'))
|
|
|
|
return &drgn_enomem;
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_declare_variable(struct drgn_qualified_type qualified_type,
|
|
|
|
struct string_callback *name, size_t indent,
|
2021-11-23 08:52:39 +00:00
|
|
|
bool define_anonymous_type, struct string_builder *sb)
|
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
|
|
|
{
|
2020-12-04 19:20:00 +00:00
|
|
|
SWITCH_ENUM(drgn_type_kind(qualified_type.type),
|
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
|
|
|
case DRGN_TYPE_VOID:
|
|
|
|
case DRGN_TYPE_INT:
|
|
|
|
case DRGN_TYPE_BOOL:
|
|
|
|
case DRGN_TYPE_FLOAT:
|
|
|
|
case DRGN_TYPE_TYPEDEF:
|
|
|
|
return c_declare_basic(qualified_type, name, indent, sb);
|
|
|
|
case DRGN_TYPE_STRUCT:
|
|
|
|
case DRGN_TYPE_UNION:
|
2019-11-15 01:12:47 +00:00
|
|
|
case DRGN_TYPE_CLASS:
|
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
|
|
|
case DRGN_TYPE_ENUM:
|
2021-11-23 08:52:39 +00:00
|
|
|
return c_declare_tagged(qualified_type, name, indent,
|
|
|
|
define_anonymous_type, sb);
|
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
|
|
|
case DRGN_TYPE_POINTER:
|
|
|
|
return c_declare_pointer(qualified_type, name, indent, sb);
|
|
|
|
case DRGN_TYPE_ARRAY:
|
|
|
|
return c_declare_array(qualified_type, name, indent, sb);
|
|
|
|
case DRGN_TYPE_FUNCTION:
|
|
|
|
return c_declare_function(qualified_type, name, indent, sb);
|
2020-12-04 19:20:00 +00: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 *
|
|
|
|
c_define_compound(struct drgn_qualified_type qualified_type, size_t indent,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_type_member *members;
|
|
|
|
size_t num_members, i;
|
|
|
|
|
|
|
|
if (!drgn_type_is_complete(qualified_type.type)) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
|
|
|
"cannot get definition of incomplete compound type");
|
|
|
|
}
|
|
|
|
|
|
|
|
members = drgn_type_members(qualified_type.type);
|
|
|
|
num_members = drgn_type_num_members(qualified_type.type);
|
|
|
|
|
|
|
|
err = c_append_tagged_name(qualified_type, indent, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, " {\n"))
|
|
|
|
return &drgn_enomem;
|
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 < num_members; i++) {
|
|
|
|
struct drgn_qualified_type member_type;
|
2020-12-18 22:11:29 +00:00
|
|
|
uint64_t member_bit_field_size;
|
|
|
|
err = drgn_member_type(&members[i], &member_type,
|
|
|
|
&member_bit_field_size);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
const char *member_name = members[i].name;
|
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 string_callback name_cb = {
|
|
|
|
.fn = c_variable_name,
|
|
|
|
.arg = (void *)member_name,
|
|
|
|
};
|
|
|
|
err = c_declare_variable(member_type,
|
|
|
|
member_name && member_name[0] ?
|
2021-11-23 08:52:39 +00:00
|
|
|
&name_cb : NULL, indent + 1, true, sb);
|
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;
|
2020-12-18 22:11:29 +00:00
|
|
|
if (member_bit_field_size &&
|
|
|
|
!string_builder_appendf(sb, " : %" PRIu64,
|
|
|
|
member_bit_field_size))
|
2019-05-14 18:07:50 +01:00
|
|
|
return &drgn_enomem;
|
|
|
|
if (!string_builder_append(sb, ";\n"))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
if (!append_tabs(indent, sb) || !string_builder_appendc(sb, '}'))
|
|
|
|
return &drgn_enomem;
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_define_enum(struct drgn_qualified_type qualified_type, size_t indent,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
const struct drgn_type_enumerator *enumerators;
|
|
|
|
size_t num_enumerators, i;
|
|
|
|
bool is_signed;
|
|
|
|
|
|
|
|
if (!drgn_type_is_complete(qualified_type.type)) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
|
|
|
"cannot get definition of incomplete enum type");
|
|
|
|
}
|
|
|
|
|
|
|
|
enumerators = drgn_type_enumerators(qualified_type.type);
|
|
|
|
num_enumerators = drgn_type_num_enumerators(qualified_type.type);
|
|
|
|
|
|
|
|
err = c_append_tagged_name(qualified_type, indent, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, " {\n"))
|
|
|
|
return &drgn_enomem;
|
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
|
|
|
|
|
|
|
is_signed = drgn_enum_type_is_signed(qualified_type.type);
|
|
|
|
for (i = 0; i < num_enumerators; i++) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!append_tabs(indent + 1, sb) ||
|
|
|
|
!string_builder_append(sb, enumerators[i].name) ||
|
|
|
|
!string_builder_append(sb, " = "))
|
|
|
|
return &drgn_enomem;
|
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 (is_signed) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendf(sb, "%" PRId64 ",\n",
|
|
|
|
enumerators[i].svalue))
|
|
|
|
return &drgn_enomem;
|
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
|
|
|
} else {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendf(sb, "%" PRIu64 ",\n",
|
|
|
|
enumerators[i].uvalue))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
if (!append_tabs(indent, sb) || !string_builder_appendc(sb, '}'))
|
|
|
|
return &drgn_enomem;
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_define_typedef(struct drgn_qualified_type qualified_type, size_t indent,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct string_callback typedef_name = {
|
|
|
|
.fn = c_variable_name,
|
|
|
|
.arg = (char *)drgn_type_name(qualified_type.type),
|
|
|
|
};
|
|
|
|
struct drgn_qualified_type aliased_type;
|
|
|
|
struct drgn_error *err;
|
|
|
|
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!append_tabs(indent, sb))
|
|
|
|
return &drgn_enomem;
|
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 (qualified_type.qualifiers) {
|
|
|
|
err = c_append_qualifiers(qualified_type.qualifiers, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ' '))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb, "typedef "))
|
|
|
|
return &drgn_enomem;
|
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
|
|
|
|
|
|
|
aliased_type = drgn_type_type(qualified_type.type);
|
2021-11-23 08:52:39 +00:00
|
|
|
return c_declare_variable(aliased_type, &typedef_name, 0, true, sb);
|
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 *
|
|
|
|
c_define_type(struct drgn_qualified_type qualified_type, size_t indent,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
2020-12-04 19:20:00 +00:00
|
|
|
SWITCH_ENUM(drgn_type_kind(qualified_type.type),
|
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
|
|
|
case DRGN_TYPE_VOID:
|
|
|
|
case DRGN_TYPE_INT:
|
|
|
|
case DRGN_TYPE_BOOL:
|
|
|
|
case DRGN_TYPE_FLOAT:
|
|
|
|
return c_declare_basic(qualified_type, NULL, indent, sb);
|
|
|
|
case DRGN_TYPE_STRUCT:
|
|
|
|
case DRGN_TYPE_UNION:
|
2019-11-15 01:12:47 +00:00
|
|
|
case DRGN_TYPE_CLASS:
|
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 c_define_compound(qualified_type, indent, sb);
|
|
|
|
case DRGN_TYPE_ENUM:
|
|
|
|
return c_define_enum(qualified_type, indent, sb);
|
|
|
|
case DRGN_TYPE_TYPEDEF:
|
|
|
|
return c_define_typedef(qualified_type, indent, sb);
|
|
|
|
case DRGN_TYPE_POINTER:
|
|
|
|
return c_declare_pointer(qualified_type, NULL, indent, sb);
|
|
|
|
case DRGN_TYPE_ARRAY:
|
|
|
|
return c_declare_array(qualified_type, NULL, indent, sb);
|
|
|
|
case DRGN_TYPE_FUNCTION:
|
|
|
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
2019-11-28 03:27:14 +00:00
|
|
|
"function type cannot be formatted");
|
2020-12-04 19:20:00 +00: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-11-28 03:27:14 +00:00
|
|
|
c_format_type_name_impl(struct drgn_qualified_type qualified_type,
|
|
|
|
struct string_builder *sb)
|
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
|
|
|
{
|
2021-11-23 08:52:39 +00:00
|
|
|
if (drgn_type_kind(qualified_type.type) == DRGN_TYPE_FUNCTION) {
|
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 string_callback name_cb = {
|
|
|
|
.fn = c_variable_name,
|
|
|
|
.arg = (void *)"",
|
|
|
|
};
|
|
|
|
|
|
|
|
return c_declare_function(qualified_type, &name_cb, 0, sb);
|
|
|
|
} else {
|
2021-11-23 08:52:39 +00:00
|
|
|
return c_declare_variable(qualified_type, NULL, 0, false, sb);
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *
|
|
|
|
c_format_type_name(struct drgn_qualified_type qualified_type, char **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;
|
2022-10-05 22:41:12 +01:00
|
|
|
struct string_builder sb = STRING_BUILDER_INIT;
|
2019-11-28 03:27:14 +00:00
|
|
|
err = c_format_type_name_impl(qualified_type, &sb);
|
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) {
|
|
|
|
free(sb.str);
|
|
|
|
return err;
|
|
|
|
}
|
2022-09-21 18:43:31 +01:00
|
|
|
if (!(*ret = string_builder_null_terminate(&sb)))
|
2019-05-14 18:07:50 +01:00
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *
|
|
|
|
c_format_type(struct drgn_qualified_type qualified_type, char **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;
|
2022-10-05 22:41:12 +01:00
|
|
|
struct string_builder sb = STRING_BUILDER_INIT;
|
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 (drgn_type_is_complete(qualified_type.type))
|
|
|
|
err = c_define_type(qualified_type, 0, &sb);
|
|
|
|
else
|
2019-11-28 03:27:14 +00:00
|
|
|
err = c_format_type_name_impl(qualified_type, &sb);
|
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) {
|
|
|
|
free(sb.str);
|
|
|
|
return err;
|
|
|
|
}
|
2022-09-21 18:43:31 +01:00
|
|
|
if (!(*ret = string_builder_null_terminate(&sb)))
|
2019-05-14 18:07:50 +01:00
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2019-12-06 19:40:13 +00:00
|
|
|
c_format_object_impl(const struct drgn_object *obj, size_t indent,
|
|
|
|
size_t one_line_columns, size_t multi_line_columns,
|
2019-12-06 18:24:24 +00:00
|
|
|
enum drgn_format_object_flags flags,
|
|
|
|
struct string_builder *sb);
|
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-12-06 19:17:43 +00:00
|
|
|
static bool is_character_type(struct drgn_type *type)
|
|
|
|
{
|
|
|
|
switch (drgn_type_primitive(type)) {
|
|
|
|
case DRGN_C_TYPE_CHAR:
|
|
|
|
case DRGN_C_TYPE_SIGNED_CHAR:
|
|
|
|
case DRGN_C_TYPE_UNSIGNED_CHAR:
|
|
|
|
return true;
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_format_character(unsigned char c, bool escape_single_quote,
|
|
|
|
bool escape_double_quote, struct string_builder *sb)
|
|
|
|
{
|
|
|
|
bool ret;
|
|
|
|
|
|
|
|
switch (c) {
|
|
|
|
case '\0':
|
|
|
|
ret = string_builder_append(sb, "\\0");
|
|
|
|
break;
|
|
|
|
case '\a':
|
|
|
|
ret = string_builder_append(sb, "\\a");
|
|
|
|
break;
|
|
|
|
case '\b':
|
|
|
|
ret = string_builder_append(sb, "\\b");
|
|
|
|
break;
|
|
|
|
case '\t':
|
|
|
|
ret = string_builder_append(sb, "\\t");
|
|
|
|
break;
|
|
|
|
case '\n':
|
|
|
|
ret = string_builder_append(sb, "\\n");
|
|
|
|
break;
|
|
|
|
case '\v':
|
|
|
|
ret = string_builder_append(sb, "\\v");
|
|
|
|
break;
|
|
|
|
case '\f':
|
|
|
|
ret = string_builder_append(sb, "\\f");
|
|
|
|
break;
|
|
|
|
case '\r':
|
|
|
|
ret = string_builder_append(sb, "\\r");
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
if (!escape_double_quote)
|
|
|
|
goto no_escape;
|
|
|
|
ret = string_builder_append(sb, "\\\"");
|
|
|
|
break;
|
|
|
|
case '\'':
|
|
|
|
if (!escape_single_quote)
|
|
|
|
goto no_escape;
|
|
|
|
ret = string_builder_append(sb, "\\'");
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
ret = string_builder_append(sb, "\\\\");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (c <= '\x1f' || c >= '\x7f') {
|
|
|
|
ret = string_builder_appendf(sb, "\\x%02x", c);
|
|
|
|
} else {
|
|
|
|
no_escape:
|
|
|
|
ret = string_builder_appendc(sb, c);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ret ? NULL : &drgn_enomem;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2021-06-04 01:43:27 +01:00
|
|
|
c_format_string(struct drgn_program *prog, uint64_t address, uint64_t length,
|
|
|
|
struct string_builder *sb)
|
2019-12-06 19:17:43 +00:00
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
|
|
|
|
if (!string_builder_appendc(sb, '"'))
|
|
|
|
return &drgn_enomem;
|
|
|
|
while (length) {
|
|
|
|
unsigned char c;
|
2021-06-04 01:43:27 +01:00
|
|
|
err = drgn_program_read_memory(prog, &c, address++, 1, false);
|
2019-12-06 19:17:43 +00:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (c == '\0') {
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
err = c_format_character(c, false, true, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
length--;
|
|
|
|
}
|
|
|
|
if (!string_builder_appendc(sb, '"'))
|
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
static struct drgn_error *
|
2019-12-06 19:17:43 +00:00
|
|
|
c_format_int_object(const struct drgn_object *obj,
|
|
|
|
enum drgn_format_object_flags flags,
|
|
|
|
struct string_builder *sb)
|
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-12-06 19:17:43 +00:00
|
|
|
if ((flags & DRGN_FORMAT_OBJECT_CHAR) && is_character_type(obj->type)) {
|
|
|
|
union drgn_value value;
|
|
|
|
|
|
|
|
if (!string_builder_appendc(sb, '\''))
|
|
|
|
return &drgn_enomem;
|
|
|
|
err = drgn_object_read_integer(obj, &value);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
err = c_format_character(value.uvalue, true, false, sb);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (!string_builder_appendc(sb, '\''))
|
|
|
|
return &drgn_enomem;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
libdrgn: support value objects with >64-bit integer types
The Linux kernel's struct task_struct on AArch64 contains an array of
__uint128_t:
>>> task = find_task(prog, 1)
>>> task.type_
struct task_struct *
>>> task.thread.type_
struct thread_struct {
struct cpu_context cpu_context;
struct {
unsigned long tp_value;
unsigned long tp2_value;
struct user_fpsimd_state fpsimd_state;
} uw;
enum fp_type fp_type;
unsigned int fpsimd_cpu;
void *sve_state;
void *sme_state;
unsigned int vl[2];
unsigned int vl_onexec[2];
unsigned long fault_address;
unsigned long fault_code;
struct debug_info debug;
struct ptrauth_keys_user keys_user;
struct ptrauth_keys_kernel keys_kernel;
u64 mte_ctrl;
u64 sctlr_user;
u64 svcr;
u64 tpidr2_el0;
}
>>> task.thread.uw.fpsimd_state.type_
struct user_fpsimd_state {
__int128 unsigned vregs[32];
__u32 fpsr;
__u32 fpcr;
__u32 __reserved[2];
}
As a result, printing a task_struct fails:
>>> task
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/host/home/osandov/repos/drgn3/drgn/cli.py", line 140, in _displayhook
text = value.format_(columns=shutil.get_terminal_size((0, 0)).columns)
NotImplementedError: integer values larger than 64 bits are not yet supported
PR #311 suggested treating >64-bit integers as byte arrays for now; I
tried an alternate hack of handling >64-bit integers only in the
pretty-printing code. Both of these had issues, though.
Instead, let's push >64-bit integer support a little further and allow
storing "big integer" value objects. We still don't support any
operations on them, so this still doesn't complete #170. We store the
raw bytes of the value for now, but we'll probably change this if we add
support for operations (e.g., to store the value as an mp_limb_t array
for GMP). We also print >64-bit integer types in hexadecimal for
simplicity. This is inconsistent with the existing behavior of printing
in decimal, but more readable. In the future, we might want to add
heuristics to decide when to print in decimal vs hexadecimal for all
sizes.
Closes #311.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2023-08-02 21:12:19 +01:00
|
|
|
union drgn_value value_mem;
|
|
|
|
const union drgn_value *value;
|
|
|
|
err = drgn_object_read_value(obj, &value_mem, &value);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2020-12-04 20:01:29 +00:00
|
|
|
switch (obj->encoding) {
|
libdrgn: support value objects with >64-bit integer types
The Linux kernel's struct task_struct on AArch64 contains an array of
__uint128_t:
>>> task = find_task(prog, 1)
>>> task.type_
struct task_struct *
>>> task.thread.type_
struct thread_struct {
struct cpu_context cpu_context;
struct {
unsigned long tp_value;
unsigned long tp2_value;
struct user_fpsimd_state fpsimd_state;
} uw;
enum fp_type fp_type;
unsigned int fpsimd_cpu;
void *sve_state;
void *sme_state;
unsigned int vl[2];
unsigned int vl_onexec[2];
unsigned long fault_address;
unsigned long fault_code;
struct debug_info debug;
struct ptrauth_keys_user keys_user;
struct ptrauth_keys_kernel keys_kernel;
u64 mte_ctrl;
u64 sctlr_user;
u64 svcr;
u64 tpidr2_el0;
}
>>> task.thread.uw.fpsimd_state.type_
struct user_fpsimd_state {
__int128 unsigned vregs[32];
__u32 fpsr;
__u32 fpcr;
__u32 __reserved[2];
}
As a result, printing a task_struct fails:
>>> task
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/host/home/osandov/repos/drgn3/drgn/cli.py", line 140, in _displayhook
text = value.format_(columns=shutil.get_terminal_size((0, 0)).columns)
NotImplementedError: integer values larger than 64 bits are not yet supported
PR #311 suggested treating >64-bit integers as byte arrays for now; I
tried an alternate hack of handling >64-bit integers only in the
pretty-printing code. Both of these had issues, though.
Instead, let's push >64-bit integer support a little further and allow
storing "big integer" value objects. We still don't support any
operations on them, so this still doesn't complete #170. We store the
raw bytes of the value for now, but we'll probably change this if we add
support for operations (e.g., to store the value as an mp_limb_t array
for GMP). We also print >64-bit integer types in hexadecimal for
simplicity. This is inconsistent with the existing behavior of printing
in decimal, but more readable. In the future, we might want to add
heuristics to decide when to print in decimal vs hexadecimal for all
sizes.
Closes #311.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2023-08-02 21:12:19 +01:00
|
|
|
case DRGN_OBJECT_ENCODING_SIGNED:
|
|
|
|
if (!string_builder_appendf(sb, "%" PRId64, value->svalue)) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DRGN_OBJECT_ENCODING_UNSIGNED:
|
|
|
|
if (!string_builder_appendf(sb, "%" PRIu64, value->uvalue)) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DRGN_OBJECT_ENCODING_SIGNED_BIG:
|
|
|
|
case DRGN_OBJECT_ENCODING_UNSIGNED_BIG: {
|
|
|
|
if (!string_builder_append(sb, "0x")) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
const uint8_t *buf = (uint8_t *)value->bufp;
|
|
|
|
size_t bytes = drgn_object_size(obj);
|
|
|
|
if (obj->little_endian) {
|
|
|
|
size_t i = bytes - 1;
|
|
|
|
while (i > 0 && buf[i] == 0)
|
|
|
|
i--;
|
|
|
|
if (!string_builder_appendf(sb, "%" PRIx8, buf[i])) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
while (i-- > 0) {
|
|
|
|
if (!string_builder_appendf(sb, "%02" PRIx8, buf[i])) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
size_t i = 0;
|
|
|
|
while (i < bytes - 1 && buf[i] == 0)
|
|
|
|
i++;
|
|
|
|
if (!string_builder_appendf(sb, "%" PRIx8, buf[i])) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
while (++i < bytes) {
|
|
|
|
if (!string_builder_appendf(sb, "%02" PRIx8, buf[i])) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
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
|
|
|
}
|
|
|
|
default:
|
2020-05-07 23:02:33 +01:00
|
|
|
UNREACHABLE();
|
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: support value objects with >64-bit integer types
The Linux kernel's struct task_struct on AArch64 contains an array of
__uint128_t:
>>> task = find_task(prog, 1)
>>> task.type_
struct task_struct *
>>> task.thread.type_
struct thread_struct {
struct cpu_context cpu_context;
struct {
unsigned long tp_value;
unsigned long tp2_value;
struct user_fpsimd_state fpsimd_state;
} uw;
enum fp_type fp_type;
unsigned int fpsimd_cpu;
void *sve_state;
void *sme_state;
unsigned int vl[2];
unsigned int vl_onexec[2];
unsigned long fault_address;
unsigned long fault_code;
struct debug_info debug;
struct ptrauth_keys_user keys_user;
struct ptrauth_keys_kernel keys_kernel;
u64 mte_ctrl;
u64 sctlr_user;
u64 svcr;
u64 tpidr2_el0;
}
>>> task.thread.uw.fpsimd_state.type_
struct user_fpsimd_state {
__int128 unsigned vregs[32];
__u32 fpsr;
__u32 fpcr;
__u32 __reserved[2];
}
As a result, printing a task_struct fails:
>>> task
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/host/home/osandov/repos/drgn3/drgn/cli.py", line 140, in _displayhook
text = value.format_(columns=shutil.get_terminal_size((0, 0)).columns)
NotImplementedError: integer values larger than 64 bits are not yet supported
PR #311 suggested treating >64-bit integers as byte arrays for now; I
tried an alternate hack of handling >64-bit integers only in the
pretty-printing code. Both of these had issues, though.
Instead, let's push >64-bit integer support a little further and allow
storing "big integer" value objects. We still don't support any
operations on them, so this still doesn't complete #170. We store the
raw bytes of the value for now, but we'll probably change this if we add
support for operations (e.g., to store the value as an mp_limb_t array
for GMP). We also print >64-bit integer types in hexadecimal for
simplicity. This is inconsistent with the existing behavior of printing
in decimal, but more readable. In the future, we might want to add
heuristics to decide when to print in decimal vs hexadecimal for all
sizes.
Closes #311.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2023-08-02 21:12:19 +01:00
|
|
|
err = NULL;
|
|
|
|
out:
|
|
|
|
drgn_object_deinit_value(obj, value);
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2019-11-28 03:27:14 +00:00
|
|
|
c_format_float_object(const struct drgn_object *obj, struct string_builder *sb)
|
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;
|
|
|
|
double fvalue;
|
|
|
|
|
|
|
|
err = drgn_object_read_float(obj, &fvalue);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (rint(fvalue) == fvalue) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendf(sb, "%.1f", fvalue))
|
|
|
|
return &drgn_enomem;
|
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
|
|
|
} else {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendf(sb, "%.*g", DBL_DECIMAL_DIG,
|
|
|
|
fvalue))
|
|
|
|
return &drgn_enomem;
|
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-14 18:07:50 +01:00
|
|
|
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-12-06 23:25:39 +00:00
|
|
|
static struct drgn_error drgn_line_wrap = {
|
|
|
|
.code = DRGN_ERROR_STOP,
|
|
|
|
.message = "needs line wrap",
|
|
|
|
};
|
|
|
|
|
|
|
|
struct initializer_iter {
|
|
|
|
struct drgn_error *(*next)(struct initializer_iter *,
|
|
|
|
struct drgn_object *,
|
|
|
|
enum drgn_format_object_flags *);
|
|
|
|
void (*reset)(struct initializer_iter *);
|
2019-12-09 20:44:25 +00:00
|
|
|
struct drgn_error *(*append_designation)(struct initializer_iter *,
|
|
|
|
struct string_builder *);
|
2019-12-06 23:25:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct drgn_error *c_format_initializer(struct drgn_program *prog,
|
|
|
|
struct initializer_iter *iter,
|
|
|
|
size_t indent,
|
|
|
|
size_t one_line_columns,
|
|
|
|
size_t multi_line_columns,
|
2019-12-09 20:44:25 +00:00
|
|
|
bool same_line,
|
2019-12-06 23:25:39 +00:00
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_object obj;
|
|
|
|
enum drgn_format_object_flags initializer_flags;
|
|
|
|
size_t brace, remaining_columns, start_columns;
|
|
|
|
|
|
|
|
drgn_object_init(&obj, prog);
|
|
|
|
|
|
|
|
/* First, try to fit everything on one line. */
|
|
|
|
brace = sb->len;
|
|
|
|
if (!string_builder_appendc(sb, '{')) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
if (__builtin_sub_overflow(one_line_columns, 1, &remaining_columns))
|
|
|
|
remaining_columns = 0;
|
|
|
|
for (;;) {
|
|
|
|
size_t initializer_start;
|
|
|
|
|
|
|
|
err = iter->next(iter, &obj, &initializer_flags);
|
2021-03-05 20:46:06 +00:00
|
|
|
if (err == &drgn_stop)
|
2019-12-06 23:25:39 +00:00
|
|
|
break;
|
|
|
|
else if (err)
|
|
|
|
goto out;
|
|
|
|
|
2019-12-09 20:44:25 +00:00
|
|
|
if (!same_line) {
|
|
|
|
err = &drgn_line_wrap;
|
|
|
|
break;
|
|
|
|
} else if (sb->len == brace + 1) {
|
2019-12-06 23:25:39 +00:00
|
|
|
if (remaining_columns < 3) {
|
|
|
|
/*
|
|
|
|
* The preceding space and closing space and
|
|
|
|
* brace don't fit.
|
|
|
|
*/
|
|
|
|
err = &drgn_line_wrap;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!string_builder_appendc(sb, ' ')) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
remaining_columns--;
|
|
|
|
} else {
|
|
|
|
if (remaining_columns < 4) {
|
|
|
|
/*
|
|
|
|
* The preceding comma and space and closing
|
|
|
|
* space and brace don't fit.
|
|
|
|
*/
|
|
|
|
err = &drgn_line_wrap;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!string_builder_append(sb, ", ")) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
remaining_columns -= 2;
|
|
|
|
}
|
|
|
|
|
2019-12-09 20:44:25 +00:00
|
|
|
if (iter->append_designation) {
|
|
|
|
size_t designation_start = sb->len;
|
|
|
|
|
|
|
|
err = iter->append_designation(iter, sb);
|
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
if (__builtin_sub_overflow(remaining_columns,
|
|
|
|
sb->len - designation_start,
|
|
|
|
&remaining_columns)) {
|
|
|
|
err = &drgn_line_wrap;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-06 23:25:39 +00:00
|
|
|
initializer_start = sb->len;
|
|
|
|
err = c_format_object_impl(&obj, indent + 1,
|
|
|
|
remaining_columns - 2, 0,
|
|
|
|
initializer_flags, sb);
|
|
|
|
if (err == &drgn_line_wrap)
|
|
|
|
break;
|
|
|
|
else if (err)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
if (__builtin_sub_overflow(remaining_columns,
|
|
|
|
sb->len - initializer_start,
|
|
|
|
&remaining_columns)) {
|
|
|
|
err = &drgn_line_wrap;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (err != &drgn_line_wrap) {
|
|
|
|
/* All of the initializers fit. */
|
|
|
|
if (sb->len == brace + 1) {
|
|
|
|
/* There were no initializers. */
|
|
|
|
if (string_builder_appendc(sb, '}'))
|
|
|
|
err = NULL;
|
|
|
|
else
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
} else if (remaining_columns >= 2) {
|
|
|
|
if (string_builder_append(sb, " }"))
|
|
|
|
err = NULL;
|
|
|
|
else
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/* The final space and closing brace didn't fit. */
|
|
|
|
}
|
|
|
|
|
|
|
|
/* It didn't fit on one line. Try multiple lines. */
|
|
|
|
|
|
|
|
if (multi_line_columns == 0) {
|
|
|
|
/* We were asked to stay on one line. */
|
|
|
|
err = &drgn_line_wrap;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
sb->len = brace + 1;
|
|
|
|
if (__builtin_sub_overflow(multi_line_columns, 8 * (indent + 1),
|
|
|
|
&start_columns))
|
|
|
|
start_columns = 0;
|
|
|
|
remaining_columns = 0;
|
|
|
|
iter->reset(iter);
|
|
|
|
for (;;) {
|
2019-12-09 20:44:25 +00:00
|
|
|
size_t newline, designation_start, line_columns;
|
2019-12-06 23:25:39 +00:00
|
|
|
|
|
|
|
err = iter->next(iter, &obj, &initializer_flags);
|
2021-03-05 20:46:06 +00:00
|
|
|
if (err == &drgn_stop)
|
2019-12-06 23:25:39 +00:00
|
|
|
break;
|
|
|
|
else if (err)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
newline = sb->len;
|
|
|
|
if (!string_builder_appendc(sb, '\n') ||
|
|
|
|
!append_tabs(indent + 1, sb)) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2019-12-09 20:44:25 +00:00
|
|
|
designation_start = sb->len;
|
|
|
|
line_columns = start_columns;
|
|
|
|
if (iter->append_designation) {
|
|
|
|
err = iter->append_designation(iter, sb);
|
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
if (__builtin_sub_overflow(line_columns,
|
|
|
|
sb->len - designation_start,
|
|
|
|
&line_columns))
|
|
|
|
line_columns = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (line_columns > 1) {
|
2019-12-06 23:25:39 +00:00
|
|
|
size_t initializer_start = sb->len;
|
|
|
|
|
2019-12-09 20:44:25 +00:00
|
|
|
err = c_format_object_impl(&obj, 0, line_columns - 1,
|
2019-12-06 23:25:39 +00:00
|
|
|
0, initializer_flags, sb);
|
|
|
|
if (!err) {
|
2019-12-09 20:44:25 +00:00
|
|
|
size_t len = sb->len - designation_start;
|
2019-12-06 23:25:39 +00:00
|
|
|
|
2019-12-09 20:44:25 +00:00
|
|
|
if (same_line && len + 2 <= remaining_columns) {
|
2019-12-06 23:25:39 +00:00
|
|
|
/*
|
|
|
|
* It would've fit on the previous line.
|
|
|
|
* Move it over.
|
|
|
|
*/
|
|
|
|
sb->str[newline] = ' ';
|
|
|
|
memmove(&sb->str[newline + 1],
|
2019-12-09 20:44:25 +00:00
|
|
|
&sb->str[designation_start],
|
|
|
|
len);
|
|
|
|
sb->len = newline + 1 + len;
|
2019-12-06 23:25:39 +00:00
|
|
|
if (!string_builder_appendc(sb, ',')) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
2019-12-09 20:44:25 +00:00
|
|
|
remaining_columns -= len + 2;
|
2019-12-06 23:25:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
2019-12-09 20:44:25 +00:00
|
|
|
if (len < start_columns) {
|
2019-12-06 23:25:39 +00:00
|
|
|
/* It fit on the new line. */
|
|
|
|
if (!string_builder_appendc(sb, ',')) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
remaining_columns =
|
2019-12-09 20:44:25 +00:00
|
|
|
start_columns - len - 1;
|
2019-12-06 23:25:39 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else if (err != &drgn_line_wrap) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
/* It didn't fit. */
|
|
|
|
sb->len = initializer_start;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = c_format_object_impl(&obj, indent + 1, 0,
|
|
|
|
multi_line_columns,
|
|
|
|
initializer_flags, sb);
|
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
if (!string_builder_appendc(sb, ',')) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
remaining_columns = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!string_builder_appendc(sb, '\n') || !append_tabs(indent, sb) ||
|
|
|
|
!string_builder_appendc(sb, '}')) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
err = NULL;
|
|
|
|
out:
|
|
|
|
drgn_object_deinit(&obj);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2019-12-09 20:44:25 +00:00
|
|
|
struct compound_initializer_state {
|
|
|
|
struct drgn_type_member *member, *end;
|
|
|
|
uint64_t bit_offset;
|
|
|
|
};
|
|
|
|
|
2023-08-02 22:54:59 +01:00
|
|
|
DEFINE_VECTOR(compound_initializer_stack, struct compound_initializer_state);
|
2019-12-09 20:44:25 +00:00
|
|
|
|
|
|
|
struct compound_initializer_iter {
|
|
|
|
struct initializer_iter iter;
|
|
|
|
const struct drgn_object *obj;
|
|
|
|
struct compound_initializer_stack stack;
|
2019-12-10 00:22:24 +00:00
|
|
|
enum drgn_format_object_flags flags, member_flags;
|
2019-12-09 20:44:25 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
compound_initializer_iter_next(struct initializer_iter *iter_,
|
|
|
|
struct drgn_object *obj_ret,
|
|
|
|
enum drgn_format_object_flags *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
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
2019-12-09 20:44:25 +00:00
|
|
|
struct compound_initializer_iter *iter =
|
|
|
|
container_of(iter_, struct compound_initializer_iter, iter);
|
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-12-09 20:44:25 +00:00
|
|
|
for (;;) {
|
|
|
|
if (!iter->stack.size)
|
|
|
|
return &drgn_stop;
|
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
|
|
|
|
2020-12-18 22:11:29 +00:00
|
|
|
struct compound_initializer_state *top =
|
|
|
|
&iter->stack.data[iter->stack.size - 1];
|
2019-12-09 20:44:25 +00:00
|
|
|
if (top->member == top->end) {
|
|
|
|
iter->stack.size--;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-12-18 22:11:29 +00:00
|
|
|
uint64_t bit_offset = top->bit_offset;
|
|
|
|
struct drgn_type_member *member = top->member++;
|
|
|
|
struct drgn_qualified_type member_type;
|
|
|
|
uint64_t member_bit_field_size;
|
|
|
|
err = drgn_member_type(member, &member_type,
|
|
|
|
&member_bit_field_size);
|
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;
|
|
|
|
|
2019-12-09 20:44:25 +00:00
|
|
|
/*
|
2019-12-10 00:22:24 +00:00
|
|
|
* If the member is named or we are not including names, return
|
|
|
|
* it. Otherwise, if it has members, descend into it. If it
|
|
|
|
* doesn't, then this isn't valid C, but let's return it
|
|
|
|
* anyways.
|
2019-12-09 20:44:25 +00:00
|
|
|
*/
|
2019-12-10 00:22:24 +00:00
|
|
|
if (member->name ||
|
|
|
|
!(iter->flags & DRGN_FORMAT_OBJECT_MEMBER_NAMES) ||
|
2019-12-10 09:36:45 +00:00
|
|
|
!drgn_type_has_members(member_type.type)) {
|
|
|
|
err = drgn_object_slice(obj_ret, iter->obj, member_type,
|
2020-04-14 00:16:34 +01:00
|
|
|
bit_offset + member->bit_offset,
|
2020-12-18 22:11:29 +00:00
|
|
|
member_bit_field_size);
|
2019-12-10 09:36:45 +00:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
/* If we're including names, we can skip zeroes. */
|
|
|
|
if ((iter->flags & (DRGN_FORMAT_OBJECT_MEMBER_NAMES |
|
|
|
|
DRGN_FORMAT_OBJECT_IMPLICIT_MEMBERS)) ==
|
|
|
|
DRGN_FORMAT_OBJECT_MEMBER_NAMES) {
|
|
|
|
bool zero;
|
|
|
|
|
|
|
|
err = drgn_object_is_zero(obj_ret, &zero);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (zero)
|
|
|
|
continue;
|
|
|
|
}
|
2019-12-09 20:44:25 +00:00
|
|
|
break;
|
2019-12-10 09:36:45 +00: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
|
|
|
|
2020-12-18 22:11:29 +00:00
|
|
|
struct compound_initializer_state *new =
|
|
|
|
compound_initializer_stack_append_entry(&iter->stack);
|
2019-12-09 20:44:25 +00:00
|
|
|
if (!new)
|
|
|
|
return &drgn_enomem;
|
|
|
|
new->member = drgn_type_members(member_type.type);
|
|
|
|
new->end = new->member + drgn_type_num_members(member_type.type);
|
2020-04-14 00:16:34 +01:00
|
|
|
new->bit_offset = bit_offset + member->bit_offset;
|
2019-12-09 20:44:25 +00: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-12-09 20:44:25 +00:00
|
|
|
*flags_ret = iter->member_flags;
|
|
|
|
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-12-09 20:44:25 +00:00
|
|
|
static void compound_initializer_iter_reset(struct initializer_iter *iter_)
|
|
|
|
{
|
|
|
|
struct compound_initializer_iter *iter =
|
|
|
|
container_of(iter_, struct compound_initializer_iter, iter);
|
|
|
|
struct drgn_type *underlying_type =
|
|
|
|
drgn_underlying_type(iter->obj->type);
|
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-12-09 20:44:25 +00:00
|
|
|
iter->stack.size = 1;
|
|
|
|
iter->stack.data[0].member = drgn_type_members(underlying_type);
|
|
|
|
}
|
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-12-09 20:44:25 +00:00
|
|
|
static struct drgn_error *
|
|
|
|
compound_initializer_append_designation(struct initializer_iter *iter_,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct compound_initializer_iter *iter =
|
|
|
|
container_of(iter_, struct compound_initializer_iter, iter);
|
|
|
|
struct compound_initializer_state *top =
|
|
|
|
&iter->stack.data[iter->stack.size - 1];
|
|
|
|
const char *name = top->member[-1].name;
|
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-12-09 20:44:25 +00:00
|
|
|
if (name && !string_builder_appendf(sb, ".%s = ", name))
|
|
|
|
return &drgn_enomem;
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2019-11-28 03:27:14 +00:00
|
|
|
c_format_compound_object(const struct drgn_object *obj,
|
|
|
|
struct drgn_type *underlying_type, size_t indent,
|
2019-12-09 20:52:05 +00:00
|
|
|
size_t one_line_columns, size_t multi_line_columns,
|
2019-12-12 22:30:04 +00:00
|
|
|
enum drgn_format_object_flags flags,
|
|
|
|
struct string_builder *sb)
|
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;
|
|
|
|
|
|
|
|
if (!drgn_type_is_complete(underlying_type)) {
|
2019-11-15 01:12:47 +00:00
|
|
|
const char *keyword;
|
|
|
|
|
|
|
|
switch (drgn_type_kind(underlying_type)) {
|
|
|
|
case DRGN_TYPE_STRUCT:
|
|
|
|
keyword = "struct";
|
|
|
|
break;
|
|
|
|
case DRGN_TYPE_UNION:
|
|
|
|
keyword = "union";
|
|
|
|
break;
|
|
|
|
case DRGN_TYPE_CLASS:
|
|
|
|
keyword = "class";
|
|
|
|
break;
|
|
|
|
default:
|
2020-05-07 23:02:33 +01:00
|
|
|
UNREACHABLE();
|
2019-11-15 01:12:47 +00: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
|
|
|
return drgn_error_format(DRGN_ERROR_TYPE,
|
|
|
|
"cannot format incomplete %s object",
|
2019-11-15 01:12:47 +00:00
|
|
|
keyword);
|
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
|
|
|
}
|
|
|
|
|
2020-12-18 22:11:29 +00:00
|
|
|
struct compound_initializer_iter iter = {
|
|
|
|
.iter = {
|
|
|
|
.next = compound_initializer_iter_next,
|
|
|
|
.reset = compound_initializer_iter_reset,
|
|
|
|
.append_designation =
|
|
|
|
flags & DRGN_FORMAT_OBJECT_MEMBER_NAMES ?
|
|
|
|
compound_initializer_append_designation : NULL,
|
|
|
|
},
|
|
|
|
.obj = obj,
|
|
|
|
.stack = VECTOR_INIT,
|
|
|
|
.flags = flags,
|
|
|
|
.member_flags = drgn_member_format_object_flags(flags),
|
|
|
|
};
|
|
|
|
struct compound_initializer_state *new =
|
|
|
|
compound_initializer_stack_append_entry(&iter.stack);
|
2019-12-09 20:44:25 +00:00
|
|
|
if (!new) {
|
|
|
|
err = &drgn_enomem;
|
|
|
|
goto out;
|
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-12-09 20:44:25 +00:00
|
|
|
new->member = drgn_type_members(underlying_type);
|
2021-04-02 21:36:03 +01:00
|
|
|
new->end = add_to_possibly_null_pointer(new->member,
|
|
|
|
drgn_type_num_members(underlying_type));
|
2019-12-09 20:44:25 +00:00
|
|
|
new->bit_offset = 0;
|
2019-12-10 09:36:45 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* If we don't want zero members, ignore any at the end. If we're
|
|
|
|
* including member names, then we'll skip past zero members as we
|
|
|
|
* iterate, so we don't need to do this.
|
|
|
|
*/
|
|
|
|
if (!(flags & (DRGN_FORMAT_OBJECT_MEMBER_NAMES |
|
|
|
|
DRGN_FORMAT_OBJECT_IMPLICIT_MEMBERS)) &&
|
|
|
|
new->member < new->end) {
|
|
|
|
struct drgn_object member;
|
2020-08-27 19:26:39 +01:00
|
|
|
drgn_object_init(&member, drgn_object_program(obj));
|
2019-12-10 09:36:45 +00:00
|
|
|
do {
|
|
|
|
struct drgn_qualified_type member_type;
|
2020-12-18 22:11:29 +00:00
|
|
|
uint64_t member_bit_field_size;
|
|
|
|
err = drgn_member_type(&new->end[-1], &member_type,
|
|
|
|
&member_bit_field_size);
|
2019-12-10 09:36:45 +00:00
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
|
|
|
|
err = drgn_object_slice(&member, obj, member_type,
|
|
|
|
new->end[-1].bit_offset,
|
2020-12-18 22:11:29 +00:00
|
|
|
member_bit_field_size);
|
2019-12-10 09:36:45 +00:00
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
|
2020-12-18 22:11:29 +00:00
|
|
|
bool zero;
|
2019-12-10 09:36:45 +00:00
|
|
|
err = drgn_object_is_zero(&member, &zero);
|
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
if (zero)
|
|
|
|
new->end--;
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
} while (new->member < new->end);
|
|
|
|
drgn_object_deinit(&member);
|
|
|
|
if (err)
|
2023-01-06 22:46:08 +00:00
|
|
|
goto out;
|
2019-12-10 09:36:45 +00:00
|
|
|
}
|
|
|
|
|
2020-08-27 19:26:39 +01:00
|
|
|
err = c_format_initializer(drgn_object_program(obj), &iter.iter, indent,
|
2019-12-09 20:52:05 +00:00
|
|
|
one_line_columns, multi_line_columns,
|
|
|
|
flags & DRGN_FORMAT_OBJECT_MEMBERS_SAME_LINE,
|
|
|
|
sb);
|
2019-12-09 20:44:25 +00:00
|
|
|
out:
|
|
|
|
compound_initializer_stack_deinit(&iter.stack);
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2019-11-28 03:27:14 +00:00
|
|
|
c_format_enum_object(const struct drgn_object *obj,
|
|
|
|
struct drgn_type *underlying_type,
|
|
|
|
struct string_builder *sb)
|
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_type_enumerator *enumerators;
|
|
|
|
size_t num_enumerators, i;
|
|
|
|
|
|
|
|
if (!drgn_type_is_complete(underlying_type)) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_TYPE,
|
|
|
|
"cannot format incomplete enum object");
|
|
|
|
}
|
|
|
|
|
|
|
|
enumerators = drgn_type_enumerators(underlying_type);
|
|
|
|
num_enumerators = drgn_type_num_enumerators(underlying_type);
|
|
|
|
if (drgn_enum_type_is_signed(underlying_type)) {
|
|
|
|
int64_t svalue;
|
|
|
|
|
|
|
|
err = drgn_object_read_signed(obj, &svalue);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
for (i = 0; i < num_enumerators; i++) {
|
|
|
|
if (enumerators[i].svalue == svalue) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb,
|
|
|
|
enumerators[i].name))
|
|
|
|
return &drgn_enomem;
|
|
|
|
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-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendf(sb, "%" PRId64, svalue))
|
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
} else {
|
|
|
|
uint64_t uvalue;
|
|
|
|
|
|
|
|
err = drgn_object_read_unsigned(obj, &uvalue);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
for (i = 0; i < num_enumerators; i++) {
|
|
|
|
if (enumerators[i].uvalue == uvalue) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_append(sb,
|
|
|
|
enumerators[i].name))
|
|
|
|
return &drgn_enomem;
|
|
|
|
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-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendf(sb, "%" PRIu64, uvalue))
|
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2019-11-28 03:27:14 +00:00
|
|
|
c_format_pointer_object(const struct drgn_object *obj,
|
2019-12-06 19:40:13 +00:00
|
|
|
struct drgn_type *underlying_type,
|
2019-12-06 18:24:24 +00:00
|
|
|
size_t indent, size_t one_line_columns,
|
|
|
|
size_t multi_line_columns,
|
|
|
|
enum drgn_format_object_flags flags,
|
2019-11-28 03:27:14 +00:00
|
|
|
struct string_builder *sb)
|
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-12-12 22:30:04 +00:00
|
|
|
enum drgn_format_object_flags passthrough_flags =
|
|
|
|
drgn_passthrough_format_object_flags(flags);
|
2019-12-06 18:24:24 +00:00
|
|
|
bool dereference = flags & DRGN_FORMAT_OBJECT_DEREFERENCE;
|
2019-12-06 18:59:31 +00:00
|
|
|
bool c_string =
|
|
|
|
((flags & DRGN_FORMAT_OBJECT_STRING) &&
|
|
|
|
is_character_type(drgn_type_type(underlying_type).type));
|
2019-12-12 22:30:04 +00:00
|
|
|
bool have_symbol;
|
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
|
|
|
uint64_t uvalue;
|
2019-12-12 22:30:04 +00:00
|
|
|
struct drgn_symbol sym;
|
|
|
|
size_t start, type_start, type_end, value_start, value_end;
|
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-12-12 22:30:04 +00:00
|
|
|
start = sb->len;
|
2019-12-06 18:59:31 +00:00
|
|
|
if (dereference && !c_string && !string_builder_appendc(sb, '*'))
|
|
|
|
return &drgn_enomem;
|
2019-12-12 22:30:04 +00:00
|
|
|
type_start = sb->len;
|
2019-12-06 19:40:13 +00:00
|
|
|
if (flags & DRGN_FORMAT_OBJECT_TYPE_NAME) {
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, '('))
|
|
|
|
return &drgn_enomem;
|
2019-11-28 03:27:14 +00:00
|
|
|
err = c_format_type_name_impl(drgn_object_qualified_type(obj),
|
|
|
|
sb);
|
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;
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ')'))
|
|
|
|
return &drgn_enomem;
|
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-12-12 22:30:04 +00:00
|
|
|
type_end = sb->len;
|
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_object_read_unsigned(obj, &uvalue);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
2019-12-12 22:30:04 +00:00
|
|
|
have_symbol = ((flags & DRGN_FORMAT_OBJECT_SYMBOLIZE) &&
|
2020-08-27 19:26:39 +01:00
|
|
|
drgn_program_find_symbol_by_address_internal(drgn_object_program(obj),
|
2020-02-07 16:42:25 +00:00
|
|
|
uvalue,
|
|
|
|
NULL,
|
|
|
|
&sym));
|
2019-12-06 18:59:31 +00:00
|
|
|
if (have_symbol && dereference && !c_string &&
|
2019-12-12 22:30:04 +00:00
|
|
|
!string_builder_appendc(sb, '('))
|
|
|
|
return &drgn_enomem;
|
|
|
|
value_start = sb->len;
|
|
|
|
if (have_symbol &&
|
|
|
|
!string_builder_appendf(sb, "%s+0x%" PRIx64 " = ", sym.name,
|
|
|
|
uvalue - sym.address))
|
|
|
|
return &drgn_enomem;
|
|
|
|
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendf(sb, "0x%" PRIx64, uvalue))
|
|
|
|
return &drgn_enomem;
|
2019-12-06 18:59:31 +00:00
|
|
|
if (!dereference && !c_string)
|
2019-05-14 18:07:50 +01:00
|
|
|
return NULL;
|
2019-12-12 22:30:04 +00:00
|
|
|
value_end = sb->len;
|
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-12-06 18:59:31 +00:00
|
|
|
if ((have_symbol && dereference && !c_string &&
|
2019-12-12 22:30:04 +00:00
|
|
|
!string_builder_appendc(sb, ')')) ||
|
|
|
|
!string_builder_append(sb, " = "))
|
2019-05-14 18:07:50 +01:00
|
|
|
return &drgn_enomem;
|
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-12-06 18:59:31 +00:00
|
|
|
if (c_string) {
|
2021-06-04 01:43:27 +01:00
|
|
|
err = c_format_string(drgn_object_program(obj), uvalue,
|
2020-08-27 19:26:39 +01:00
|
|
|
UINT64_MAX, sb);
|
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
|
|
|
} else {
|
|
|
|
struct drgn_object dereferenced;
|
|
|
|
|
2020-08-27 19:26:39 +01:00
|
|
|
drgn_object_init(&dereferenced, drgn_object_program(obj));
|
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_object_dereference(&dereferenced, obj);
|
|
|
|
if (err) {
|
|
|
|
drgn_object_deinit(&dereferenced);
|
|
|
|
if (err->code == DRGN_ERROR_TYPE)
|
|
|
|
goto no_dereference;
|
|
|
|
return err;
|
|
|
|
}
|
2019-12-12 22:30:04 +00:00
|
|
|
if (__builtin_sub_overflow(one_line_columns, sb->len - start,
|
|
|
|
&one_line_columns))
|
|
|
|
one_line_columns = 0;
|
2019-12-06 19:40:13 +00:00
|
|
|
err = c_format_object_impl(&dereferenced, indent,
|
2019-11-28 03:27:14 +00:00
|
|
|
one_line_columns, multi_line_columns,
|
2019-12-12 22:30:04 +00:00
|
|
|
passthrough_flags, sb);
|
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_object_deinit(&dereferenced);
|
|
|
|
}
|
2020-02-03 18:07:07 +00:00
|
|
|
if (!err || (err->code != DRGN_ERROR_FAULT && err->code != DRGN_ERROR_OUT_OF_BOUNDS)) {
|
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
|
|
|
/* We either succeeded or hit a fatal error. */
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
no_dereference:
|
|
|
|
/*
|
2019-12-12 22:30:04 +00:00
|
|
|
* We hit a non-fatal error. Delete the asterisk and symbol parentheses
|
|
|
|
* and truncate everything after the address.
|
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_error_destroy(err);
|
2019-12-12 22:30:04 +00:00
|
|
|
if (type_start != start) {
|
|
|
|
memmove(&sb->str[start], &sb->str[type_start],
|
|
|
|
type_end - type_start);
|
|
|
|
}
|
|
|
|
if (start + type_end - type_start != value_start) {
|
|
|
|
memmove(&sb->str[start + type_end - type_start],
|
|
|
|
&sb->str[value_start], value_end - value_start);
|
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-12-12 22:30:04 +00:00
|
|
|
sb->len = start + type_end - type_start + value_end - value_start;
|
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-12-06 23:25:39 +00:00
|
|
|
struct array_initializer_iter {
|
|
|
|
struct initializer_iter iter;
|
|
|
|
const struct drgn_object *obj;
|
|
|
|
struct drgn_qualified_type element_type;
|
|
|
|
uint64_t element_bit_size;
|
|
|
|
uint64_t length, i;
|
2019-12-10 00:35:33 +00:00
|
|
|
enum drgn_format_object_flags flags, element_flags;
|
2019-12-06 23:25:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
array_initializer_iter_next(struct initializer_iter *iter_,
|
|
|
|
struct drgn_object *obj_ret,
|
|
|
|
enum drgn_format_object_flags *flags_ret)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct array_initializer_iter *iter =
|
|
|
|
container_of(iter_, struct array_initializer_iter, iter);
|
|
|
|
|
2019-12-10 00:35:33 +00:00
|
|
|
for (;;) {
|
|
|
|
bool zero;
|
|
|
|
|
|
|
|
if (iter->i >= iter->length)
|
|
|
|
return &drgn_stop;
|
|
|
|
err = drgn_object_slice(obj_ret, iter->obj, iter->element_type,
|
|
|
|
iter->i * iter->element_bit_size, 0);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
iter->i++;
|
|
|
|
|
|
|
|
/* If we're including indices, we can skip zeroes. */
|
2019-12-10 09:48:06 +00:00
|
|
|
if ((iter->flags & (DRGN_FORMAT_OBJECT_ELEMENT_INDICES |
|
|
|
|
DRGN_FORMAT_OBJECT_IMPLICIT_ELEMENTS)) !=
|
|
|
|
DRGN_FORMAT_OBJECT_ELEMENT_INDICES)
|
2019-12-10 00:35:33 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
err = drgn_object_is_zero(obj_ret, &zero);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (!zero)
|
|
|
|
break;
|
|
|
|
}
|
2019-12-06 23:25:39 +00:00
|
|
|
*flags_ret = iter->element_flags;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void array_initializer_iter_reset(struct initializer_iter *iter_)
|
|
|
|
{
|
|
|
|
struct array_initializer_iter *iter =
|
|
|
|
container_of(iter_, struct array_initializer_iter, iter);
|
|
|
|
|
|
|
|
iter->i = 0;
|
|
|
|
}
|
|
|
|
|
2019-12-10 00:35:33 +00:00
|
|
|
static struct drgn_error *
|
|
|
|
array_initializer_append_designation(struct initializer_iter *iter_,
|
|
|
|
struct string_builder *sb)
|
|
|
|
{
|
|
|
|
struct array_initializer_iter *iter =
|
|
|
|
container_of(iter_, struct array_initializer_iter, iter);
|
|
|
|
|
|
|
|
if (!string_builder_appendf(sb, "[%" PRIu64 "] = ", iter->i - 1))
|
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
static struct drgn_error *
|
2019-11-28 03:27:14 +00:00
|
|
|
c_format_array_object(const struct drgn_object *obj,
|
|
|
|
struct drgn_type *underlying_type, size_t indent,
|
|
|
|
size_t one_line_columns, size_t multi_line_columns,
|
2019-12-12 22:30:04 +00:00
|
|
|
enum drgn_format_object_flags flags,
|
2019-11-28 03:27:14 +00:00
|
|
|
struct string_builder *sb)
|
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-12-06 23:25:39 +00:00
|
|
|
struct array_initializer_iter iter = {
|
|
|
|
.iter = {
|
|
|
|
.next = array_initializer_iter_next,
|
|
|
|
.reset = array_initializer_iter_reset,
|
2019-12-10 00:35:33 +00:00
|
|
|
.append_designation =
|
|
|
|
flags & DRGN_FORMAT_OBJECT_ELEMENT_INDICES ?
|
|
|
|
array_initializer_append_designation : NULL,
|
2019-12-06 23:25:39 +00:00
|
|
|
},
|
|
|
|
.obj = obj,
|
|
|
|
.element_type = drgn_type_type(underlying_type),
|
|
|
|
.length = drgn_type_length(underlying_type),
|
2019-12-10 00:35:33 +00:00
|
|
|
.flags = flags,
|
2019-12-06 23:25:39 +00:00
|
|
|
.element_flags = drgn_element_format_object_flags(flags),
|
|
|
|
};
|
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-12-06 23:25:39 +00:00
|
|
|
if ((flags & DRGN_FORMAT_OBJECT_STRING) && iter.length &&
|
|
|
|
is_character_type(iter.element_type.type)) {
|
2020-12-04 21:20:09 +00:00
|
|
|
SWITCH_ENUM(obj->kind,
|
|
|
|
case DRGN_OBJECT_VALUE: {
|
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
|
|
|
const unsigned char *buf;
|
2019-12-06 23:25:39 +00:00
|
|
|
uint64_t size, i;
|
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-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, '"'))
|
|
|
|
return &drgn_enomem;
|
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
|
|
|
buf = (const unsigned char *)drgn_object_buffer(obj);
|
2020-12-11 19:18:54 +00:00
|
|
|
size = drgn_object_size(obj);
|
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 < size; i++) {
|
|
|
|
if (buf[i] == '\0')
|
|
|
|
break;
|
2019-12-06 19:17:43 +00:00
|
|
|
err = c_format_character(buf[i], false, true,
|
|
|
|
sb);
|
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;
|
|
|
|
}
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, '"'))
|
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
}
|
2020-12-04 21:20:09 +00:00
|
|
|
case DRGN_OBJECT_REFERENCE:
|
2021-06-04 01:43:27 +01:00
|
|
|
return c_format_string(drgn_object_program(obj),
|
2020-12-14 10:46:42 +00:00
|
|
|
obj->address, iter.length, sb);
|
2020-12-29 22:41:01 +00:00
|
|
|
case DRGN_OBJECT_ABSENT:
|
2020-12-04 21:20:09 +00: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-12-06 23:25:39 +00:00
|
|
|
err = drgn_type_bit_size(iter.element_type.type,
|
|
|
|
&iter.element_bit_size);
|
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;
|
|
|
|
|
2019-12-10 00:35:33 +00:00
|
|
|
/*
|
2019-12-10 09:48:06 +00:00
|
|
|
* If we don't want zero elements, ignore any at the end. If we're
|
|
|
|
* including indices, then we'll skip past zeroes as we iterate, so we
|
2019-12-10 00:35:33 +00:00
|
|
|
* don't need to do this.
|
|
|
|
*/
|
2019-12-10 09:48:06 +00:00
|
|
|
if (!(flags & (DRGN_FORMAT_OBJECT_ELEMENT_INDICES |
|
|
|
|
DRGN_FORMAT_OBJECT_IMPLICIT_ELEMENTS)) &&
|
2019-12-10 00:35:33 +00:00
|
|
|
iter.length) {
|
2019-12-06 23:25:39 +00:00
|
|
|
struct drgn_object element;
|
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
|
|
|
|
2020-08-27 19:26:39 +01:00
|
|
|
drgn_object_init(&element, drgn_object_program(obj));
|
2019-12-06 23:25:39 +00:00
|
|
|
do {
|
|
|
|
bool zero;
|
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-12-06 23:25:39 +00:00
|
|
|
err = drgn_object_slice(&element, obj,
|
|
|
|
iter.element_type,
|
|
|
|
(iter.length - 1) *
|
|
|
|
iter.element_bit_size,
|
|
|
|
0);
|
|
|
|
if (err)
|
2019-12-07 02:02:57 +00:00
|
|
|
break;
|
|
|
|
|
2019-12-06 23:25:39 +00:00
|
|
|
err = drgn_object_is_zero(&element, &zero);
|
|
|
|
if (err)
|
|
|
|
break;
|
|
|
|
if (zero)
|
|
|
|
iter.length--;
|
2019-12-07 02:02:57 +00:00
|
|
|
else
|
2019-12-06 23:25:39 +00:00
|
|
|
break;
|
|
|
|
} while (iter.length);
|
|
|
|
drgn_object_deinit(&element);
|
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-12-06 23:25:39 +00:00
|
|
|
return err;
|
2019-05-14 18:07:50 +01:00
|
|
|
}
|
2020-08-27 19:26:39 +01:00
|
|
|
return c_format_initializer(drgn_object_program(obj), &iter.iter,
|
|
|
|
indent, one_line_columns,
|
|
|
|
multi_line_columns,
|
2019-12-09 20:52:05 +00:00
|
|
|
flags & DRGN_FORMAT_OBJECT_ELEMENTS_SAME_LINE,
|
2019-12-09 20:44:25 +00:00
|
|
|
sb);
|
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-11-28 03:27:14 +00:00
|
|
|
c_format_function_object(const struct drgn_object *obj,
|
|
|
|
struct string_builder *sb)
|
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
|
|
|
{
|
2020-12-04 21:27:01 +00:00
|
|
|
assert(obj->kind == DRGN_OBJECT_REFERENCE);
|
2020-12-14 10:46:42 +00:00
|
|
|
if (!string_builder_appendf(sb, "0x%" PRIx64, obj->address))
|
2019-05-14 18:07:50 +01:00
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2019-12-06 19:40:13 +00:00
|
|
|
c_format_object_impl(const struct drgn_object *obj, size_t indent,
|
2019-12-06 18:24:24 +00:00
|
|
|
size_t one_line_columns, size_t multi_line_columns,
|
|
|
|
enum drgn_format_object_flags flags,
|
|
|
|
struct string_builder *sb)
|
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_type *underlying_type = drgn_underlying_type(obj->type);
|
|
|
|
|
2020-12-04 21:27:01 +00:00
|
|
|
if (drgn_type_kind(underlying_type) == DRGN_TYPE_VOID) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_TYPE,
|
|
|
|
"cannot format void object");
|
|
|
|
}
|
|
|
|
|
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
|
|
|
/*
|
|
|
|
* Pointers are special because they can have an asterisk prefix if
|
|
|
|
* we're dereferencing them.
|
|
|
|
*/
|
2020-12-04 21:27:01 +00:00
|
|
|
if (drgn_type_kind(underlying_type) == DRGN_TYPE_POINTER &&
|
2020-12-29 22:41:01 +00:00
|
|
|
obj->kind != DRGN_OBJECT_ABSENT) {
|
2019-12-06 19:40:13 +00:00
|
|
|
return c_format_pointer_object(obj, underlying_type, indent,
|
|
|
|
one_line_columns,
|
2019-12-06 18:24:24 +00:00
|
|
|
multi_line_columns, flags, sb);
|
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-12-06 19:40:13 +00:00
|
|
|
if (flags & DRGN_FORMAT_OBJECT_TYPE_NAME) {
|
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
|
|
|
size_t old_len = sb->len;
|
|
|
|
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, '('))
|
|
|
|
return &drgn_enomem;
|
2019-11-28 03:27:14 +00:00
|
|
|
err = c_format_type_name_impl(drgn_object_qualified_type(obj),
|
|
|
|
sb);
|
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;
|
2019-05-14 18:07:50 +01:00
|
|
|
if (!string_builder_appendc(sb, ')'))
|
|
|
|
return &drgn_enomem;
|
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 (__builtin_sub_overflow(one_line_columns, sb->len - old_len,
|
|
|
|
&one_line_columns))
|
|
|
|
one_line_columns = 0;
|
|
|
|
}
|
|
|
|
|
2020-12-29 22:41:01 +00:00
|
|
|
if (obj->kind == DRGN_OBJECT_ABSENT) {
|
|
|
|
if (!string_builder_append(sb, "<absent>"))
|
2020-12-04 21:27:01 +00:00
|
|
|
return &drgn_enomem;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-12-04 19:20:00 +00:00
|
|
|
SWITCH_ENUM(drgn_type_kind(underlying_type),
|
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
|
|
|
case DRGN_TYPE_INT:
|
|
|
|
case DRGN_TYPE_BOOL:
|
2019-12-06 19:17:43 +00:00
|
|
|
return c_format_int_object(obj, flags, sb);
|
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
|
|
|
case DRGN_TYPE_FLOAT:
|
2019-11-28 03:27:14 +00:00
|
|
|
return c_format_float_object(obj, sb);
|
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
|
|
|
case DRGN_TYPE_STRUCT:
|
|
|
|
case DRGN_TYPE_UNION:
|
2019-11-15 01:12:47 +00:00
|
|
|
case DRGN_TYPE_CLASS:
|
2019-11-28 03:27:14 +00:00
|
|
|
return c_format_compound_object(obj, underlying_type, indent,
|
2019-12-09 20:52:05 +00:00
|
|
|
one_line_columns,
|
2019-12-12 22:30:04 +00:00
|
|
|
multi_line_columns, flags, sb);
|
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
|
|
|
case DRGN_TYPE_ENUM:
|
2019-11-28 03:27:14 +00:00
|
|
|
return c_format_enum_object(obj, underlying_type, sb);
|
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
|
|
|
case DRGN_TYPE_ARRAY:
|
2019-11-28 03:27:14 +00:00
|
|
|
return c_format_array_object(obj, underlying_type, indent,
|
|
|
|
one_line_columns,
|
2019-12-12 22:30:04 +00:00
|
|
|
multi_line_columns, flags, sb);
|
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
|
|
|
case DRGN_TYPE_FUNCTION:
|
2019-11-28 03:27:14 +00:00
|
|
|
return c_format_function_object(obj, sb);
|
2020-12-04 21:27:01 +00:00
|
|
|
case DRGN_TYPE_VOID:
|
2020-12-04 19:20:00 +00:00
|
|
|
case DRGN_TYPE_TYPEDEF:
|
|
|
|
case DRGN_TYPE_POINTER:
|
|
|
|
)
|
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
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_format_object(const struct drgn_object *obj,
|
|
|
|
size_t columns,
|
|
|
|
enum drgn_format_object_flags flags,
|
|
|
|
char **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;
|
2022-10-05 22:41:12 +01:00
|
|
|
struct string_builder sb = STRING_BUILDER_INIT;
|
2019-12-06 19:40:13 +00:00
|
|
|
err = c_format_object_impl(obj, 0, columns, max(columns, (size_t)1),
|
|
|
|
flags, &sb);
|
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) {
|
|
|
|
free(sb.str);
|
|
|
|
return err;
|
|
|
|
}
|
2022-09-21 18:43:31 +01:00
|
|
|
if (!(*ret = string_builder_null_terminate(&sb)))
|
2019-05-14 18:07:50 +01:00
|
|
|
return &drgn_enomem;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
/* This obviously incomplete since we only handle the tokens we care about. */
|
|
|
|
enum {
|
|
|
|
C_TOKEN_EOF = -1,
|
|
|
|
MIN_KEYWORD_TOKEN,
|
|
|
|
MIN_SPECIFIER_TOKEN = MIN_KEYWORD_TOKEN,
|
|
|
|
C_TOKEN_VOID = MIN_SPECIFIER_TOKEN,
|
|
|
|
C_TOKEN_CHAR,
|
|
|
|
C_TOKEN_SHORT,
|
|
|
|
C_TOKEN_INT,
|
|
|
|
C_TOKEN_LONG,
|
|
|
|
C_TOKEN_SIGNED,
|
|
|
|
C_TOKEN_UNSIGNED,
|
|
|
|
C_TOKEN_BOOL,
|
|
|
|
C_TOKEN_FLOAT,
|
|
|
|
C_TOKEN_DOUBLE,
|
|
|
|
C_TOKEN_COMPLEX,
|
|
|
|
MAX_SPECIFIER_TOKEN = C_TOKEN_COMPLEX,
|
|
|
|
MIN_QUALIFIER_TOKEN,
|
|
|
|
C_TOKEN_CONST = MIN_QUALIFIER_TOKEN,
|
|
|
|
C_TOKEN_RESTRICT,
|
|
|
|
C_TOKEN_VOLATILE,
|
|
|
|
C_TOKEN_ATOMIC,
|
|
|
|
MAX_QUALIFIER_TOKEN = C_TOKEN_ATOMIC,
|
|
|
|
C_TOKEN_STRUCT,
|
|
|
|
C_TOKEN_UNION,
|
2022-02-18 06:18:53 +00:00
|
|
|
C_TOKEN_CLASS,
|
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
|
|
|
C_TOKEN_ENUM,
|
|
|
|
MAX_KEYWORD_TOKEN = C_TOKEN_ENUM,
|
|
|
|
C_TOKEN_LPAREN,
|
|
|
|
C_TOKEN_RPAREN,
|
|
|
|
C_TOKEN_LBRACKET,
|
|
|
|
C_TOKEN_RBRACKET,
|
|
|
|
C_TOKEN_ASTERISK,
|
|
|
|
C_TOKEN_DOT,
|
|
|
|
C_TOKEN_NUMBER,
|
|
|
|
C_TOKEN_IDENTIFIER,
|
2022-11-30 01:19:32 +00:00
|
|
|
C_TOKEN_TEMPLATE_ARGUMENTS,
|
2022-12-01 00:52:49 +00:00
|
|
|
C_TOKEN_COLON,
|
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
|
|
|
};
|
|
|
|
|
2022-02-05 01:17:31 +00:00
|
|
|
#include "c_keywords.inc"
|
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
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
struct drgn_c_family_lexer {
|
|
|
|
struct drgn_lexer lexer;
|
|
|
|
bool cpp;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct drgn_error *drgn_c_family_lexer_func(struct drgn_lexer *lexer,
|
|
|
|
struct drgn_token *token) {
|
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
|
|
|
const char *p = lexer->p;
|
2022-02-18 06:18:53 +00:00
|
|
|
bool cpp = ((struct drgn_c_family_lexer *)lexer)->cpp;
|
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
|
|
|
|
|
|
|
while (isspace(*p))
|
|
|
|
p++;
|
|
|
|
|
|
|
|
token->value = p;
|
|
|
|
switch (*p) {
|
|
|
|
case '\0':
|
|
|
|
token->kind = C_TOKEN_EOF;
|
|
|
|
break;
|
|
|
|
case '(':
|
|
|
|
token->kind = C_TOKEN_LPAREN;
|
|
|
|
p++;
|
|
|
|
break;
|
|
|
|
case ')':
|
|
|
|
token->kind = C_TOKEN_RPAREN;
|
|
|
|
p++;
|
|
|
|
break;
|
|
|
|
case '[':
|
|
|
|
token->kind = C_TOKEN_LBRACKET;
|
|
|
|
p++;
|
|
|
|
break;
|
|
|
|
case ']':
|
|
|
|
token->kind = C_TOKEN_RBRACKET;
|
|
|
|
p++;
|
|
|
|
break;
|
|
|
|
case '*':
|
|
|
|
token->kind = C_TOKEN_ASTERISK;
|
|
|
|
p++;
|
|
|
|
break;
|
|
|
|
case '.':
|
|
|
|
token->kind = C_TOKEN_DOT;
|
|
|
|
p++;
|
|
|
|
break;
|
2022-12-01 00:52:49 +00:00
|
|
|
case ':':
|
|
|
|
token->kind = C_TOKEN_COLON;
|
|
|
|
p++;
|
|
|
|
break;
|
2022-11-30 01:19:32 +00:00
|
|
|
case '<':
|
2022-12-01 00:52:49 +00:00
|
|
|
// This is a hack for cpp_append_to_identifier(). We don't want
|
2022-11-30 01:19:32 +00:00
|
|
|
// to deal with actually parsing template arguments, and we
|
|
|
|
// don't care about "<" otherwise, so this scans a token from
|
|
|
|
// the "<" to its matching ">".
|
|
|
|
if (cpp) {
|
|
|
|
token->kind = C_TOKEN_TEMPLATE_ARGUMENTS;
|
|
|
|
p++;
|
|
|
|
size_t less_thans = 1;
|
|
|
|
bool in_single_quotes = false;
|
|
|
|
do {
|
|
|
|
switch (*p++) {
|
|
|
|
case '<':
|
|
|
|
if (!in_single_quotes)
|
|
|
|
less_thans++;
|
|
|
|
break;
|
|
|
|
case '>':
|
|
|
|
if (!in_single_quotes)
|
|
|
|
less_thans--;
|
|
|
|
break;
|
|
|
|
case '\'':
|
|
|
|
// Handling the edge-case of an escaped single-quote
|
|
|
|
if (!(in_single_quotes && *(p - 2) == '\\'))
|
|
|
|
in_single_quotes = !in_single_quotes;
|
|
|
|
break;
|
|
|
|
case '\0':
|
|
|
|
return drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"invalid template arguments");
|
|
|
|
}
|
|
|
|
} while (less_thans > 0);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
fallthrough;
|
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
|
|
|
default:
|
|
|
|
if (isalpha(*p) || *p == '_') {
|
|
|
|
do {
|
|
|
|
p++;
|
|
|
|
} while (isalnum(*p) || *p == '_');
|
2022-02-05 01:17:31 +00:00
|
|
|
token->kind = identifier_token_kind(token->value,
|
2022-02-18 06:18:53 +00:00
|
|
|
p - token->value,
|
|
|
|
cpp);
|
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
|
|
|
} else if ('0' <= *p && *p <= '9') {
|
|
|
|
token->kind = C_TOKEN_NUMBER;
|
|
|
|
if (*p++ == '0' && *p == 'x') {
|
|
|
|
p++;
|
|
|
|
while (('0' <= *p && *p <= '9') ||
|
|
|
|
('a' <= *p && *p <= 'f') ||
|
|
|
|
('A' <= *p && *p <= 'F')) {
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (p - token->value <= 2) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"invalid number");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
while ('0' <= *p && *p <= '9')
|
|
|
|
p++;
|
|
|
|
}
|
|
|
|
if (isalpha(*p) || *p == '_') {
|
|
|
|
return drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"invalid number");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return drgn_error_format(DRGN_ERROR_SYNTAX,
|
|
|
|
"invalid character \\x%02x", (unsigned char)*p);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
token->len = p - token->value;
|
|
|
|
lexer->p = p;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *c_token_to_u64(const struct drgn_token *token,
|
|
|
|
uint64_t *ret)
|
|
|
|
{
|
|
|
|
uint64_t x = 0;
|
|
|
|
size_t i;
|
|
|
|
|
|
|
|
assert(token->kind == C_TOKEN_NUMBER);
|
|
|
|
if (token->len > 2 && token->value[0] == '0' &&
|
|
|
|
token->value[1] == 'x') {
|
|
|
|
for (i = 2; i < token->len; i++) {
|
|
|
|
char c = token->value[i];
|
|
|
|
int digit;
|
|
|
|
|
|
|
|
if ('0' <= c && c <= '9')
|
|
|
|
digit = c - '0';
|
|
|
|
else if ('a' <= c && c <= 'f')
|
|
|
|
digit = c - 'a';
|
|
|
|
else /* ('A' <= c && c <= 'F') */
|
|
|
|
digit = c - 'A';
|
|
|
|
if (x > UINT64_MAX / 16)
|
|
|
|
goto overflow;
|
|
|
|
x *= 16;
|
|
|
|
if (x > UINT64_MAX - digit)
|
|
|
|
goto overflow;
|
|
|
|
x += digit;
|
|
|
|
}
|
|
|
|
} else if (token->value[0] == '0') {
|
|
|
|
for (i = 1; i < token->len; i++) {
|
|
|
|
int digit;
|
|
|
|
|
|
|
|
digit = token->value[i] - '0';
|
|
|
|
if (x > UINT64_MAX / 8)
|
|
|
|
goto overflow;
|
|
|
|
x *= 8;
|
|
|
|
if (x > UINT64_MAX - digit)
|
|
|
|
goto overflow;
|
|
|
|
x += digit;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
for (i = 0; i < token->len; i++) {
|
|
|
|
int digit;
|
|
|
|
|
|
|
|
digit = token->value[i] - '0';
|
|
|
|
if (x > UINT64_MAX / 10)
|
|
|
|
goto overflow;
|
|
|
|
x *= 10;
|
|
|
|
if (x > UINT64_MAX - digit)
|
|
|
|
goto overflow;
|
|
|
|
x += digit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*ret = x;
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
overflow:
|
|
|
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
|
|
|
"number is too large");
|
|
|
|
}
|
|
|
|
|
|
|
|
enum c_type_specifier {
|
|
|
|
SPECIFIER_ERROR,
|
|
|
|
SPECIFIER_VOID,
|
|
|
|
SPECIFIER_CHAR,
|
|
|
|
SPECIFIER_SIGNED_CHAR,
|
|
|
|
SPECIFIER_UNSIGNED_CHAR,
|
|
|
|
SPECIFIER_SHORT,
|
|
|
|
SPECIFIER_SHORT_INT,
|
|
|
|
SPECIFIER_SIGNED_SHORT_INT,
|
|
|
|
SPECIFIER_UNSIGNED_SHORT_INT,
|
|
|
|
SPECIFIER_SIGNED_SHORT,
|
|
|
|
SPECIFIER_UNSIGNED_SHORT,
|
|
|
|
SPECIFIER_INT,
|
|
|
|
SPECIFIER_SIGNED_INT,
|
|
|
|
SPECIFIER_UNSIGNED_INT,
|
|
|
|
SPECIFIER_LONG,
|
|
|
|
SPECIFIER_LONG_INT,
|
|
|
|
SPECIFIER_SIGNED_LONG,
|
|
|
|
SPECIFIER_UNSIGNED_LONG,
|
|
|
|
SPECIFIER_SIGNED_LONG_INT,
|
|
|
|
SPECIFIER_UNSIGNED_LONG_INT,
|
|
|
|
SPECIFIER_LONG_LONG,
|
|
|
|
SPECIFIER_LONG_LONG_INT,
|
|
|
|
SPECIFIER_SIGNED_LONG_LONG_INT,
|
|
|
|
SPECIFIER_UNSIGNED_LONG_LONG_INT,
|
|
|
|
SPECIFIER_SIGNED_LONG_LONG,
|
|
|
|
SPECIFIER_UNSIGNED_LONG_LONG,
|
|
|
|
SPECIFIER_SIGNED,
|
|
|
|
SPECIFIER_UNSIGNED,
|
|
|
|
SPECIFIER_BOOL,
|
|
|
|
SPECIFIER_FLOAT,
|
|
|
|
SPECIFIER_DOUBLE,
|
|
|
|
SPECIFIER_LONG_DOUBLE,
|
|
|
|
SPECIFIER_NONE,
|
|
|
|
NUM_SPECIFIER_STATES,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *specifier_spelling[NUM_SPECIFIER_STATES] = {
|
|
|
|
[SPECIFIER_VOID] = "void",
|
|
|
|
[SPECIFIER_CHAR] = "char",
|
|
|
|
[SPECIFIER_SIGNED_CHAR] = "signed char",
|
|
|
|
[SPECIFIER_UNSIGNED_CHAR] = "unsigned char",
|
|
|
|
[SPECIFIER_SHORT] = "short",
|
|
|
|
[SPECIFIER_SHORT_INT] = "short int",
|
|
|
|
[SPECIFIER_SIGNED_SHORT_INT] = "signed short int",
|
|
|
|
[SPECIFIER_UNSIGNED_SHORT_INT] = "unsigned short int",
|
|
|
|
[SPECIFIER_SIGNED_SHORT] = "signed short",
|
|
|
|
[SPECIFIER_UNSIGNED_SHORT] = "unsigned short",
|
|
|
|
[SPECIFIER_INT] = "int",
|
|
|
|
[SPECIFIER_SIGNED_INT] = "signed int",
|
|
|
|
[SPECIFIER_UNSIGNED_INT] = "unsigned int",
|
|
|
|
[SPECIFIER_LONG] = "long",
|
|
|
|
[SPECIFIER_LONG_INT] = "long int",
|
|
|
|
[SPECIFIER_SIGNED_LONG] = "signed long",
|
|
|
|
[SPECIFIER_UNSIGNED_LONG] = "unsigned long",
|
|
|
|
[SPECIFIER_SIGNED_LONG_INT] = "signed long int",
|
|
|
|
[SPECIFIER_UNSIGNED_LONG_INT] = "unsigned long int",
|
|
|
|
[SPECIFIER_LONG_LONG] = "long long",
|
|
|
|
[SPECIFIER_LONG_LONG_INT] = "long long int",
|
|
|
|
[SPECIFIER_SIGNED_LONG_LONG_INT] = "signed long long int",
|
|
|
|
[SPECIFIER_UNSIGNED_LONG_LONG_INT] = "unsigned long long int",
|
|
|
|
[SPECIFIER_SIGNED_LONG_LONG] = "signed long long",
|
|
|
|
[SPECIFIER_UNSIGNED_LONG_LONG] = "unsigned long long",
|
|
|
|
[SPECIFIER_SIGNED] = "signed",
|
|
|
|
[SPECIFIER_UNSIGNED] = "unsigned",
|
|
|
|
[SPECIFIER_BOOL] = "_Bool",
|
|
|
|
[SPECIFIER_FLOAT] = "float",
|
|
|
|
[SPECIFIER_DOUBLE] = "double",
|
|
|
|
[SPECIFIER_LONG_DOUBLE] = "long double",
|
|
|
|
};
|
|
|
|
|
|
|
|
static const enum drgn_qualifiers qualifier_from_token[MAX_QUALIFIER_TOKEN + 1] = {
|
|
|
|
[C_TOKEN_CONST] = DRGN_QUALIFIER_CONST,
|
|
|
|
[C_TOKEN_RESTRICT] = DRGN_QUALIFIER_RESTRICT,
|
|
|
|
[C_TOKEN_VOLATILE] = DRGN_QUALIFIER_VOLATILE,
|
|
|
|
[C_TOKEN_ATOMIC] = DRGN_QUALIFIER_ATOMIC,
|
|
|
|
};
|
|
|
|
|
2019-04-20 00:05:19 +01:00
|
|
|
static const enum c_type_specifier
|
|
|
|
specifier_transition[NUM_SPECIFIER_STATES][MAX_SPECIFIER_TOKEN + 1] = {
|
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
|
|
|
[SPECIFIER_NONE] = {
|
|
|
|
[C_TOKEN_VOID] = SPECIFIER_VOID,
|
|
|
|
[C_TOKEN_CHAR] = SPECIFIER_CHAR,
|
|
|
|
[C_TOKEN_SHORT] = SPECIFIER_SHORT,
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_INT,
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_LONG,
|
|
|
|
[C_TOKEN_SIGNED] = SPECIFIER_SIGNED,
|
|
|
|
[C_TOKEN_UNSIGNED] = SPECIFIER_UNSIGNED,
|
|
|
|
[C_TOKEN_BOOL] = SPECIFIER_BOOL,
|
|
|
|
[C_TOKEN_FLOAT] = SPECIFIER_FLOAT,
|
|
|
|
[C_TOKEN_DOUBLE] = SPECIFIER_DOUBLE,
|
|
|
|
},
|
|
|
|
[SPECIFIER_VOID] = {},
|
|
|
|
[SPECIFIER_CHAR] = {
|
|
|
|
[C_TOKEN_SIGNED] = SPECIFIER_SIGNED_CHAR,
|
|
|
|
[C_TOKEN_UNSIGNED] = SPECIFIER_UNSIGNED_CHAR,
|
|
|
|
},
|
|
|
|
[SPECIFIER_SIGNED_CHAR] = {},
|
|
|
|
[SPECIFIER_UNSIGNED_CHAR] = {},
|
|
|
|
[SPECIFIER_SHORT] = {
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_SHORT_INT,
|
|
|
|
[C_TOKEN_SIGNED] = SPECIFIER_SIGNED_SHORT,
|
|
|
|
[C_TOKEN_UNSIGNED] = SPECIFIER_UNSIGNED_SHORT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_SHORT_INT] = {
|
|
|
|
[C_TOKEN_SIGNED] = SPECIFIER_SIGNED_SHORT_INT,
|
|
|
|
[C_TOKEN_UNSIGNED] = SPECIFIER_UNSIGNED_SHORT_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_SIGNED_SHORT_INT] = {},
|
|
|
|
[SPECIFIER_UNSIGNED_SHORT_INT] = {},
|
|
|
|
[SPECIFIER_SIGNED_SHORT] = {
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_SIGNED_SHORT_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_UNSIGNED_SHORT] = {
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_UNSIGNED_SHORT_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_INT] = {
|
|
|
|
[C_TOKEN_SHORT] = SPECIFIER_SHORT_INT,
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_LONG_INT,
|
|
|
|
[C_TOKEN_SIGNED] = SPECIFIER_SIGNED_INT,
|
|
|
|
[C_TOKEN_UNSIGNED] = SPECIFIER_UNSIGNED_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_SIGNED_INT] = {
|
|
|
|
[C_TOKEN_SHORT] = SPECIFIER_SIGNED_SHORT_INT,
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_SIGNED_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_UNSIGNED_INT] = {
|
|
|
|
[C_TOKEN_SHORT] = SPECIFIER_UNSIGNED_SHORT_INT,
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_UNSIGNED_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_LONG] = {
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_LONG_INT,
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_LONG_LONG,
|
|
|
|
[C_TOKEN_SIGNED] = SPECIFIER_SIGNED_LONG,
|
|
|
|
[C_TOKEN_UNSIGNED] = SPECIFIER_UNSIGNED_LONG,
|
|
|
|
[C_TOKEN_DOUBLE] = SPECIFIER_LONG_DOUBLE,
|
|
|
|
},
|
|
|
|
[SPECIFIER_LONG_INT] = {
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_LONG_LONG_INT,
|
|
|
|
[C_TOKEN_SIGNED] = SPECIFIER_SIGNED_LONG_INT,
|
|
|
|
[C_TOKEN_UNSIGNED] = SPECIFIER_UNSIGNED_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_SIGNED_LONG] = {
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_SIGNED_LONG_LONG,
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_SIGNED_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_UNSIGNED_LONG] = {
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_UNSIGNED_LONG_LONG,
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_UNSIGNED_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_SIGNED_LONG_INT] = {
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_SIGNED_LONG_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_UNSIGNED_LONG_INT] = {
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_UNSIGNED_LONG_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_LONG_LONG] = {
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_LONG_LONG_INT,
|
|
|
|
[C_TOKEN_SIGNED] = SPECIFIER_SIGNED_LONG_LONG,
|
|
|
|
[C_TOKEN_UNSIGNED] = SPECIFIER_UNSIGNED_LONG_LONG,
|
|
|
|
},
|
|
|
|
[SPECIFIER_LONG_LONG_INT] = {
|
|
|
|
[C_TOKEN_SIGNED] = SPECIFIER_SIGNED_LONG_LONG_INT,
|
|
|
|
[C_TOKEN_UNSIGNED] = SPECIFIER_UNSIGNED_LONG_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_SIGNED_LONG_LONG_INT] = {},
|
|
|
|
[SPECIFIER_UNSIGNED_LONG_LONG_INT] = {},
|
|
|
|
[SPECIFIER_SIGNED_LONG_LONG] = {
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_SIGNED_LONG_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_UNSIGNED_LONG_LONG] = {
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_UNSIGNED_LONG_LONG_INT,
|
|
|
|
},
|
|
|
|
[SPECIFIER_SIGNED] = {
|
|
|
|
[C_TOKEN_CHAR] = SPECIFIER_SIGNED_CHAR,
|
|
|
|
[C_TOKEN_SHORT] = SPECIFIER_SIGNED_SHORT,
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_SIGNED_INT,
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_SIGNED_LONG,
|
|
|
|
},
|
|
|
|
[SPECIFIER_UNSIGNED] = {
|
|
|
|
[C_TOKEN_CHAR] = SPECIFIER_UNSIGNED_CHAR,
|
|
|
|
[C_TOKEN_SHORT] = SPECIFIER_UNSIGNED_SHORT,
|
|
|
|
[C_TOKEN_INT] = SPECIFIER_UNSIGNED_INT,
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_UNSIGNED_LONG,
|
|
|
|
},
|
|
|
|
[SPECIFIER_BOOL] = {},
|
|
|
|
[SPECIFIER_FLOAT] = {},
|
|
|
|
[SPECIFIER_DOUBLE] = {
|
|
|
|
[C_TOKEN_LONG] = SPECIFIER_LONG_DOUBLE,
|
|
|
|
},
|
|
|
|
[SPECIFIER_LONG_DOUBLE] = {},
|
|
|
|
};
|
|
|
|
|
2019-04-20 00:05:19 +01:00
|
|
|
static const enum drgn_primitive_type specifier_kind[NUM_SPECIFIER_STATES] = {
|
|
|
|
[SPECIFIER_VOID] = DRGN_C_TYPE_VOID,
|
|
|
|
[SPECIFIER_CHAR] = DRGN_C_TYPE_CHAR,
|
|
|
|
[SPECIFIER_SIGNED_CHAR] = DRGN_C_TYPE_SIGNED_CHAR,
|
|
|
|
[SPECIFIER_UNSIGNED_CHAR] = DRGN_C_TYPE_UNSIGNED_CHAR,
|
|
|
|
[SPECIFIER_SHORT] = DRGN_C_TYPE_SHORT,
|
|
|
|
[SPECIFIER_SHORT_INT] = DRGN_C_TYPE_SHORT,
|
|
|
|
[SPECIFIER_SIGNED_SHORT_INT] = DRGN_C_TYPE_SHORT,
|
|
|
|
[SPECIFIER_UNSIGNED_SHORT_INT] = DRGN_C_TYPE_UNSIGNED_SHORT,
|
|
|
|
[SPECIFIER_SIGNED_SHORT] = DRGN_C_TYPE_SHORT,
|
|
|
|
[SPECIFIER_UNSIGNED_SHORT] = DRGN_C_TYPE_UNSIGNED_SHORT,
|
|
|
|
[SPECIFIER_INT] = DRGN_C_TYPE_INT,
|
|
|
|
[SPECIFIER_SIGNED_INT] = DRGN_C_TYPE_INT,
|
|
|
|
[SPECIFIER_UNSIGNED_INT] = DRGN_C_TYPE_UNSIGNED_INT,
|
|
|
|
[SPECIFIER_LONG] = DRGN_C_TYPE_LONG,
|
|
|
|
[SPECIFIER_LONG_INT] = DRGN_C_TYPE_LONG,
|
|
|
|
[SPECIFIER_SIGNED_LONG] = DRGN_C_TYPE_LONG,
|
|
|
|
[SPECIFIER_UNSIGNED_LONG] = DRGN_C_TYPE_UNSIGNED_LONG,
|
|
|
|
[SPECIFIER_SIGNED_LONG_INT] = DRGN_C_TYPE_LONG,
|
|
|
|
[SPECIFIER_UNSIGNED_LONG_INT] = DRGN_C_TYPE_UNSIGNED_LONG,
|
|
|
|
[SPECIFIER_LONG_LONG] = DRGN_C_TYPE_LONG_LONG,
|
|
|
|
[SPECIFIER_LONG_LONG_INT] = DRGN_C_TYPE_LONG_LONG,
|
|
|
|
[SPECIFIER_SIGNED_LONG_LONG_INT] = DRGN_C_TYPE_LONG_LONG,
|
|
|
|
[SPECIFIER_UNSIGNED_LONG_LONG_INT] = DRGN_C_TYPE_UNSIGNED_LONG_LONG,
|
|
|
|
[SPECIFIER_SIGNED_LONG_LONG] = DRGN_C_TYPE_LONG_LONG,
|
|
|
|
[SPECIFIER_UNSIGNED_LONG_LONG] = DRGN_C_TYPE_UNSIGNED_LONG_LONG,
|
|
|
|
[SPECIFIER_SIGNED] = DRGN_C_TYPE_INT,
|
|
|
|
[SPECIFIER_UNSIGNED] = DRGN_C_TYPE_UNSIGNED_INT,
|
|
|
|
[SPECIFIER_BOOL] = DRGN_C_TYPE_BOOL,
|
|
|
|
[SPECIFIER_FLOAT] = DRGN_C_TYPE_FLOAT,
|
|
|
|
[SPECIFIER_DOUBLE] = DRGN_C_TYPE_DOUBLE,
|
|
|
|
[SPECIFIER_LONG_DOUBLE] = DRGN_C_TYPE_LONG_DOUBLE,
|
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-04-20 00:05:19 +01:00
|
|
|
enum drgn_primitive_type c_parse_specifier_list(const char *s)
|
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;
|
2022-02-18 06:18:53 +00:00
|
|
|
struct drgn_c_family_lexer c_family_lexer;
|
|
|
|
struct drgn_lexer *lexer = &c_family_lexer.lexer;
|
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
|
|
|
enum c_type_specifier specifier = SPECIFIER_NONE;
|
2019-04-20 00:05:19 +01:00
|
|
|
enum drgn_primitive_type primitive = DRGN_NOT_PRIMITIVE_TYPE;
|
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
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
c_family_lexer.cpp = false;
|
|
|
|
drgn_lexer_init(lexer, drgn_c_family_lexer_func, s);
|
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 (;;) {
|
|
|
|
struct drgn_token token;
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
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) {
|
|
|
|
drgn_error_destroy(err);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (MIN_SPECIFIER_TOKEN <= token.kind &&
|
|
|
|
token.kind <= MAX_SPECIFIER_TOKEN)
|
|
|
|
specifier = specifier_transition[specifier][token.kind];
|
|
|
|
else if (token.kind == C_TOKEN_EOF)
|
|
|
|
break;
|
|
|
|
else
|
|
|
|
specifier = SPECIFIER_ERROR;
|
|
|
|
if (specifier == SPECIFIER_ERROR)
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2019-04-20 00:05:19 +01:00
|
|
|
primitive = specifier_kind[specifier];
|
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
|
|
|
out:
|
2022-02-18 06:18:53 +00:00
|
|
|
drgn_lexer_deinit(lexer);
|
2019-04-20 00:05:19 +01:00
|
|
|
return primitive;
|
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
|
|
|
}
|
|
|
|
|
2022-12-01 00:52:49 +00:00
|
|
|
|
2022-11-30 01:19:32 +00:00
|
|
|
// The DWARF index currently includes template arguments in indexed names. So,
|
|
|
|
// to be able to find a type with template arguments, we have to look it up with
|
|
|
|
// the template arguments included. This looks for a C_TOKEN_TEMPLATE_ARGUMENTS
|
|
|
|
// token after the identifier and returns the length from the beginning of the
|
|
|
|
// identifier to the end of the template arguments.
|
|
|
|
//
|
|
|
|
// Note that this requires that the user formats the template arguments exactly
|
|
|
|
// as they appear in DWARF (which can vary between compilers). In the future, it
|
|
|
|
// might be better to properly parse and either normalize the template arguments
|
|
|
|
// or look them up as an AST somehow.
|
2022-12-01 00:52:49 +00:00
|
|
|
static struct drgn_error *cpp_append_to_identifier(
|
|
|
|
struct drgn_lexer *lexer, const char *identifier, size_t *len_ret)
|
2022-11-30 01:19:32 +00:00
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
|
|
|
|
// Only for C++.
|
|
|
|
if (!((struct drgn_c_family_lexer *)lexer)->cpp)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
struct drgn_token token;
|
2022-12-01 00:52:49 +00:00
|
|
|
|
|
|
|
do {
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
} while (!err && (token.kind == C_TOKEN_IDENTIFIER ||
|
|
|
|
token.kind == C_TOKEN_COLON));
|
|
|
|
|
2022-11-30 01:19:32 +00:00
|
|
|
if (err)
|
|
|
|
return err;
|
2022-12-01 00:52:49 +00:00
|
|
|
if (token.kind != C_TOKEN_TEMPLATE_ARGUMENTS) {
|
|
|
|
err = drgn_lexer_push(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2022-11-30 01:19:32 +00:00
|
|
|
*len_ret = token.value + token.len - identifier;
|
|
|
|
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
|
|
|
static struct drgn_error *
|
2020-04-23 00:23:26 +01:00
|
|
|
c_parse_specifier_qualifier_list(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
|
|
|
struct drgn_lexer *lexer, const char *filename,
|
|
|
|
struct drgn_qualified_type *ret)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
enum c_type_specifier specifier = SPECIFIER_NONE;
|
|
|
|
enum drgn_qualifiers qualifiers = 0;
|
|
|
|
const char *identifier = NULL;
|
|
|
|
size_t identifier_len = 0;
|
|
|
|
int tag_token = C_TOKEN_EOF;
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
struct drgn_token token;
|
|
|
|
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
/* type-qualifier */
|
|
|
|
if (MIN_QUALIFIER_TOKEN <= token.kind &&
|
|
|
|
token.kind <= MAX_QUALIFIER_TOKEN) {
|
|
|
|
qualifiers |= qualifier_from_token[token.kind];
|
|
|
|
/* type-specifier */
|
|
|
|
} else if (MIN_SPECIFIER_TOKEN <= token.kind &&
|
|
|
|
token.kind <= MAX_SPECIFIER_TOKEN) {
|
|
|
|
enum c_type_specifier prev_specifier;
|
|
|
|
|
|
|
|
if (tag_token != C_TOKEN_EOF) {
|
|
|
|
return drgn_error_format(DRGN_ERROR_SYNTAX,
|
|
|
|
"cannot combine '%s' with '%s'",
|
2022-02-05 01:17:31 +00:00
|
|
|
keyword_spelling[token.kind],
|
|
|
|
keyword_spelling[tag_token]);
|
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 (identifier) {
|
|
|
|
return drgn_error_format(DRGN_ERROR_SYNTAX,
|
|
|
|
"cannot combine '%s' with identifier",
|
2022-02-05 01:17:31 +00:00
|
|
|
keyword_spelling[token.kind]);
|
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
|
|
|
}
|
|
|
|
prev_specifier = specifier;
|
|
|
|
specifier = specifier_transition[specifier][token.kind];
|
|
|
|
if (specifier == SPECIFIER_ERROR) {
|
|
|
|
return drgn_error_format(DRGN_ERROR_SYNTAX,
|
|
|
|
"cannot combine '%s' with '%s'",
|
2022-02-05 01:17:31 +00:00
|
|
|
keyword_spelling[token.kind],
|
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
|
|
|
specifier_spelling[prev_specifier]);
|
|
|
|
}
|
2022-12-01 00:52:49 +00:00
|
|
|
} else if ((token.kind == C_TOKEN_IDENTIFIER ||
|
|
|
|
token.kind == C_TOKEN_COLON) &&
|
|
|
|
specifier == SPECIFIER_NONE && !identifier) {
|
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
|
|
|
identifier = token.value;
|
|
|
|
identifier_len = token.len;
|
2022-12-01 00:52:49 +00:00
|
|
|
err = cpp_append_to_identifier(lexer, identifier,
|
|
|
|
&identifier_len);
|
2022-11-30 01:19:32 +00:00
|
|
|
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
|
|
|
} else if (token.kind == C_TOKEN_STRUCT ||
|
|
|
|
token.kind == C_TOKEN_UNION ||
|
2022-02-18 06:18:53 +00:00
|
|
|
token.kind == C_TOKEN_CLASS ||
|
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
|
|
|
token.kind == C_TOKEN_ENUM) {
|
|
|
|
if (identifier) {
|
|
|
|
return drgn_error_format(DRGN_ERROR_SYNTAX,
|
|
|
|
"cannot combine '%s' with identifier",
|
2022-02-05 01:17:31 +00:00
|
|
|
keyword_spelling[token.kind]);
|
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 (specifier != SPECIFIER_NONE) {
|
|
|
|
return drgn_error_format(DRGN_ERROR_SYNTAX,
|
|
|
|
"cannot combine '%s' with '%s'",
|
2022-02-05 01:17:31 +00:00
|
|
|
keyword_spelling[token.kind],
|
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
|
|
|
specifier_spelling[specifier]);
|
|
|
|
}
|
|
|
|
tag_token = token.kind;
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
2022-12-01 00:52:49 +00:00
|
|
|
if (!(token.kind == C_TOKEN_IDENTIFIER ||
|
|
|
|
token.kind == C_TOKEN_COLON)) {
|
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_format(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected identifier after '%s'",
|
2022-02-05 01:17:31 +00:00
|
|
|
keyword_spelling[tag_token]);
|
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
|
|
|
|
|
|
|
}
|
|
|
|
identifier = token.value;
|
|
|
|
identifier_len = token.len;
|
2022-12-01 00:52:49 +00:00
|
|
|
err = cpp_append_to_identifier(lexer, identifier,
|
|
|
|
&identifier_len);
|
2022-11-30 01:19:32 +00:00
|
|
|
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
|
|
|
} else {
|
|
|
|
err = drgn_lexer_push(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (specifier == SPECIFIER_NONE) {
|
|
|
|
enum drgn_type_kind kind;
|
|
|
|
|
|
|
|
if (tag_token == C_TOKEN_STRUCT) {
|
|
|
|
kind = DRGN_TYPE_STRUCT;
|
|
|
|
} else if (tag_token == C_TOKEN_UNION) {
|
|
|
|
kind = DRGN_TYPE_UNION;
|
2022-02-18 06:18:53 +00:00
|
|
|
} else if (tag_token == C_TOKEN_CLASS) {
|
|
|
|
kind = DRGN_TYPE_CLASS;
|
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
|
|
|
} else if (tag_token == C_TOKEN_ENUM) {
|
|
|
|
kind = DRGN_TYPE_ENUM;
|
|
|
|
} else if (identifier) {
|
2022-11-29 00:12:51 +00:00
|
|
|
if (identifier_len == sizeof("size_t") - 1 &&
|
|
|
|
memcmp(identifier, "size_t",
|
|
|
|
sizeof("size_t") - 1) == 0) {
|
2020-04-23 00:23:26 +01:00
|
|
|
err = drgn_program_find_primitive_type(prog,
|
|
|
|
DRGN_C_TYPE_SIZE_T,
|
|
|
|
&ret->type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
2019-04-20 00:05:19 +01:00
|
|
|
ret->qualifiers = 0;
|
|
|
|
goto out;
|
2022-11-29 00:12:51 +00:00
|
|
|
} else if (identifier_len == sizeof("ptrdiff_t") - 1 &&
|
|
|
|
memcmp(identifier, "ptrdiff_t",
|
|
|
|
sizeof("ptrdiff_t") - 1) == 0) {
|
2020-04-23 00:23:26 +01:00
|
|
|
err = drgn_program_find_primitive_type(prog,
|
|
|
|
DRGN_C_TYPE_PTRDIFF_T,
|
|
|
|
&ret->type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
2019-04-20 00:05:19 +01:00
|
|
|
ret->qualifiers = 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
|
|
|
goto out;
|
|
|
|
} else {
|
|
|
|
kind = DRGN_TYPE_TYPEDEF;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected type specifier");
|
|
|
|
}
|
|
|
|
|
2020-04-23 00:23:26 +01:00
|
|
|
err = drgn_program_find_type_impl(prog, kind, identifier,
|
2019-04-28 16:42:28 +01:00
|
|
|
identifier_len, filename,
|
|
|
|
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
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
} else {
|
2020-04-23 00:23:26 +01:00
|
|
|
err = drgn_program_find_primitive_type(prog,
|
|
|
|
specifier_kind[specifier],
|
|
|
|
&ret->type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
2019-04-20 00:05:19 +01:00
|
|
|
ret->qualifiers = 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
|
|
|
}
|
|
|
|
out:
|
|
|
|
ret->qualifiers |= qualifiers;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
struct c_declarator {
|
|
|
|
/* C_TOKEN_ASTERISK or C_TOKEN_LBRACKET. */
|
|
|
|
int kind;
|
|
|
|
enum drgn_qualifiers qualifiers;
|
|
|
|
/* Only for C_TOKEN_LBRACKET. */
|
|
|
|
bool is_complete;
|
|
|
|
uint64_t length;
|
|
|
|
struct c_declarator *next;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* These functions don't free the declarator list on error. */
|
|
|
|
static struct drgn_error *
|
2020-04-23 00:23:26 +01:00
|
|
|
c_parse_abstract_declarator(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
|
|
|
struct drgn_lexer *lexer,
|
|
|
|
struct c_declarator **outer,
|
|
|
|
struct c_declarator **inner);
|
|
|
|
|
|
|
|
static struct drgn_error *
|
|
|
|
c_parse_optional_type_qualifier_list(struct drgn_lexer *lexer,
|
|
|
|
enum drgn_qualifiers *qualifiers)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_token token;
|
|
|
|
|
|
|
|
*qualifiers = 0;
|
|
|
|
for (;;) {
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (token.kind < MIN_QUALIFIER_TOKEN ||
|
|
|
|
token.kind > MAX_QUALIFIER_TOKEN) {
|
|
|
|
err = drgn_lexer_push(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
*qualifiers |= qualifier_from_token[token.kind];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2020-04-23 00:23:26 +01:00
|
|
|
c_parse_pointer(struct drgn_program *prog, struct drgn_lexer *lexer,
|
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 c_declarator **outer, struct c_declarator **inner)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_token token;
|
|
|
|
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (token.kind != C_TOKEN_ASTERISK)
|
|
|
|
return drgn_error_create(DRGN_ERROR_SYNTAX, "expected '*'");
|
|
|
|
|
|
|
|
*inner = NULL;
|
|
|
|
for (;;) {
|
|
|
|
struct c_declarator *tmp;
|
|
|
|
|
|
|
|
tmp = malloc(sizeof(*tmp));
|
|
|
|
if (!tmp)
|
|
|
|
return &drgn_enomem;
|
|
|
|
|
|
|
|
tmp->kind = C_TOKEN_ASTERISK;
|
|
|
|
tmp->next = *outer;
|
|
|
|
*outer = tmp;
|
|
|
|
|
|
|
|
err = c_parse_optional_type_qualifier_list(lexer,
|
|
|
|
&(*outer)->qualifiers);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (!*inner)
|
|
|
|
*inner = *outer;
|
|
|
|
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (token.kind != C_TOKEN_ASTERISK)
|
|
|
|
return drgn_lexer_push(lexer, &token);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2020-04-23 00:23:26 +01:00
|
|
|
c_parse_direct_abstract_declarator(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
|
|
|
struct drgn_lexer *lexer,
|
|
|
|
struct c_declarator **outer,
|
|
|
|
struct c_declarator **inner)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_token token;
|
|
|
|
|
|
|
|
*inner = NULL;
|
|
|
|
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (token.kind == C_TOKEN_LPAREN) {
|
|
|
|
struct drgn_token token2;
|
|
|
|
|
|
|
|
err = drgn_lexer_peek(lexer, &token2);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (token2.kind == C_TOKEN_ASTERISK ||
|
|
|
|
token2.kind == C_TOKEN_LPAREN ||
|
|
|
|
token2.kind == C_TOKEN_LBRACKET) {
|
2020-04-23 00:23:26 +01:00
|
|
|
err = c_parse_abstract_declarator(prog, lexer, outer,
|
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
|
|
|
inner);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
err = drgn_lexer_pop(lexer, &token2);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (token2.kind != C_TOKEN_RPAREN) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected ')'");
|
|
|
|
}
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
if (token.kind == C_TOKEN_LBRACKET) {
|
|
|
|
struct c_declarator *tmp;
|
|
|
|
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
tmp = malloc(sizeof(*tmp));
|
|
|
|
if (!tmp)
|
|
|
|
return &drgn_enomem;
|
|
|
|
|
|
|
|
tmp->kind = C_TOKEN_LBRACKET;
|
|
|
|
tmp->qualifiers = 0;
|
|
|
|
if (token.kind == C_TOKEN_NUMBER) {
|
|
|
|
tmp->is_complete = true;
|
|
|
|
err = c_token_to_u64(&token, &tmp->length);
|
|
|
|
if (err) {
|
|
|
|
free(tmp);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err) {
|
|
|
|
free(tmp);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tmp->is_complete = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (*inner) {
|
|
|
|
tmp->next = (*inner)->next;
|
|
|
|
*inner = (*inner)->next = tmp;
|
|
|
|
} else {
|
|
|
|
tmp->next = *outer;
|
|
|
|
*outer = *inner = tmp;
|
|
|
|
}
|
|
|
|
if (token.kind != C_TOKEN_RBRACKET) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected ']'");
|
|
|
|
}
|
|
|
|
} else if (token.kind == C_TOKEN_LPAREN) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"function pointer types are not implemented");
|
|
|
|
} else {
|
|
|
|
err = drgn_lexer_push(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (!*inner) {
|
|
|
|
return drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected abstract declarator");
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *
|
2020-04-23 00:23:26 +01:00
|
|
|
c_parse_abstract_declarator(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
|
|
|
struct drgn_lexer *lexer,
|
|
|
|
struct c_declarator **outer,
|
|
|
|
struct c_declarator **inner)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_token token;
|
|
|
|
|
|
|
|
err = drgn_lexer_peek(lexer, &token);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (token.kind == C_TOKEN_ASTERISK) {
|
2020-04-23 00:23:26 +01:00
|
|
|
err = c_parse_pointer(prog, lexer, outer, inner);
|
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_lexer_peek(lexer, &token);
|
2021-12-08 21:47:12 +00:00
|
|
|
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
|
|
|
if (token.kind == C_TOKEN_LPAREN ||
|
|
|
|
token.kind == C_TOKEN_LBRACKET) {
|
|
|
|
struct c_declarator *tmp;
|
|
|
|
|
2020-04-23 00:23:26 +01:00
|
|
|
err = c_parse_direct_abstract_declarator(prog, lexer,
|
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
|
|
|
outer, &tmp);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
} else {
|
2020-04-23 00:23:26 +01:00
|
|
|
return c_parse_direct_abstract_declarator(prog, lexer, outer,
|
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
|
|
|
inner);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This always frees the declarator list regardless of success or failure. */
|
|
|
|
static struct drgn_error *
|
2020-04-23 00:23:26 +01:00
|
|
|
c_type_from_declarator(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
|
|
|
struct c_declarator *declarator,
|
|
|
|
struct drgn_qualified_type *ret)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
|
|
|
|
if (!declarator)
|
|
|
|
return NULL;
|
|
|
|
|
2020-04-23 00:23:26 +01:00
|
|
|
err = c_type_from_declarator(prog, declarator->next, 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
|
|
|
if (err) {
|
|
|
|
free(declarator);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (declarator->kind == C_TOKEN_ASTERISK) {
|
2021-02-23 22:06:41 +00:00
|
|
|
uint8_t address_size;
|
|
|
|
err = drgn_program_address_size(prog, &address_size);
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
if (!err) {
|
2021-02-23 22:06:41 +00:00
|
|
|
err = drgn_pointer_type_create(prog, *ret, address_size,
|
Track byte order in scalar types instead of objects
Currently, reference objects and buffer value objects have a byte order.
However, this doesn't always make sense for a couple of reasons:
- Byte order is only meaningful for scalars. What does it mean for a
struct to be big endian? A struct doesn't have a most or least
significant byte; its scalar members do.
- The DWARF specification allows either types or variables to have a
byte order (DW_AT_endianity). The only producer I could find that uses
this is GCC for the scalar_storage_order type attribute, and it only
uses it for base types, not variables. GDB only seems to use to check
it for base types, as well.
So, remove the byte order from objects, and move it to integer, boolean,
floating-point, and pointer types. This model makes more sense, and it
means that we can get the binary representation of any object now.
The only downside is that we can no longer support a bit offset for
non-scalars, but as far as I can tell, nothing needs that.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-02-18 00:13:23 +00:00
|
|
|
DRGN_PROGRAM_ENDIAN,
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
drgn_type_language(ret->type),
|
|
|
|
&ret->type);
|
|
|
|
}
|
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
|
|
|
} else if (declarator->is_complete) {
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
err = drgn_array_type_create(prog, *ret, declarator->length,
|
|
|
|
drgn_type_language(ret->type),
|
|
|
|
&ret->type);
|
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
|
|
|
} else {
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
err = drgn_incomplete_array_type_create(prog, *ret,
|
|
|
|
drgn_type_language(ret->type),
|
|
|
|
&ret->type);
|
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)
|
|
|
|
ret->qualifiers = declarator->qualifiers;
|
|
|
|
free(declarator);
|
|
|
|
return err;
|
|
|
|
}
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
static struct drgn_error *c_family_find_type(const struct drgn_language *lang,
|
|
|
|
struct drgn_program *prog,
|
|
|
|
const char *name,
|
|
|
|
const char *filename,
|
|
|
|
struct drgn_qualified_type *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;
|
2022-02-18 06:18:53 +00:00
|
|
|
struct drgn_c_family_lexer c_family_lexer;
|
|
|
|
struct drgn_lexer *lexer = &c_family_lexer.lexer;
|
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_token token;
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
c_family_lexer.cpp = lang == &drgn_language_cpp;
|
|
|
|
drgn_lexer_init(lexer, drgn_c_family_lexer_func, name);
|
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
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
err = c_parse_specifier_qualifier_list(prog, lexer, filename, 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
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
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)
|
|
|
|
goto out;
|
|
|
|
if (token.kind != C_TOKEN_EOF) {
|
|
|
|
struct c_declarator *outer = NULL, *inner;
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
err = drgn_lexer_push(lexer, &token);
|
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;
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
err = c_parse_abstract_declarator(prog, lexer, &outer, &inner);
|
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) {
|
|
|
|
while (outer) {
|
|
|
|
struct c_declarator *next;
|
|
|
|
|
|
|
|
next = outer->next;
|
|
|
|
free(outer);
|
|
|
|
outer = next;
|
|
|
|
}
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
2020-04-23 00:23:26 +01:00
|
|
|
err = c_type_from_declarator(prog, outer, 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
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
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)
|
|
|
|
goto out;
|
|
|
|
if (token.kind != C_TOKEN_EOF) {
|
|
|
|
err = drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"extra tokens after type name");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = NULL;
|
|
|
|
out:
|
2022-02-18 06:18:53 +00:00
|
|
|
drgn_lexer_deinit(lexer);
|
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;
|
|
|
|
}
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
static struct drgn_error *c_family_bit_offset(struct drgn_program *prog,
|
|
|
|
struct drgn_type *type,
|
|
|
|
const char *member_designator,
|
|
|
|
uint64_t *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;
|
2022-02-18 06:18:53 +00:00
|
|
|
struct drgn_c_family_lexer c_family_lexer;
|
|
|
|
struct drgn_lexer *lexer = &c_family_lexer.lexer;
|
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
|
|
|
int state = INT_MIN;
|
|
|
|
uint64_t bit_offset = 0;
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
c_family_lexer.cpp = prog->lang == &drgn_language_cpp;
|
|
|
|
drgn_lexer_init(lexer, drgn_c_family_lexer_func, member_designator);
|
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 (;;) {
|
|
|
|
struct drgn_token token;
|
|
|
|
|
2022-02-18 06:18:53 +00:00
|
|
|
err = drgn_lexer_pop(lexer, &token);
|
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)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
switch (state) {
|
|
|
|
case INT_MIN:
|
|
|
|
case C_TOKEN_DOT:
|
|
|
|
if (token.kind == C_TOKEN_IDENTIFIER) {
|
2020-12-15 01:58:44 +00:00
|
|
|
struct drgn_type_member *member;
|
|
|
|
uint64_t member_bit_offset;
|
|
|
|
err = drgn_type_find_member_len(type,
|
|
|
|
token.value,
|
|
|
|
token.len,
|
|
|
|
&member,
|
|
|
|
&member_bit_offset);
|
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)
|
|
|
|
goto out;
|
|
|
|
if (__builtin_add_overflow(bit_offset,
|
2020-12-15 01:58:44 +00:00
|
|
|
member_bit_offset,
|
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
|
|
|
&bit_offset)) {
|
|
|
|
err = drgn_error_create(DRGN_ERROR_OVERFLOW,
|
|
|
|
"offset is too large");
|
|
|
|
goto out;
|
|
|
|
}
|
2020-12-15 01:58:44 +00:00
|
|
|
struct drgn_qualified_type member_type;
|
2020-12-18 22:11:29 +00:00
|
|
|
err = drgn_member_type(member, &member_type,
|
|
|
|
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
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
type = member_type.type;
|
|
|
|
} else if (state == C_TOKEN_DOT) {
|
|
|
|
err = drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected identifier after '.'");
|
|
|
|
goto out;
|
|
|
|
} else {
|
|
|
|
err = drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected identifier");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case C_TOKEN_IDENTIFIER:
|
|
|
|
case C_TOKEN_RBRACKET:
|
|
|
|
switch (token.kind) {
|
|
|
|
case C_TOKEN_EOF:
|
|
|
|
*ret = bit_offset;
|
|
|
|
err = NULL;
|
|
|
|
goto out;
|
|
|
|
case C_TOKEN_DOT:
|
|
|
|
case C_TOKEN_LBRACKET:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
if (state == C_TOKEN_IDENTIFIER) {
|
|
|
|
err = drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected '.' or '[' after identifier");
|
|
|
|
goto out;
|
|
|
|
} else {
|
|
|
|
err = drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected '.' or '[' after ']'");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case C_TOKEN_LBRACKET:
|
|
|
|
if (token.kind == C_TOKEN_NUMBER) {
|
|
|
|
struct drgn_type *underlying_type;
|
|
|
|
struct drgn_type *element_type;
|
|
|
|
uint64_t index, bit_size, element_offset;
|
|
|
|
|
|
|
|
err = c_token_to_u64(&token, &index);
|
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
underlying_type = drgn_underlying_type(type);
|
|
|
|
if (drgn_type_kind(underlying_type) != DRGN_TYPE_ARRAY) {
|
|
|
|
err = drgn_type_error("'%s' is not an array",
|
|
|
|
type);
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
element_type =
|
|
|
|
drgn_type_type(underlying_type).type;
|
|
|
|
err = drgn_type_bit_size(element_type,
|
|
|
|
&bit_size);
|
|
|
|
if (err)
|
|
|
|
goto out;
|
|
|
|
if (__builtin_mul_overflow(index, bit_size,
|
|
|
|
&element_offset) ||
|
|
|
|
__builtin_add_overflow(bit_offset,
|
|
|
|
element_offset,
|
|
|
|
&bit_offset)) {
|
|
|
|
err = drgn_error_create(DRGN_ERROR_OVERFLOW,
|
|
|
|
"offset is too large");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
type = element_type;
|
|
|
|
} else {
|
|
|
|
err = drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected number after '['");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case C_TOKEN_NUMBER:
|
|
|
|
if (token.kind != C_TOKEN_RBRACKET) {
|
|
|
|
err = drgn_error_create(DRGN_ERROR_SYNTAX,
|
|
|
|
"expected ']' after number");
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2020-05-07 23:02:33 +01:00
|
|
|
UNREACHABLE();
|
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
|
|
|
}
|
|
|
|
state = token.kind;
|
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2022-02-18 06:18:53 +00:00
|
|
|
drgn_lexer_deinit(lexer);
|
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;
|
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_integer_literal(struct drgn_object *res,
|
|
|
|
uint64_t uvalue)
|
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-04-22 20:30:15 +01:00
|
|
|
static const enum drgn_primitive_type types[] = {
|
|
|
|
DRGN_C_TYPE_INT,
|
|
|
|
DRGN_C_TYPE_LONG,
|
|
|
|
DRGN_C_TYPE_LONG_LONG,
|
|
|
|
DRGN_C_TYPE_UNSIGNED_LONG_LONG,
|
|
|
|
};
|
|
|
|
struct drgn_error *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
|
|
|
|
2021-08-24 01:07:26 +01:00
|
|
|
unsigned int bits = fls(uvalue);
|
|
|
|
struct drgn_qualified_type qualified_type;
|
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
|
|
|
qualified_type.qualifiers = 0;
|
2021-08-24 01:07:26 +01:00
|
|
|
array_for_each(type, types) {
|
2020-08-27 19:26:39 +01:00
|
|
|
err = drgn_program_find_primitive_type(drgn_object_program(res),
|
2021-08-24 01:07:26 +01:00
|
|
|
*type,
|
2020-04-23 00:23:26 +01:00
|
|
|
&qualified_type.type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (drgn_type_is_signed(qualified_type.type) &&
|
|
|
|
bits < 8 * drgn_type_size(qualified_type.type)) {
|
|
|
|
return drgn_object_set_signed(res,
|
|
|
|
qualified_type,
|
|
|
|
uvalue, 0);
|
|
|
|
} else if (!drgn_type_is_signed(qualified_type.type) &&
|
|
|
|
bits <= 8 * drgn_type_size(qualified_type.type)) {
|
|
|
|
return drgn_object_set_unsigned(res, qualified_type,
|
|
|
|
uvalue, 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
|
|
|
}
|
2019-04-22 20:30:15 +01:00
|
|
|
return drgn_error_create(DRGN_ERROR_INVALID_ARGUMENT,
|
|
|
|
"integer literal is too large");
|
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
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_bool_literal(struct drgn_object *res, bool bvalue)
|
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-04-22 20:30:15 +01:00
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_qualified_type qualified_type;
|
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
|
|
|
|
2020-08-27 19:26:39 +01:00
|
|
|
err = drgn_program_find_primitive_type(drgn_object_program(res),
|
|
|
|
DRGN_C_TYPE_INT,
|
2020-04-23 00:23:26 +01:00
|
|
|
&qualified_type.type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
qualified_type.qualifiers = 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
|
|
|
return drgn_object_set_signed(res, qualified_type, bvalue, 0);
|
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_float_literal(struct drgn_object *res,
|
|
|
|
double fvalue)
|
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-04-22 20:30:15 +01:00
|
|
|
struct drgn_error *err;
|
|
|
|
struct drgn_qualified_type qualified_type;
|
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
|
|
|
|
2020-08-27 19:26:39 +01:00
|
|
|
err = drgn_program_find_primitive_type(drgn_object_program(res),
|
|
|
|
DRGN_C_TYPE_DOUBLE,
|
2020-04-23 00:23:26 +01:00
|
|
|
&qualified_type.type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
qualified_type.qualifiers = 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
|
|
|
return drgn_object_set_float(res, qualified_type, fvalue);
|
|
|
|
}
|
|
|
|
|
2019-04-20 00:05:19 +01:00
|
|
|
static const int c_integer_conversion_rank[] = {
|
|
|
|
[DRGN_C_TYPE_BOOL] = 0,
|
|
|
|
[DRGN_C_TYPE_CHAR] = 1,
|
|
|
|
[DRGN_C_TYPE_SIGNED_CHAR] = 1,
|
|
|
|
[DRGN_C_TYPE_UNSIGNED_CHAR] = 1,
|
|
|
|
[DRGN_C_TYPE_SHORT] = 2,
|
|
|
|
[DRGN_C_TYPE_UNSIGNED_SHORT] = 2,
|
|
|
|
[DRGN_C_TYPE_INT] = 3,
|
|
|
|
[DRGN_C_TYPE_UNSIGNED_INT] = 3,
|
|
|
|
[DRGN_C_TYPE_LONG] = 4,
|
|
|
|
[DRGN_C_TYPE_UNSIGNED_LONG] = 4,
|
|
|
|
[DRGN_C_TYPE_LONG_LONG] = 5,
|
|
|
|
[DRGN_C_TYPE_UNSIGNED_LONG_LONG] = 5,
|
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 bool c_can_represent_all_values(struct drgn_type *type1,
|
|
|
|
uint64_t bit_field_size1,
|
|
|
|
struct drgn_type *type2,
|
|
|
|
uint64_t bit_field_size2)
|
|
|
|
{
|
|
|
|
uint64_t width1, width2;
|
|
|
|
bool is_signed1, is_signed2;
|
|
|
|
|
|
|
|
if (drgn_type_kind(type1) == DRGN_TYPE_BOOL) {
|
|
|
|
width1 = 1;
|
|
|
|
is_signed1 = false;
|
|
|
|
} else {
|
|
|
|
width1 = (bit_field_size1 ? bit_field_size1 :
|
|
|
|
8 * drgn_type_size(type1));
|
|
|
|
is_signed1 = drgn_type_is_signed(type1);
|
|
|
|
}
|
|
|
|
if (drgn_type_kind(type2) == DRGN_TYPE_BOOL) {
|
|
|
|
width2 = 1;
|
|
|
|
is_signed2 = false;
|
|
|
|
} else {
|
|
|
|
width2 = (bit_field_size2 ? bit_field_size2 :
|
|
|
|
8 * drgn_type_size(type2));
|
|
|
|
is_signed2 = drgn_type_is_signed(type2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (is_signed1 == is_signed2)
|
|
|
|
return width1 >= width2;
|
|
|
|
else if (is_signed1 && !is_signed2)
|
|
|
|
return width1 > width2;
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-04-23 00:23:26 +01:00
|
|
|
static struct drgn_error *c_integer_promotions(struct drgn_program *prog,
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type *type)
|
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-04-22 20:30:15 +01:00
|
|
|
struct drgn_error *err;
|
2019-04-20 00:05:19 +01:00
|
|
|
enum drgn_primitive_type primitive;
|
2019-04-22 20:30:15 +01:00
|
|
|
struct drgn_type *int_type;
|
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
|
|
|
|
|
|
|
switch (drgn_type_kind(type->underlying_type)) {
|
|
|
|
case DRGN_TYPE_ENUM:
|
|
|
|
/* Convert the enum to its compatible type. */
|
|
|
|
type->type = type->underlying_type =
|
|
|
|
drgn_type_type(type->underlying_type).type;
|
|
|
|
if (!type->type) {
|
|
|
|
return drgn_error_format(DRGN_ERROR_INVALID_ARGUMENT,
|
|
|
|
"operand cannot have incomplete enum type");
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DRGN_TYPE_INT:
|
|
|
|
case DRGN_TYPE_BOOL:
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-04-20 00:05:19 +01:00
|
|
|
primitive = drgn_type_primitive(type->underlying_type);
|
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
|
|
|
/*
|
|
|
|
* Integer promotions are performed on types whose integer conversion
|
|
|
|
* rank is less than or equal to the rank of int and unsigned int.
|
|
|
|
*
|
|
|
|
* If this isn't a standard integer type, then we don't know the rank,
|
|
|
|
* so we may need to promote it. According to the C standard, "the rank
|
|
|
|
* of a signed integer type shall be greater than the rank of any signed
|
|
|
|
* integer type with less precision", and "the rank of any standard
|
|
|
|
* integer type shall be greater than the rank of any extended integer
|
|
|
|
* type with the same width". If an extended signed integer type has
|
|
|
|
* less precision than int, or the same width as int, then all of its
|
|
|
|
* values can be represented by int (and likewise for an extended
|
|
|
|
* unsigned integer type and unsigned int). Therefore, an extended
|
|
|
|
* integer type should be promoted iff all of its values can be
|
|
|
|
* represented by int or unsigned int.
|
|
|
|
*
|
|
|
|
* Integer promotions are also performed on bit fields. The C standard
|
|
|
|
* only requires that bit fields of type _Bool, int, or unsigned int are
|
|
|
|
* supported, so it does not define how integer promotions should affect
|
|
|
|
* a bit field which cannot be represented by int or unsigned int. Clang
|
|
|
|
* promotes it to the full width, but GCC does not. We implement the GCC
|
|
|
|
* behavior of preserving the width.
|
|
|
|
*/
|
2021-08-24 01:07:26 +01:00
|
|
|
if (primitive >= array_size(c_integer_conversion_rank) ||
|
2019-04-22 20:30:15 +01:00
|
|
|
type->bit_field_size) {
|
2020-04-23 00:23:26 +01:00
|
|
|
err = drgn_program_find_primitive_type(prog, DRGN_C_TYPE_INT,
|
|
|
|
&int_type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (c_can_represent_all_values(int_type, 0,
|
|
|
|
type->underlying_type,
|
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
|
|
|
type->bit_field_size)) {
|
2019-04-22 20:30:15 +01:00
|
|
|
type->type = type->underlying_type = int_type;
|
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
|
|
|
type->bit_field_size = 0;
|
2019-04-22 20:30:15 +01:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2020-04-23 00:23:26 +01:00
|
|
|
err = drgn_program_find_primitive_type(prog,
|
|
|
|
DRGN_C_TYPE_UNSIGNED_INT,
|
|
|
|
&int_type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (c_can_represent_all_values(int_type, 0,
|
|
|
|
type->underlying_type,
|
|
|
|
type->bit_field_size)) {
|
|
|
|
type->type = type->underlying_type = int_type;
|
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
|
|
|
type->bit_field_size = 0;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-04-20 00:05:19 +01:00
|
|
|
if (primitive == DRGN_C_TYPE_INT ||
|
|
|
|
primitive == DRGN_C_TYPE_UNSIGNED_INT ||
|
|
|
|
c_integer_conversion_rank[primitive] >
|
|
|
|
c_integer_conversion_rank[DRGN_C_TYPE_INT])
|
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;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* If int can represent all values of the original type, then the result
|
|
|
|
* is int. Otherwise, the result is unsigned int.
|
|
|
|
*/
|
2020-04-23 00:23:26 +01:00
|
|
|
err = drgn_program_find_primitive_type(prog, DRGN_C_TYPE_INT,
|
|
|
|
&int_type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
if (c_can_represent_all_values(int_type, 0, type->underlying_type, 0)) {
|
|
|
|
type->type = int_type;
|
|
|
|
} else {
|
2020-04-23 00:23:26 +01:00
|
|
|
err = drgn_program_find_primitive_type(prog,
|
|
|
|
DRGN_C_TYPE_UNSIGNED_INT,
|
|
|
|
&type->type);
|
2019-04-22 20:30:15 +01:00
|
|
|
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
|
|
|
type->underlying_type = type->type;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2019-04-22 20:30:15 +01:00
|
|
|
static struct drgn_error *
|
2020-04-23 00:23:26 +01:00
|
|
|
c_corresponding_unsigned_type(struct drgn_program *prog,
|
2019-04-22 20:30:15 +01:00
|
|
|
enum drgn_primitive_type type,
|
|
|
|
struct drgn_type **ret)
|
|
|
|
{
|
|
|
|
switch (type) {
|
|
|
|
/*
|
|
|
|
* char, signed char, and short are promoted to int, so we don't need to
|
|
|
|
* handle them here.
|
|
|
|
*/
|
|
|
|
case DRGN_C_TYPE_INT:
|
2020-04-23 00:23:26 +01:00
|
|
|
return drgn_program_find_primitive_type(prog,
|
|
|
|
DRGN_C_TYPE_UNSIGNED_INT,
|
|
|
|
ret);
|
2019-04-22 20:30:15 +01:00
|
|
|
case DRGN_C_TYPE_LONG:
|
2020-04-23 00:23:26 +01:00
|
|
|
return drgn_program_find_primitive_type(prog,
|
|
|
|
DRGN_C_TYPE_UNSIGNED_LONG,
|
|
|
|
ret);
|
2019-04-22 20:30:15 +01:00
|
|
|
case DRGN_C_TYPE_LONG_LONG:
|
2020-04-23 00:23:26 +01:00
|
|
|
return drgn_program_find_primitive_type(prog,
|
|
|
|
DRGN_C_TYPE_UNSIGNED_LONG_LONG,
|
|
|
|
ret);
|
2019-04-22 20:30:15 +01:00
|
|
|
default:
|
2020-05-07 23:02:33 +01:00
|
|
|
UNREACHABLE();
|
2019-04-22 20:30:15 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-04-23 00:23:26 +01:00
|
|
|
static struct drgn_error *c_common_real_type(struct drgn_program *prog,
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type *type1,
|
|
|
|
struct drgn_operand_type *type2,
|
|
|
|
struct drgn_operand_type *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;
|
2019-04-20 00:05:19 +01:00
|
|
|
enum drgn_primitive_type primitive1, primitive2;
|
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
|
|
|
bool is_float1, is_float2;
|
|
|
|
bool is_signed1, is_signed2;
|
|
|
|
int rank_cmp;
|
|
|
|
|
|
|
|
ret->qualifiers = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Strictly, the rules are:
|
|
|
|
*
|
|
|
|
* If either operand is long double, then the result is long double.
|
|
|
|
* Otherwise, if either operand is double, then the result is double.
|
|
|
|
* Otherwise, if either operand is float, then the result is float.
|
|
|
|
*
|
|
|
|
* However, we also have to handle other floating types not in the
|
|
|
|
* standard. Thus, the result is always the larger type, with ties
|
|
|
|
* broken in the order unknown > long double > double > float.
|
|
|
|
*/
|
|
|
|
is_float1 = drgn_type_kind(type1->underlying_type) == DRGN_TYPE_FLOAT;
|
|
|
|
is_float2 = drgn_type_kind(type2->underlying_type) == DRGN_TYPE_FLOAT;
|
|
|
|
if (is_float1 && is_float2) {
|
|
|
|
uint64_t size1, size2;
|
|
|
|
|
|
|
|
size1 = drgn_type_size(type1->underlying_type);
|
|
|
|
size2 = drgn_type_size(type2->underlying_type);
|
|
|
|
if (size1 > size2)
|
|
|
|
goto ret1;
|
|
|
|
else if (size2 > size1)
|
|
|
|
goto ret2;
|
2019-04-20 00:05:19 +01:00
|
|
|
else if (drgn_type_primitive(type1->underlying_type) >
|
|
|
|
drgn_type_primitive(type2->underlying_type))
|
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
|
|
|
goto ret1;
|
|
|
|
else
|
|
|
|
goto ret2;
|
|
|
|
} else if (is_float1) {
|
|
|
|
goto ret1;
|
|
|
|
} else if (is_float2) {
|
|
|
|
goto ret2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, the integer promotions are performed before applying the
|
|
|
|
* following rules.
|
|
|
|
*/
|
2020-04-23 00:23:26 +01:00
|
|
|
err = c_integer_promotions(prog, type1);
|
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;
|
2020-04-23 00:23:26 +01:00
|
|
|
err = c_integer_promotions(prog, type2);
|
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;
|
|
|
|
|
|
|
|
is_signed1 = drgn_type_is_signed(type1->underlying_type);
|
|
|
|
is_signed2 = drgn_type_is_signed(type2->underlying_type);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The C standard only requires that bit fields of type _Bool, int, or
|
|
|
|
* unsigned int are supported, which are always promoted to int or
|
|
|
|
* unsigned int, so it does not define how to find the common real type
|
|
|
|
* when one or both of the operands are bit fields. GCC seems to use the
|
|
|
|
* wider operand, or the unsigned operand if they have equal width. As
|
|
|
|
* usual, we pick type2 if the two types are equivalent.
|
|
|
|
*/
|
|
|
|
if (type1->bit_field_size || type2->bit_field_size) {
|
|
|
|
uint64_t width1, width2;
|
|
|
|
|
|
|
|
width1 = (type1->bit_field_size ? type1->bit_field_size :
|
|
|
|
8 * drgn_type_size(type1->type));
|
|
|
|
width2 = (type2->bit_field_size ? type2->bit_field_size :
|
|
|
|
8 * drgn_type_size(type2->type));
|
|
|
|
if (width1 < width2 ||
|
|
|
|
(width1 == width2 && (!is_signed2 || is_signed1)))
|
|
|
|
goto ret2;
|
|
|
|
else
|
|
|
|
goto ret1;
|
|
|
|
}
|
|
|
|
|
2019-04-20 00:05:19 +01:00
|
|
|
primitive1 = drgn_type_primitive(type1->underlying_type);
|
|
|
|
primitive2 = drgn_type_primitive(type2->underlying_type);
|
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-04-20 00:05:19 +01:00
|
|
|
if (primitive1 != DRGN_NOT_PRIMITIVE_TYPE &&
|
|
|
|
primitive2 != DRGN_NOT_PRIMITIVE_TYPE) {
|
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 both operands have the same type, then no further
|
|
|
|
* conversions are needed.
|
|
|
|
*
|
|
|
|
* We can return either type1 or type2 here; it only makes a
|
|
|
|
* difference for typedefs. Arbitrarily pick type2 because
|
|
|
|
* that's what GCC seems to do (Clang always throws away the
|
|
|
|
* typedef).
|
|
|
|
*/
|
2019-04-20 00:05:19 +01:00
|
|
|
if (primitive1 == primitive2)
|
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
|
|
|
goto ret2;
|
|
|
|
|
|
|
|
/* Ranks are small, so this won't overflow. */
|
2019-04-20 00:05:19 +01:00
|
|
|
rank_cmp = (c_integer_conversion_rank[primitive1] -
|
|
|
|
c_integer_conversion_rank[primitive2]);
|
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
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* We don't know the rank of non-standard integer types.
|
|
|
|
* However, we can usually compare their ranks, because
|
|
|
|
* according to the C standard, "the rank of a signed integer
|
|
|
|
* type shall be greater than the rank of any signed integer
|
|
|
|
* type with less precision", "the rank of any unsigned integer
|
|
|
|
* type shall equal the rank of the corresponding signed integer
|
|
|
|
* type", and "the rank of any standard integer type shall be
|
|
|
|
* greater than the rank of any extended integer type with the
|
|
|
|
* same width". The only case where we can't is if both types
|
|
|
|
* are non-standard and have the same size; we treat them as
|
|
|
|
* having equal rank in this case.
|
|
|
|
*/
|
|
|
|
uint64_t size1, size2;
|
|
|
|
|
|
|
|
size1 = drgn_type_size(type1->underlying_type);
|
|
|
|
size2 = drgn_type_size(type2->underlying_type);
|
2019-04-20 00:05:19 +01:00
|
|
|
if (size1 == size2 && primitive1 == DRGN_NOT_PRIMITIVE_TYPE &&
|
|
|
|
primitive2 == DRGN_NOT_PRIMITIVE_TYPE)
|
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
|
|
|
rank_cmp = 0;
|
2019-04-20 00:05:19 +01:00
|
|
|
else if ((size1 == size2 && primitive2 != DRGN_NOT_PRIMITIVE_TYPE) ||
|
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
|
|
|
size1 < size2)
|
|
|
|
rank_cmp = -1;
|
|
|
|
else
|
|
|
|
rank_cmp = 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, if both operands have signed integer types or both have
|
|
|
|
* unsigned integer types, then the result is the type of the operand
|
|
|
|
* with the greater rank.
|
|
|
|
*/
|
|
|
|
if (is_signed1 == is_signed2) {
|
|
|
|
if (rank_cmp > 0)
|
|
|
|
goto ret1;
|
|
|
|
else
|
|
|
|
goto ret2;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, if the operand that has unsigned integer type has rank
|
|
|
|
* greater or equal to the rank of the type of the other operand, then
|
|
|
|
* the result is the unsigned integer type.
|
|
|
|
*/
|
|
|
|
if (!is_signed1 && rank_cmp >= 0)
|
|
|
|
goto ret1;
|
|
|
|
else if (!is_signed2 && rank_cmp <= 0)
|
|
|
|
goto ret2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, if the type of the operand with signed integer type can
|
|
|
|
* represent all of the values of the type of the operand with unsigned
|
|
|
|
* integer type, then the result is the signed integer type.
|
|
|
|
*/
|
|
|
|
if (is_signed1 && c_can_represent_all_values(type1->underlying_type, 0,
|
|
|
|
type2->underlying_type, 0))
|
|
|
|
goto ret1;
|
|
|
|
if (is_signed2 && c_can_represent_all_values(type2->underlying_type, 0,
|
|
|
|
type1->underlying_type, 0))
|
|
|
|
goto ret2;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Otherwise, the result is the unsigned integer type corresponding to
|
|
|
|
* the type of the operand with signed integer type.
|
|
|
|
*
|
|
|
|
* Note that this case is not reached for non-standard types: if the
|
|
|
|
* types have different signs and the signed integer type has greater
|
|
|
|
* rank, then it must have greater size and thus be able to represent
|
|
|
|
* all values of the unsigned integer type.
|
|
|
|
*/
|
2020-04-23 00:23:26 +01:00
|
|
|
err = c_corresponding_unsigned_type(prog,
|
2019-04-22 20:30:15 +01:00
|
|
|
is_signed1 ? primitive1 : primitive2,
|
|
|
|
&ret->type);
|
|
|
|
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
|
|
|
ret->underlying_type = ret->type;
|
|
|
|
ret->bit_field_size = 0;
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ret1:
|
|
|
|
*ret = *type1;
|
|
|
|
return NULL;
|
|
|
|
ret2:
|
|
|
|
*ret = *type2;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct drgn_error *c_operand_type(const struct drgn_object *obj,
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type *type_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
|
|
|
bool *is_pointer_ret,
|
|
|
|
uint64_t *referenced_size_ret)
|
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
|
|
|
|
2021-02-18 22:20:13 +00:00
|
|
|
*type_ret = drgn_object_operand_type(obj);
|
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
|
|
|
switch (drgn_type_kind(type_ret->underlying_type)) {
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
case DRGN_TYPE_ARRAY: {
|
2021-02-23 22:06:41 +00:00
|
|
|
uint8_t address_size;
|
|
|
|
err = drgn_program_address_size(drgn_object_program(obj),
|
|
|
|
&address_size);
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
2020-08-27 19:26:39 +01:00
|
|
|
err = drgn_pointer_type_create(drgn_object_program(obj),
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
drgn_type_type(type_ret->underlying_type),
|
2021-02-23 22:06:41 +00:00
|
|
|
address_size,
|
|
|
|
DRGN_PROGRAM_ENDIAN,
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
drgn_type_language(type_ret->underlying_type),
|
|
|
|
&type_ret->type);
|
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;
|
|
|
|
type_ret->underlying_type = type_ret->type;
|
|
|
|
break;
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +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
|
|
|
case DRGN_TYPE_FUNCTION: {
|
|
|
|
struct drgn_qualified_type function_type = {
|
|
|
|
.type = type_ret->underlying_type,
|
|
|
|
.qualifiers = type_ret->qualifiers,
|
|
|
|
};
|
2021-02-23 22:06:41 +00:00
|
|
|
uint8_t address_size;
|
|
|
|
err = drgn_program_address_size(drgn_object_program(obj),
|
|
|
|
&address_size);
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
2020-08-27 19:26:39 +01:00
|
|
|
err = drgn_pointer_type_create(drgn_object_program(obj),
|
2021-02-23 22:06:41 +00:00
|
|
|
function_type, address_size,
|
Track byte order in scalar types instead of objects
Currently, reference objects and buffer value objects have a byte order.
However, this doesn't always make sense for a couple of reasons:
- Byte order is only meaningful for scalars. What does it mean for a
struct to be big endian? A struct doesn't have a most or least
significant byte; its scalar members do.
- The DWARF specification allows either types or variables to have a
byte order (DW_AT_endianity). The only producer I could find that uses
this is GCC for the scalar_storage_order type attribute, and it only
uses it for base types, not variables. GDB only seems to use to check
it for base types, as well.
So, remove the byte order from objects, and move it to integer, boolean,
floating-point, and pointer types. This model makes more sense, and it
means that we can get the binary representation of any object now.
The only downside is that we can no longer support a bit offset for
non-scalars, but as far as I can tell, nothing needs that.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-02-18 00:13:23 +00:00
|
|
|
DRGN_PROGRAM_ENDIAN,
|
Associate types with program
I originally envisioned types as dumb descriptors. This mostly works for
C because in C, types are fairly simple. However, even then the
drgn_program_member_info() API is awkward. You should be able to look up
a member directly from a type, but we need the program for caching
purposes. This has also held me back from adding offsetof() or
has_member() APIs.
Things get even messier with C++. C++ template parameters can be objects
(e.g., template <int N>). Such parameters would best be represented by a
drgn object, which we need a drgn program for. Static members are a
similar case.
So, let's reimagine types as being owned by a program. This has a few
parts:
1. In libdrgn, simple types are now created by factory functions,
drgn_foo_type_create().
2. To handle their variable length fields, compound types, enum types,
and function types are constructed with a "builder" API.
3. Simple types are deduplicated.
4. The Python type factory functions are replaced by methods of the
Program class.
5. While we're changing the API, the parameters to pointer_type() and
array_type() are reordered to be more logical (and to allow
pointer_type() to take a default size of None for the program's
default pointer size).
6. Likewise, the type factory methods take qualifiers as a keyword
argument only.
A big part of this change is updating the tests and splitting up large
test cases into smaller ones in a few places.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2020-07-16 00:34:56 +01:00
|
|
|
drgn_type_language(type_ret->underlying_type),
|
|
|
|
&type_ret->type);
|
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;
|
|
|
|
type_ret->underlying_type = type_ret->type;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
Track byte order in scalar types instead of objects
Currently, reference objects and buffer value objects have a byte order.
However, this doesn't always make sense for a couple of reasons:
- Byte order is only meaningful for scalars. What does it mean for a
struct to be big endian? A struct doesn't have a most or least
significant byte; its scalar members do.
- The DWARF specification allows either types or variables to have a
byte order (DW_AT_endianity). The only producer I could find that uses
this is GCC for the scalar_storage_order type attribute, and it only
uses it for base types, not variables. GDB only seems to use to check
it for base types, as well.
So, remove the byte order from objects, and move it to integer, boolean,
floating-point, and pointer types. This model makes more sense, and it
means that we can get the binary representation of any object now.
The only downside is that we can no longer support a bit offset for
non-scalars, but as far as I can tell, nothing needs that.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-02-18 00:13:23 +00:00
|
|
|
err = drgn_type_with_byte_order(&type_ret->type,
|
|
|
|
&type_ret->underlying_type,
|
|
|
|
DRGN_PROGRAM_ENDIAN);
|
|
|
|
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
|
|
|
break;
|
|
|
|
}
|
|
|
|
type_ret->qualifiers = 0;
|
|
|
|
|
|
|
|
if (is_pointer_ret) {
|
Track byte order in scalar types instead of objects
Currently, reference objects and buffer value objects have a byte order.
However, this doesn't always make sense for a couple of reasons:
- Byte order is only meaningful for scalars. What does it mean for a
struct to be big endian? A struct doesn't have a most or least
significant byte; its scalar members do.
- The DWARF specification allows either types or variables to have a
byte order (DW_AT_endianity). The only producer I could find that uses
this is GCC for the scalar_storage_order type attribute, and it only
uses it for base types, not variables. GDB only seems to use to check
it for base types, as well.
So, remove the byte order from objects, and move it to integer, boolean,
floating-point, and pointer types. This model makes more sense, and it
means that we can get the binary representation of any object now.
The only downside is that we can no longer support a bit offset for
non-scalars, but as far as I can tell, nothing needs that.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-02-18 00:13:23 +00:00
|
|
|
struct drgn_type *type = type_ret->underlying_type;
|
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
|
|
|
*is_pointer_ret = drgn_type_kind(type) == DRGN_TYPE_POINTER;
|
2019-04-12 23:25:21 +01:00
|
|
|
if (*is_pointer_ret && referenced_size_ret) {
|
Track byte order in scalar types instead of objects
Currently, reference objects and buffer value objects have a byte order.
However, this doesn't always make sense for a couple of reasons:
- Byte order is only meaningful for scalars. What does it mean for a
struct to be big endian? A struct doesn't have a most or least
significant byte; its scalar members do.
- The DWARF specification allows either types or variables to have a
byte order (DW_AT_endianity). The only producer I could find that uses
this is GCC for the scalar_storage_order type attribute, and it only
uses it for base types, not variables. GDB only seems to use to check
it for base types, as well.
So, remove the byte order from objects, and move it to integer, boolean,
floating-point, and pointer types. This model makes more sense, and it
means that we can get the binary representation of any object now.
The only downside is that we can no longer support a bit offset for
non-scalars, but as far as I can tell, nothing needs that.
Signed-off-by: Omar Sandoval <osandov@osandov.com>
2021-02-18 00:13:23 +00:00
|
|
|
struct drgn_type *referenced_type =
|
2019-04-13 00:06:24 +01:00
|
|
|
drgn_underlying_type(drgn_type_type(type).type);
|
|
|
|
if (drgn_type_kind(referenced_type) == DRGN_TYPE_VOID) {
|
|
|
|
*referenced_size_ret = 1;
|
|
|
|
} else {
|
|
|
|
err = drgn_type_sizeof(referenced_type,
|
|
|
|
referenced_size_ret);
|
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_op_cast(struct drgn_object *res,
|
|
|
|
struct drgn_qualified_type qualified_type,
|
|
|
|
const struct drgn_object *obj)
|
2019-04-13 00:37:28 +01:00
|
|
|
{
|
|
|
|
struct drgn_error *err;
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type type;
|
2019-04-13 00:37:28 +01:00
|
|
|
err = c_operand_type(obj, &type, NULL, NULL);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
return drgn_op_cast(res, qualified_type, obj, &type);
|
|
|
|
}
|
|
|
|
|
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
|
|
|
/*
|
|
|
|
* It's too expensive to check that two pointer types are compatible, so we just
|
|
|
|
* check that they refer to the same kind of type with equal size.
|
|
|
|
*/
|
2021-02-18 22:20:13 +00:00
|
|
|
static bool c_pointers_similar(const struct drgn_operand_type *lhs_type,
|
|
|
|
const struct drgn_operand_type *rhs_type,
|
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
|
|
|
uint64_t lhs_size, uint64_t rhs_size)
|
|
|
|
{
|
|
|
|
struct drgn_type *lhs_referenced_type, *rhs_referenced_type;
|
|
|
|
|
|
|
|
lhs_referenced_type = drgn_type_type(lhs_type->underlying_type).type;
|
|
|
|
rhs_referenced_type = drgn_type_type(rhs_type->underlying_type).type;
|
|
|
|
return (drgn_type_kind(lhs_referenced_type) ==
|
|
|
|
drgn_type_kind(rhs_referenced_type) && lhs_size == rhs_size);
|
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_op_bool(const struct drgn_object *obj, bool *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-12-06 01:50:00 +00:00
|
|
|
struct drgn_error *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
|
|
|
struct drgn_type *underlying_type;
|
|
|
|
|
|
|
|
underlying_type = drgn_underlying_type(obj->type);
|
|
|
|
if (drgn_type_kind(underlying_type) == DRGN_TYPE_ARRAY) {
|
|
|
|
*ret = true;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!drgn_type_is_scalar(underlying_type)) {
|
|
|
|
return drgn_qualified_type_error("cannot convert '%s' to bool",
|
|
|
|
drgn_object_qualified_type(obj));
|
|
|
|
}
|
|
|
|
|
2019-12-06 01:50:00 +00:00
|
|
|
err = drgn_object_is_zero(obj, ret);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
*ret = !*ret;
|
|
|
|
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
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_op_cmp(const struct drgn_object *lhs,
|
|
|
|
const struct drgn_object *rhs, int *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;
|
|
|
|
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type lhs_type, rhs_type;
|
|
|
|
bool lhs_pointer, rhs_pointer;
|
2019-04-12 23:25:21 +01:00
|
|
|
err = c_operand_type(lhs, &lhs_type, &lhs_pointer, 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
|
|
|
if (err)
|
|
|
|
return err;
|
2019-04-12 23:25:21 +01:00
|
|
|
err = c_operand_type(rhs, &rhs_type, &rhs_pointer, 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
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (lhs_pointer && rhs_pointer) {
|
|
|
|
return drgn_op_cmp_pointers(lhs, rhs, ret);
|
|
|
|
} else if (lhs_pointer || rhs_pointer) {
|
|
|
|
goto type_error;
|
|
|
|
} else {
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type type;
|
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 (!drgn_type_is_arithmetic(lhs_type.underlying_type) ||
|
|
|
|
!drgn_type_is_arithmetic(rhs_type.underlying_type))
|
|
|
|
goto type_error;
|
2020-08-27 19:26:39 +01:00
|
|
|
err = c_common_real_type(drgn_object_program(lhs), &lhs_type,
|
|
|
|
&rhs_type, &type);
|
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;
|
|
|
|
|
|
|
|
return drgn_op_cmp_impl(lhs, rhs, &type, ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_error:
|
|
|
|
return drgn_error_binary_op("comparison", &lhs_type, &rhs_type);
|
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_op_add(struct drgn_object *res,
|
|
|
|
const struct drgn_object *lhs,
|
|
|
|
const struct drgn_object *rhs)
|
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;
|
2021-02-18 22:20:13 +00:00
|
|
|
|
|
|
|
struct drgn_operand_type lhs_type, rhs_type;
|
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
|
|
|
bool lhs_pointer, rhs_pointer;
|
|
|
|
uint64_t lhs_size, rhs_size;
|
|
|
|
err = c_operand_type(lhs, &lhs_type, &lhs_pointer, &lhs_size);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
err = c_operand_type(rhs, &rhs_type, &rhs_pointer, &rhs_size);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (lhs_pointer) {
|
|
|
|
if (!drgn_type_is_integer(rhs_type.underlying_type))
|
|
|
|
goto type_error;
|
|
|
|
return drgn_op_add_to_pointer(res, &lhs_type, lhs_size, false, lhs, rhs);
|
|
|
|
} else if (rhs_pointer) {
|
|
|
|
if (!drgn_type_is_integer(lhs_type.underlying_type))
|
|
|
|
goto type_error;
|
|
|
|
return drgn_op_add_to_pointer(res, &rhs_type, rhs_size, false, rhs, lhs);
|
|
|
|
} else {
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type type;
|
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 (!drgn_type_is_arithmetic(lhs_type.underlying_type) ||
|
|
|
|
!drgn_type_is_arithmetic(rhs_type.underlying_type))
|
|
|
|
goto type_error;
|
2020-08-27 19:26:39 +01:00
|
|
|
err = c_common_real_type(drgn_object_program(lhs), &lhs_type,
|
|
|
|
&rhs_type, &type);
|
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;
|
|
|
|
|
|
|
|
return drgn_op_add_impl(res, &type, lhs, rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_error:
|
|
|
|
return drgn_error_binary_op("binary +", &lhs_type, &rhs_type);
|
|
|
|
}
|
|
|
|
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_op_sub(struct drgn_object *res,
|
|
|
|
const struct drgn_object *lhs,
|
|
|
|
const struct drgn_object *rhs)
|
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;
|
2021-02-18 22:20:13 +00:00
|
|
|
|
|
|
|
struct drgn_operand_type lhs_type, rhs_type;
|
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
|
|
|
bool lhs_pointer, rhs_pointer;
|
|
|
|
uint64_t lhs_size, rhs_size;
|
|
|
|
err = c_operand_type(lhs, &lhs_type, &lhs_pointer, &lhs_size);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
err = c_operand_type(rhs, &rhs_type, &rhs_pointer, &rhs_size);
|
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
|
|
|
|
if (lhs_pointer && rhs_pointer) {
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type type = {};
|
2020-08-27 19:26:39 +01:00
|
|
|
err = drgn_program_find_primitive_type(drgn_object_program(lhs),
|
2020-04-23 00:23:26 +01:00
|
|
|
DRGN_C_TYPE_PTRDIFF_T,
|
|
|
|
&type.type);
|
2019-04-22 20:30:15 +01:00
|
|
|
if (err)
|
|
|
|
return err;
|
|
|
|
type.underlying_type = drgn_underlying_type(type.type);
|
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 (!c_pointers_similar(&lhs_type, &rhs_type, lhs_size,
|
|
|
|
rhs_size))
|
|
|
|
goto type_error;
|
|
|
|
return drgn_op_sub_pointers(res, &type, lhs_size, lhs, rhs);
|
|
|
|
} else if (lhs_pointer) {
|
|
|
|
if (!drgn_type_is_integer(rhs_type.underlying_type))
|
|
|
|
goto type_error;
|
|
|
|
return drgn_op_add_to_pointer(res, &lhs_type, lhs_size, true,
|
|
|
|
lhs, rhs);
|
|
|
|
} else {
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type type;
|
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 (!drgn_type_is_arithmetic(lhs_type.underlying_type) ||
|
|
|
|
!drgn_type_is_arithmetic(rhs_type.underlying_type))
|
|
|
|
goto type_error;
|
2020-08-27 19:26:39 +01:00
|
|
|
err = c_common_real_type(drgn_object_program(lhs), &lhs_type,
|
|
|
|
&rhs_type, &type);
|
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;
|
|
|
|
|
|
|
|
return drgn_op_sub_impl(res, &type, lhs, rhs);
|
|
|
|
}
|
|
|
|
|
|
|
|
type_error:
|
|
|
|
return drgn_error_binary_op("binary -", &lhs_type, &rhs_type);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define BINARY_OP(op_name, op, check) \
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_op_##op_name(struct drgn_object *res, \
|
|
|
|
const struct drgn_object *lhs, \
|
|
|
|
const struct drgn_object *rhs) \
|
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; \
|
|
|
|
\
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type lhs_type, rhs_type, type; \
|
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 = c_operand_type(lhs, &lhs_type, NULL, NULL); \
|
|
|
|
if (err) \
|
|
|
|
return err; \
|
|
|
|
err = c_operand_type(rhs, &rhs_type, NULL, NULL); \
|
|
|
|
if (err) \
|
|
|
|
return err; \
|
|
|
|
if (!drgn_type_is_##check(lhs_type.underlying_type) || \
|
|
|
|
!drgn_type_is_##check(rhs_type.underlying_type)) \
|
|
|
|
return drgn_error_binary_op("binary "#op, &lhs_type, \
|
|
|
|
&rhs_type); \
|
|
|
|
\
|
2020-08-27 19:26:39 +01:00
|
|
|
err = c_common_real_type(drgn_object_program(lhs), &lhs_type, \
|
|
|
|
&rhs_type, &type); \
|
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; \
|
|
|
|
\
|
|
|
|
return drgn_op_##op_name##_impl(res, &type, lhs, rhs); \
|
|
|
|
}
|
|
|
|
BINARY_OP(mul, *, arithmetic)
|
|
|
|
BINARY_OP(div, /, arithmetic)
|
|
|
|
BINARY_OP(mod, %, integer)
|
|
|
|
BINARY_OP(and, &, integer)
|
|
|
|
BINARY_OP(or, |, integer)
|
|
|
|
BINARY_OP(xor, ^, integer)
|
|
|
|
#undef BINARY_OP
|
|
|
|
|
|
|
|
#define SHIFT_OP(op_name, op) \
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_op_##op_name(struct drgn_object *res, \
|
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
|
|
|
const struct drgn_object *lhs, \
|
|
|
|
const struct drgn_object *rhs) \
|
|
|
|
{ \
|
|
|
|
struct drgn_error *err; \
|
|
|
|
\
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type lhs_type, rhs_type; \
|
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 = c_operand_type(lhs, &lhs_type, NULL, NULL); \
|
|
|
|
if (err) \
|
|
|
|
return err; \
|
|
|
|
err = c_operand_type(rhs, &rhs_type, NULL, NULL); \
|
|
|
|
if (err) \
|
|
|
|
return err; \
|
|
|
|
if (!drgn_type_is_integer(lhs_type.underlying_type) || \
|
|
|
|
!drgn_type_is_integer(rhs_type.underlying_type)) \
|
|
|
|
return drgn_error_binary_op("binary " #op, &lhs_type, \
|
|
|
|
&rhs_type); \
|
|
|
|
\
|
2020-08-27 19:26:39 +01:00
|
|
|
err = c_integer_promotions(drgn_object_program(lhs), &lhs_type); \
|
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; \
|
2020-08-27 19:26:39 +01:00
|
|
|
err = c_integer_promotions(drgn_object_program(lhs), &rhs_type); \
|
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; \
|
|
|
|
\
|
|
|
|
return drgn_op_##op_name##_impl(res, lhs, &lhs_type, rhs, &rhs_type); \
|
|
|
|
}
|
|
|
|
SHIFT_OP(lshift, <<)
|
|
|
|
SHIFT_OP(rshift, >>)
|
|
|
|
#undef SHIFT_OP
|
|
|
|
|
|
|
|
#define UNARY_OP(op_name, op, check) \
|
2022-02-16 20:43:36 +00:00
|
|
|
static struct drgn_error *c_op_##op_name(struct drgn_object *res, \
|
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
|
|
|
const struct drgn_object *obj) \
|
|
|
|
{ \
|
|
|
|
struct drgn_error *err; \
|
|
|
|
\
|
2021-02-18 22:20:13 +00:00
|
|
|
struct drgn_operand_type type; \
|
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 = c_operand_type(obj, &type, NULL, NULL); \
|
|
|
|
if (err) \
|
|
|
|
return err; \
|
|
|
|
if (!drgn_type_is_##check(type.underlying_type)) \
|
|
|
|
return drgn_error_unary_op("unary " #op, &type); \
|
|
|
|
\
|
2020-08-27 19:26:39 +01:00
|
|
|
err = c_integer_promotions(drgn_object_program(obj), &type); \
|
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; \
|
|
|
|
\
|
|
|
|
return drgn_op_##op_name##_impl(res, &type, obj); \
|
|
|
|
}
|
|
|
|
UNARY_OP(pos, +, arithmetic)
|
|
|
|
UNARY_OP(neg, -, arithmetic)
|
|
|
|
UNARY_OP(not, ~, integer)
|
|
|
|
#undef UNARY_OP
|
2022-02-16 20:43:36 +00:00
|
|
|
|
2022-02-16 21:05:28 +00:00
|
|
|
LIBDRGN_PUBLIC const struct drgn_language drgn_language_c = {
|
2022-02-16 20:43:36 +00:00
|
|
|
.name = "C",
|
|
|
|
.number = DRGN_LANGUAGE_C,
|
2020-12-16 00:38:21 +00:00
|
|
|
.has_namespaces = false,
|
2022-02-16 20:43:36 +00:00
|
|
|
.format_type_name = c_format_type_name,
|
|
|
|
.format_type = c_format_type,
|
|
|
|
.format_object = c_format_object,
|
2022-02-18 06:18:53 +00:00
|
|
|
.find_type = c_family_find_type,
|
|
|
|
.bit_offset = c_family_bit_offset,
|
2022-02-16 20:43:36 +00:00
|
|
|
.integer_literal = c_integer_literal,
|
|
|
|
.bool_literal = c_bool_literal,
|
|
|
|
.float_literal = c_float_literal,
|
|
|
|
.op_cast = c_op_cast,
|
|
|
|
.op_bool = c_op_bool,
|
|
|
|
.op_cmp = c_op_cmp,
|
|
|
|
.op_add = c_op_add,
|
|
|
|
.op_sub = c_op_sub,
|
|
|
|
.op_mul = c_op_mul,
|
|
|
|
.op_div = c_op_div,
|
|
|
|
.op_mod = c_op_mod,
|
|
|
|
.op_lshift = c_op_lshift,
|
|
|
|
.op_rshift = c_op_rshift,
|
|
|
|
.op_and = c_op_and,
|
|
|
|
.op_or = c_op_or,
|
|
|
|
.op_xor = c_op_xor,
|
|
|
|
.op_pos = c_op_pos,
|
|
|
|
.op_neg = c_op_neg,
|
|
|
|
.op_not = c_op_not,
|
|
|
|
};
|
|
|
|
|
2022-02-16 21:05:28 +00:00
|
|
|
LIBDRGN_PUBLIC const struct drgn_language drgn_language_cpp = {
|
2022-02-16 20:43:36 +00:00
|
|
|
.name = "C++",
|
|
|
|
.number = DRGN_LANGUAGE_CPP,
|
2020-12-16 00:38:21 +00:00
|
|
|
.has_namespaces = true,
|
2022-02-16 20:43:36 +00:00
|
|
|
.format_type_name = c_format_type_name,
|
|
|
|
.format_type = c_format_type,
|
|
|
|
.format_object = c_format_object,
|
2022-02-18 06:18:53 +00:00
|
|
|
.find_type = c_family_find_type,
|
|
|
|
.bit_offset = c_family_bit_offset,
|
2022-02-16 20:43:36 +00:00
|
|
|
.integer_literal = c_integer_literal,
|
|
|
|
.bool_literal = c_bool_literal,
|
|
|
|
.float_literal = c_float_literal,
|
|
|
|
.op_cast = c_op_cast,
|
|
|
|
.op_bool = c_op_bool,
|
|
|
|
.op_cmp = c_op_cmp,
|
|
|
|
.op_add = c_op_add,
|
|
|
|
.op_sub = c_op_sub,
|
|
|
|
.op_mul = c_op_mul,
|
|
|
|
.op_div = c_op_div,
|
|
|
|
.op_mod = c_op_mod,
|
|
|
|
.op_lshift = c_op_lshift,
|
|
|
|
.op_rshift = c_op_rshift,
|
|
|
|
.op_and = c_op_and,
|
|
|
|
.op_or = c_op_or,
|
|
|
|
.op_xor = c_op_xor,
|
|
|
|
.op_pos = c_op_pos,
|
|
|
|
.op_neg = c_op_neg,
|
|
|
|
.op_not = c_op_not,
|
|
|
|
};
|