Skip to content

Commit 22628e5

Browse files
committed
[LLDB][NativePDB] Add non-overlapping fields in root struct
1 parent 9f9b8d5 commit 22628e5

File tree

2 files changed

+66
-2
lines changed

2 files changed

+66
-2
lines changed

lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,10 @@ void UdtRecordCompleter::Record::ConstructRecord() {
442442

443443
// The end offset to a vector of field/struct that ends at the offset.
444444
std::map<uint64_t, std::vector<Member *>> end_offset_map;
445+
auto is_last_end_offset = [&](auto it) {
446+
return it != end_offset_map.end() && ++it == end_offset_map.end();
447+
};
448+
445449
for (auto &pair : fields_map) {
446450
uint64_t offset = pair.first;
447451
auto &fields = pair.second;
@@ -463,7 +467,14 @@ void UdtRecordCompleter::Record::ConstructRecord() {
463467
if (iter->second.empty())
464468
continue;
465469
parent = iter->second.back();
466-
iter->second.pop_back();
470+
471+
// For structs, if the new fields come after the already added ones
472+
// without overlap, go back to the root struct.
473+
if (parent != &record && iter->first <= offset &&
474+
record.kind == Member::Struct && is_last_end_offset(iter))
475+
parent = &record;
476+
else
477+
iter->second.pop_back();
467478
}
468479
// If it's a field, then the field is inside a union, so we can safely
469480
// increase its size by converting it to a struct to hold multiple fields.

lldb/unittests/SymbolFile/NativePDB/UdtRecordCompleterTests.cpp

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ Member *AddField(Member *member, StringRef name, uint64_t byte_offset,
9999
std::make_unique<Member>(name, byte_offset * 8, byte_size * 8,
100100
clang::QualType(), lldb::eAccessPublic, 0);
101101
field->kind = kind;
102-
field->base_offset = base_offset;
102+
field->base_offset = base_offset * 8;
103103
member->fields.push_back(std::move(field));
104104
return member->fields.back().get();
105105
}
@@ -111,6 +111,9 @@ TEST_F(UdtRecordCompleterRecordTests, TestAnonymousUnionInStruct) {
111111
CollectMember("m2", 0, 4);
112112
CollectMember("m3", 0, 1);
113113
CollectMember("m4", 0, 8);
114+
CollectMember("m5", 8, 8);
115+
CollectMember("m6", 16, 4);
116+
CollectMember("m7", 16, 8);
114117
ConstructRecord();
115118

116119
// struct {
@@ -120,6 +123,11 @@ TEST_F(UdtRecordCompleterRecordTests, TestAnonymousUnionInStruct) {
120123
// m3;
121124
// m4;
122125
// };
126+
// m5;
127+
// union {
128+
// m6;
129+
// m7;
130+
// };
123131
// };
124132
Record record;
125133
record.start_offset = 0;
@@ -128,6 +136,10 @@ TEST_F(UdtRecordCompleterRecordTests, TestAnonymousUnionInStruct) {
128136
AddField(u, "m2", 0, 4, Member::Field);
129137
AddField(u, "m3", 0, 1, Member::Field);
130138
AddField(u, "m4", 0, 8, Member::Field);
139+
AddField(&record.record, "m5", 8, 8, Member::Field);
140+
Member *u2 = AddField(&record.record, "", 16, 0, Member::Union);
141+
AddField(u2, "m6", 16, 4, Member::Field);
142+
AddField(u2, "m7", 16, 8, Member::Field);
131143
EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));
132144
}
133145

@@ -243,3 +255,44 @@ TEST_F(UdtRecordCompleterRecordTests, TestNestedUnionStructInUnion) {
243255
AddField(s2, "m4", 2, 4, Member::Field);
244256
EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));
245257
}
258+
259+
TEST_F(UdtRecordCompleterRecordTests, TestNestedUnionStructInUnion2) {
260+
SetKind(Member::Kind::Union);
261+
CollectMember("m1", 0, 4);
262+
CollectMember("m2", 0, 2);
263+
CollectMember("m3", 0, 2);
264+
CollectMember("m4", 2, 4);
265+
CollectMember("m5", 6, 2);
266+
CollectMember("m6", 6, 2);
267+
CollectMember("m7", 8, 2);
268+
ConstructRecord();
269+
270+
// union {
271+
// m1;
272+
// m2;
273+
// struct {
274+
// m3;
275+
// m4;
276+
// union {
277+
// m5;
278+
// struct {
279+
// m6;
280+
// m7;
281+
// };
282+
// };
283+
// };
284+
// };
285+
Record record;
286+
record.start_offset = 0;
287+
AddField(&record.record, "m1", 0, 4, Member::Field);
288+
AddField(&record.record, "m2", 0, 2, Member::Field);
289+
Member *s1 = AddField(&record.record, "", 0, 0, Member::Struct);
290+
AddField(s1, "m3", 0, 2, Member::Field);
291+
AddField(s1, "m4", 2, 4, Member::Field);
292+
Member *u1 = AddField(s1, "", 6, 0, Member::Union);
293+
AddField(u1, "m5", 6, 2, Member::Field);
294+
Member *s2 = AddField(u1, "", 0, 0, Member::Struct, 6);
295+
AddField(s2, "m6", 6, 2, Member::Field);
296+
AddField(s2, "m7", 8, 2, Member::Field);
297+
EXPECT_EQ(WrappedRecord(this->record), WrappedRecord(record));
298+
}

0 commit comments

Comments
 (0)