mirror of
https://github.com/JakeHillion/object-introspection.git
synced 2024-11-12 21:56:54 +00:00
EnforceCompatibility: Stub out void pointers
CodeGen v1 does not record anything for pointers to incomplete types. Not even the address, as is done for other pointers. Introduce a new Primitive type "Incomplete". This behaves identically to "Void", but allows us to tell whether a type was defined as void or if it ended up like that because of incomplete DWARF information.
This commit is contained in:
parent
7bb6791af9
commit
6fbb60826f
@ -20,7 +20,7 @@ workflows:
|
||||
- build-gcc
|
||||
oid_test_args: "-ftype-graph"
|
||||
tests_regex: "OidIntegration\\..*"
|
||||
exclude_regex: ".*inheritance_polymorphic.*|.*pointers_incomplete_containing_struct|.*arrays_member_int0"
|
||||
exclude_regex: ".*inheritance_polymorphic.*|.*arrays_member_int0"
|
||||
- test:
|
||||
name: test-typed-data-segment-gcc
|
||||
requires:
|
||||
@ -68,7 +68,7 @@ workflows:
|
||||
oid_test_args: "-ftype-graph"
|
||||
tests_regex: "OidIntegration\\..*"
|
||||
# Tests disabled due to bad DWARF generated by the old clang compiler in CI
|
||||
exclude_regex: ".*inheritance_polymorphic.*|.*pointers_incomplete_containing_struct|.*arrays_member_int0|.*fbstring.*|.*std_string_*|.*multi_arg_tb_.*|.*ignored_a"
|
||||
exclude_regex: ".*inheritance_polymorphic.*|.*arrays_member_int0|.*fbstring.*|.*std_string_*|.*multi_arg_tb_.*|.*ignored_a"
|
||||
|
||||
executors:
|
||||
ubuntu-docker:
|
||||
|
@ -83,8 +83,9 @@ Type& DrgnParser::enumerateType(struct drgn_type* type) {
|
||||
if (auto it = drgn_types_.find(type); it != drgn_types_.end())
|
||||
return it->second;
|
||||
|
||||
if (!drgn_utils::isSizeComplete(type)) {
|
||||
return makeType<Primitive>(nullptr, Primitive::Kind::Void);
|
||||
if (!drgn_utils::isSizeComplete(type) &&
|
||||
drgn_type_kind(type) != DRGN_TYPE_VOID) {
|
||||
return makeType<Primitive>(nullptr, Primitive::Kind::Incomplete);
|
||||
}
|
||||
|
||||
enum drgn_type_kind kind = drgn_type_kind(type);
|
||||
|
@ -72,9 +72,22 @@ void EnforceCompatibility::visit(Class& c) {
|
||||
accept(child);
|
||||
}
|
||||
|
||||
// CodeGen v1 replaces parent containers with padding
|
||||
std::erase_if(c.members, [](Member member) {
|
||||
return member.name.starts_with(Flattener::ParentPrefix);
|
||||
// CodeGen v1 replaces parent containers with padding
|
||||
if (member.name.starts_with(Flattener::ParentPrefix))
|
||||
return true;
|
||||
|
||||
if (auto* ptr = dynamic_cast<Pointer*>(&member.type())) {
|
||||
if (auto* primitive = dynamic_cast<Primitive*>(&ptr->pointeeType())) {
|
||||
if (primitive->kind() == Primitive::Kind::Incomplete) {
|
||||
// This is a pointer to an incomplete type. CodeGen v1 does not record
|
||||
// the pointer's address in this case.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,10 @@ void Printer::visit(const Container& c) {
|
||||
|
||||
void Printer::visit(const Primitive& p) {
|
||||
prefix();
|
||||
out_ << "Primitive: " << p.name() << std::endl;
|
||||
out_ << "Primitive: " << p.name();
|
||||
if (p.kind() == Primitive::Kind::Incomplete)
|
||||
out_ << " (incomplete)";
|
||||
out_ << std::endl;
|
||||
}
|
||||
|
||||
void Printer::visit(const Enum& e) {
|
||||
|
@ -71,6 +71,9 @@ Primitive& TypeGraph::makeType<Primitive>(Primitive::Kind kind) {
|
||||
case Primitive::Kind::Void:
|
||||
static Primitive pVoid{kind};
|
||||
return pVoid;
|
||||
case Primitive::Kind::Incomplete:
|
||||
static Primitive pIncomplete{kind};
|
||||
return pIncomplete;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,6 +60,7 @@ std::string Primitive::name() const {
|
||||
case Kind::UIntPtr:
|
||||
return "uintptr_t";
|
||||
case Kind::Void:
|
||||
case Kind::Incomplete:
|
||||
return "void";
|
||||
}
|
||||
}
|
||||
@ -95,6 +96,7 @@ std::size_t Primitive::size() const {
|
||||
case Kind::UIntPtr:
|
||||
return sizeof(uintptr_t);
|
||||
case Kind::Void:
|
||||
case Kind::Incomplete:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -411,6 +411,8 @@ class Primitive : public Type {
|
||||
UIntPtr, // Really an alias, but useful to have as its own primitive
|
||||
|
||||
Void,
|
||||
Incomplete, // Behaves the same as Void, but alerts us that the type was
|
||||
// stubbed out due to incomplete DWARF
|
||||
};
|
||||
|
||||
explicit Primitive(Kind kind) : kind_(kind) {
|
||||
@ -428,6 +430,9 @@ class Primitive : public Type {
|
||||
virtual NodeId id() const override {
|
||||
return -1;
|
||||
}
|
||||
Kind kind() const {
|
||||
return kind_;
|
||||
}
|
||||
|
||||
private:
|
||||
Kind kind_;
|
||||
|
@ -49,6 +49,8 @@ Primitive::Kind getKind(std::string_view kindStr) {
|
||||
return Primitive::Kind::UIntPtr;
|
||||
if (kindStr == "void")
|
||||
return Primitive::Kind::Void;
|
||||
if (kindStr == "void (incomplete)")
|
||||
return Primitive::Kind::Incomplete;
|
||||
throw TypeGraphParserError{"Invalid Primitive::Kind: " +
|
||||
std::string{kindStr}};
|
||||
}
|
||||
|
@ -330,7 +330,7 @@ TEST_F(DrgnParserTest, PointerNoFollow) {
|
||||
TEST_F(DrgnParserTest, PointerIncomplete) {
|
||||
test("oid_test_case_pointers_incomplete_raw", R"(
|
||||
[0] Pointer
|
||||
Primitive: void
|
||||
Primitive: void (incomplete)
|
||||
)");
|
||||
}
|
||||
|
||||
|
@ -30,3 +30,15 @@ TEST(EnforceCompatibilityTest, TypesToStub) {
|
||||
[0] Class: EnumMap (size: 8)
|
||||
)");
|
||||
}
|
||||
|
||||
TEST(EnforceCompatibilityTest, VoidPointer) {
|
||||
test(EnforceCompatibility::createPass(), R"(
|
||||
[0] Class: MyClass (size: 8)
|
||||
Member: p (offset: 0)
|
||||
[1] Pointer
|
||||
Primitive: void (incomplete)
|
||||
)",
|
||||
R"(
|
||||
[0] Class: MyClass (size: 8)
|
||||
)");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user