Skip to content

Commit c9e8e91

Browse files
authored
[BOLT][DWARF] Fix out of order rangelists/loclists (#81645)
GCC can generate rangelists/loclists that are out of order. Fixed so that we don't assert, and instead generate partially optimized list. Through most code paths we do sort rnglists/loclists, but not for loclist for a path where BOLT does not modify a function. Although it's nice to have lists sorted, this implementation shouldn't rely on it. This also fixes an issue if we partially capture a list we would write out *end_of_list in helper function. So tools won't see the rest of the addresses being written out.
1 parent 6297479 commit c9e8e91

File tree

2 files changed

+504
-26
lines changed

2 files changed

+504
-26
lines changed

bolt/lib/Core/DebugData.cpp

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,7 @@ template <typename DebugVector, typename ListEntry, typename DebugAddressEntry>
230230
static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,
231231
DebugAddrWriter &AddrWriter, DWARFUnit &CU,
232232
uint32_t &Index, const ListEntry BaseAddressx,
233-
const ListEntry OffsetPair, const ListEntry EndOfList,
233+
const ListEntry OffsetPair,
234234
const std::function<void(uint32_t)> &Func) {
235235
if (Entries.size() < 2)
236236
return false;
@@ -241,7 +241,9 @@ static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,
241241
const DebugAddressEntry &Entry = Entries[Index];
242242
if (Entry.LowPC == 0)
243243
break;
244-
assert(Base <= Entry.LowPC && "Entry base is higher than low PC");
244+
// In case rnglists or loclists are not sorted.
245+
if (Base > Entry.LowPC)
246+
break;
245247
uint32_t StartOffset = Entry.LowPC - Base;
246248
uint32_t EndOffset = Entry.HighPC - Base;
247249
if (encodeULEB128(EndOffset, TempBuffer) > 2)
@@ -266,8 +268,6 @@ static bool emitWithBase(raw_ostream &OS, const DebugVector &Entries,
266268
encodeULEB128(OffsetEntry.EndOffset, OS);
267269
Func(OffsetEntry.Index);
268270
}
269-
support::endian::write(OS, static_cast<uint8_t>(EndOfList),
270-
llvm::endianness::little);
271271
return true;
272272
}
273273

@@ -276,19 +276,17 @@ DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
276276
std::lock_guard<std::mutex> Lock(WriterMutex);
277277

278278
RangeEntries.push_back(CurrentOffset);
279-
bool WrittenStartxLength = false;
280279
std::sort(
281280
Ranges.begin(), Ranges.end(),
282281
[](const DebugAddressRange &R1, const DebugAddressRange &R2) -> bool {
283282
return R1.LowPC < R2.LowPC;
284283
});
285284
for (unsigned I = 0; I < Ranges.size();) {
286-
WrittenStartxLength = false;
287285
if (emitWithBase<DebugAddressRangesVector, dwarf::RnglistEntries,
288-
DebugAddressRange>(
289-
*CUBodyStream, Ranges, *AddrWriter, *CU, I,
290-
dwarf::DW_RLE_base_addressx, dwarf::DW_RLE_offset_pair,
291-
dwarf::DW_RLE_end_of_list, [](uint32_t Index) -> void {}))
286+
DebugAddressRange>(*CUBodyStream, Ranges, *AddrWriter, *CU,
287+
I, dwarf::DW_RLE_base_addressx,
288+
dwarf::DW_RLE_offset_pair,
289+
[](uint32_t Index) -> void {}))
292290
continue;
293291

294292
const DebugAddressRange &Range = Ranges[I];
@@ -299,12 +297,11 @@ DebugRangeListsSectionWriter::addRanges(DebugAddressRangesVector &Ranges) {
299297
encodeULEB128(Index, *CUBodyStream);
300298
encodeULEB128(Range.HighPC - Range.LowPC, *CUBodyStream);
301299
++I;
302-
WrittenStartxLength = true;
303300
}
304-
if (WrittenStartxLength)
305-
support::endian::write(*CUBodyStream,
306-
static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),
307-
llvm::endianness::little);
301+
302+
support::endian::write(*CUBodyStream,
303+
static_cast<uint8_t>(dwarf::DW_RLE_end_of_list),
304+
llvm::endianness::little);
308305
CurrentOffset = CUBodyBuffer->size();
309306
return RangeEntries.size() - 1;
310307
}
@@ -688,20 +685,18 @@ static void writeDWARF5LocList(uint32_t &NumberOfEntries, DIEValue &AttrInfo,
688685
}
689686

690687
std::vector<uint64_t> OffsetsArray;
691-
bool WrittenStartxLength = false;
692688
auto writeExpression = [&](uint32_t Index) -> void {
693689
const DebugLocationEntry &Entry = LocList[Index];
694690
encodeULEB128(Entry.Expr.size(), LocBodyStream);
695691
LocBodyStream << StringRef(
696692
reinterpret_cast<const char *>(Entry.Expr.data()), Entry.Expr.size());
697693
};
698694
for (unsigned I = 0; I < LocList.size();) {
699-
WrittenStartxLength = false;
700695
if (emitWithBase<DebugLocationsVector, dwarf::LoclistEntries,
701-
DebugLocationEntry>(
702-
LocBodyStream, LocList, AddrWriter, CU, I,
703-
dwarf::DW_LLE_base_addressx, dwarf::DW_LLE_offset_pair,
704-
dwarf::DW_LLE_end_of_list, writeExpression))
696+
DebugLocationEntry>(LocBodyStream, LocList, AddrWriter, CU,
697+
I, dwarf::DW_LLE_base_addressx,
698+
dwarf::DW_LLE_offset_pair,
699+
writeExpression))
705700
continue;
706701

707702
const DebugLocationEntry &Entry = LocList[I];
@@ -713,13 +708,11 @@ static void writeDWARF5LocList(uint32_t &NumberOfEntries, DIEValue &AttrInfo,
713708
encodeULEB128(Entry.HighPC - Entry.LowPC, LocBodyStream);
714709
writeExpression(I);
715710
++I;
716-
WrittenStartxLength = true;
717711
}
718712

719-
if (WrittenStartxLength)
720-
support::endian::write(LocBodyStream,
721-
static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
722-
llvm::endianness::little);
713+
support::endian::write(LocBodyStream,
714+
static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
715+
llvm::endianness::little);
723716
}
724717

725718
void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die,

0 commit comments

Comments
 (0)