Skip to content

Commit

Permalink
C++ Multiple Inheritance
Browse files Browse the repository at this point in the history
  • Loading branch information
ttreyer committed Mar 28, 2024
1 parent 960ec3b commit 651b120
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
24 changes: 12 additions & 12 deletions src/dwarf_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,30 +196,30 @@ SizedType Dwarf::get_stype(const std::string &type_name)
return CreateNone();
}

void Dwarf::resolve_fields(std::shared_ptr<Struct> str, lldb::SBType type)
void Dwarf::resolve_fields(std::shared_ptr<Struct> &str, lldb::SBType type, size_t offset)
{
if (!type.IsValid())
return;

for (uint32_t i = 0; i < type.GetNumberOfVirtualBaseClasses(); i++) {
auto parent = type.GetVirtualBaseClassAtIndex(i);
resolve_fields(str, parent.GetType());
}

for (uint32_t i = 0; i < type.GetNumberOfDirectBaseClasses(); i++) {
auto parent = type.GetDirectBaseClassAtIndex(i);
resolve_fields(str, parent.GetType());
}

for (uint32_t i = 0; i < type.GetNumberOfFields(); i++) {
auto field = type.GetFieldAtIndex(i);
auto field_type = get_stype(field.GetType());
str->AddField(field.GetName() ?: "",
get_stype(field.GetType()),
field.GetOffsetInBytes(),
offset + field.GetOffsetInBytes(),
resolve_bitfield(field),
false);
}

for (uint32_t i = 0; i < type.GetNumberOfVirtualBaseClasses(); i++) {
auto parent = type.GetVirtualBaseClassAtIndex(i);
resolve_fields(str, parent.GetType(), parent.GetOffsetInBytes());
}

for (uint32_t i = 0; i < type.GetNumberOfDirectBaseClasses(); i++) {
auto parent = type.GetDirectBaseClassAtIndex(i);
resolve_fields(str, parent.GetType(), parent.GetOffsetInBytes());
}
}

void Dwarf::resolve_fields(const SizedType &type)
Expand Down
2 changes: 1 addition & 1 deletion src/dwarf_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class Dwarf {

std::string get_type_name(lldb::SBType type);
SizedType get_stype(lldb::SBType type, bool resolve_structs = true);
void resolve_fields(std::shared_ptr<Struct> str, lldb::SBType type);
void resolve_fields(std::shared_ptr<Struct> &str, lldb::SBType type, size_t offset = 0);
std::optional<Bitfield> resolve_bitfield(lldb::SBTypeMember field);

BPFtrace *bpftrace_;
Expand Down
40 changes: 40 additions & 0 deletions tests/data/data_source_cxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,28 @@ class LittleChild : public Child {
LittleChild(int a, int b, int c, int d, int e, int f, int g) : Child(a, b, c, d, e, f), g(g) {}
};

struct Top {
int x;
};

struct Left : public Top {
int y;
};

struct Right : public Top {
int z;
};

struct Bottom : public Left, public Right {
int w;
};

struct Multi : public Parent, public Top {
int abc;

Multi(int a, int b, int c, int d, int e) : Parent{a, b, c, d}, Top{e}, abc{e + 1} {}
};

int func_1(Child &c, Parent &p __attribute__((unused)))
{
return dynamic_cast<Parent&>(c).d;
Expand All @@ -36,6 +58,11 @@ int func_2(LittleChild &lc)
return dynamic_cast<Parent&>(lc).d;
}

int func_3(Multi &m, Bottom &b __attribute__((unused)))
{
return m.abc;
}

int main(void)
{
Parent p{1, 2, 3, 4};
Expand All @@ -45,5 +72,18 @@ int main(void)
LittleChild lc{1, 2, 3, 4, 5, 6, 7};
func_2(lc);

Check warning

Code scanning / CodeQL

Expression has no effect Warning

This expression has no effect (because
func_2
has no external side effects).

Multi m{1, 2, 3, 4, 5};
Bottom b{
{ // Left
{1}, // Left's Top
2 // Left's y
}, { // Right
{3}, // Right's Top
4 // Right's z
},
5 // Bottom's w
};
func_3(m, b);

Check warning

Code scanning / CodeQL

Expression has no effect Warning

This expression has no effect (because
func_3
has no external side effects).

return 0;
}
26 changes: 26 additions & 0 deletions tests/field_analyser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,32 @@ TEST_F(field_analyser_dwarf, parse_inheritance_chain)
CheckLittleChildFields(cls);
}

TEST_F(field_analyser_dwarf, parse_inheritance_multi)
{
BPFtrace bpftrace;
std::string uprobe = "uprobe:" + std::string(cxx_bin_);
test(bpftrace, uprobe + ":cpp:func_3 { $x = args.m->abc; }", 0);

ASSERT_TRUE(bpftrace.structs.Has("struct Multi"));
auto cls = bpftrace.structs.Lookup("struct Multi").lock();

ASSERT_TRUE(cls->HasFields());
ASSERT_EQ(cls->fields.size(), 6);
ASSERT_EQ(cls->size, 24);

CheckParentFields(cls);

EXPECT_TRUE(cls->HasField("x"));
EXPECT_TRUE(cls->GetField("x").type.IsIntTy());
EXPECT_EQ(cls->GetField("x").type.GetSize(), 4);
EXPECT_EQ(cls->GetField("x").offset, 16);

EXPECT_TRUE(cls->HasField("abc"));
EXPECT_TRUE(cls->GetField("abc").type.IsIntTy());
EXPECT_EQ(cls->GetField("abc").type.GetSize(), 4);
EXPECT_EQ(cls->GetField("abc").offset, 20);
}

TEST_F(field_analyser_dwarf, parse_struct_anonymous_fields)
{
GTEST_SKIP() << "Anonymous fields not supported #3084";
Expand Down

0 comments on commit 651b120

Please sign in to comment.