[BOLT][DWARF] Fix handling .debug_str_offsets for type units (#75522)

There was an assumpiton that TUs and CUs share .debug_str_offsets
contribution. For ThinLTO builds it is not the case. Changed so that we
parse contributions for TUs also, and did some refactoring so that we
don't re-parse contributions that were not modified.
This commit is contained in:
Alexander Yermolovich
2023-12-14 17:27:21 -08:00
committed by GitHub
parent bd6a2452ae
commit bf2b035e58
8 changed files with 535 additions and 31 deletions

View File

@@ -851,35 +851,34 @@ std::string SimpleBinaryPatcher::patchBinary(StringRef BinaryContents) {
return BinaryContentsStr;
}
void DebugStrOffsetsWriter::initialize(
const DWARFSection &StrOffsetsSection,
const std::optional<StrOffsetsContributionDescriptor> Contr) {
void DebugStrOffsetsWriter::initialize(DWARFUnit &Unit) {
if (Unit.getVersion() < 5)
return;
const DWARFSection &StrOffsetsSection = Unit.getStringOffsetSection();
const std::optional<StrOffsetsContributionDescriptor> &Contr =
Unit.getStringOffsetsTableContribution();
if (!Contr)
return;
const uint8_t DwarfOffsetByteSize = Contr->getDwarfOffsetByteSize();
assert(DwarfOffsetByteSize == 4 &&
"Dwarf String Offsets Byte Size is not supported.");
uint32_t Index = 0;
StrOffsets.reserve(Contr->Size);
for (uint64_t Offset = 0; Offset < Contr->Size; Offset += DwarfOffsetByteSize)
IndexToAddressMap[Index++] = support::endian::read32le(
StrOffsetsSection.Data.data() + Contr->Base + Offset);
StrOffsets.push_back(support::endian::read32le(
StrOffsetsSection.Data.data() + Contr->Base + Offset));
}
void DebugStrOffsetsWriter::updateAddressMap(uint32_t Index, uint32_t Address) {
assert(IndexToAddressMap.count(Index) > 0 && "Index is not found.");
IndexToAddressMap[Index] = Address;
StrOffsetSectionWasModified = true;
}
void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
DIEBuilder &DIEBldr) {
if (IndexToAddressMap.empty())
return;
std::optional<AttrInfo> AttrVal =
findAttributeInfo(Unit.getUnitDIE(), dwarf::DW_AT_str_offsets_base);
assert(AttrVal && "DW_AT_str_offsets_base not present.");
if (!AttrVal)
return;
std::optional<uint64_t> Val = AttrVal->V.getAsSectionOffset();
assert(Val && "DW_AT_str_offsets_base Value not present.");
DIE &Die = *DIEBldr.getUnitDIEbyUnit(Unit);
@@ -888,11 +887,14 @@ void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
auto RetVal = ProcessedBaseOffsets.find(*Val);
// Handling re-use of str-offsets section.
if (RetVal == ProcessedBaseOffsets.end() || StrOffsetSectionWasModified) {
initialize(Unit);
// Update String Offsets that were modified.
for (const auto &Entry : IndexToAddressMap)
StrOffsets[Entry.first] = Entry.second;
// Writing out the header for each section.
support::endian::write(
*StrOffsetsStream,
static_cast<uint32_t>(IndexToAddressMap.size() * 4 + 4),
llvm::endianness::little);
support::endian::write(*StrOffsetsStream,
static_cast<uint32_t>(StrOffsets.size() * 4 + 4),
llvm::endianness::little);
support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(5),
llvm::endianness::little);
support::endian::write(*StrOffsetsStream, static_cast<uint16_t>(0),
@@ -904,8 +906,8 @@ void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
StrListBaseAttrInfo.getForm(),
DIEInteger(BaseOffset));
for (const auto &Entry : IndexToAddressMap)
support::endian::write(*StrOffsetsStream, Entry.second,
for (const uint32_t Offset : StrOffsets)
support::endian::write(*StrOffsetsStream, Offset,
llvm::endianness::little);
} else {
DIEBldr.replaceValue(&Die, dwarf::DW_AT_str_offsets_base,
@@ -915,6 +917,7 @@ void DebugStrOffsetsWriter::finalizeSection(DWARFUnit &Unit,
StrOffsetSectionWasModified = false;
IndexToAddressMap.clear();
StrOffsets.clear();
}
void DebugStrWriter::create() {