[BOLT][DWARF] Fix abbrev offsets for type units

Summary:
When rewriting .debug_abbrev section, update abbrev offsets for type
units in addition to compile units.

Reuse abbreviation entries if they were shared by multiple compile/type
units.

(cherry picked from FBD31262326)
This commit is contained in:
Maksim Panchenko 2021-09-28 23:30:06 -07:00
parent 47455e98b3
commit e3b901aaee
3 changed files with 41 additions and 26 deletions

View File

@ -164,7 +164,6 @@ static bool isHighPcFormEightBytes(dwarf::Form DwarfForm) {
void DWARFRewriter::updateDebugInfo() {
ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(".debug_info");
if (!DebugInfo)
return;
@ -841,9 +840,9 @@ void DWARFRewriter::finalizeDebugSections(
AbbrevSectionContents->size());
// Update abbreviation offsets if they were changed.
for (auto &CU : BC.DwCtx->compile_units()) {
if (CU->isDWOUnit())
continue;
SimpleBinaryPatcher *DebugTypesPatcher = nullptr;
for (auto &CU : BC.DwCtx->normal_units()) {
assert(!CU->isDWOUnit());
const uint64_t NewAbbrevOffset =
AbbrevWriter->getAbbreviationsOffsetForUnit(*CU);
@ -854,8 +853,22 @@ void DWARFRewriter::finalizeDebugSections(
// unit_length - 4 bytes
// version - 2 bytes
// So + 6 to patch debug_abbrev_offset
DebugInfoPatcher.addLE32Patch(CU->getOffset() + 6,
static_cast<uint32_t>(NewAbbrevOffset));
constexpr uint64_t AbbrevFieldOffset = 6;
if (!CU->isTypeUnit()) {
DebugInfoPatcher.addLE32Patch(CU->getOffset() + AbbrevFieldOffset,
static_cast<uint32_t>(NewAbbrevOffset));
continue;
}
if (!DebugTypesPatcher) {
ErrorOr<BinarySection &> DebugTypes =
BC.getUniqueSectionByName(".debug_types");
DebugTypes->registerPatcher(std::make_unique<SimpleBinaryPatcher>());
DebugTypesPatcher =
static_cast<SimpleBinaryPatcher *>(DebugTypes->getPatcher());
}
DebugTypesPatcher->addLE32Patch(CU->getOffset() + AbbrevFieldOffset,
static_cast<uint32_t>(NewAbbrevOffset));
}
}

View File

@ -409,19 +409,20 @@ void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
if (!Abbrevs)
return;
uint64_t CUIndex = Unit.getOffset();
if (CUAbbrevData.find(CUIndex) == CUAbbrevData.end()) {
std::lock_guard<std::mutex> Lock(WriterMutex);
AbbrevData &Data = CUAbbrevData[CUIndex];
Data.Buffer = std::make_unique<DebugBufferVector>();
Data.Stream = std::make_unique<raw_svector_ostream>(*Data.Buffer);
}
// Multiple units may share the same abbreviations. Only add abbreviations
// for the first unit and reuse them.
const uint64_t AbbrevOffset = Unit.getAbbreviationsOffset();
if (CUAbbrevData.find(AbbrevOffset) != CUAbbrevData.end())
return;
std::lock_guard<std::mutex> Lock(WriterMutex);
AbbrevData &UnitData = CUAbbrevData[AbbrevOffset];
UnitData.Buffer = std::make_unique<DebugBufferVector>();
UnitData.Stream = std::make_unique<raw_svector_ostream>(*UnitData.Buffer);
const auto &UnitPatches = Patches[&Unit];
raw_svector_ostream &OS = *CUAbbrevData[CUIndex].Stream.get();
raw_svector_ostream &OS = *UnitData.Stream.get();
// Take a fast path if there are no patches to apply. Simply copy the original
// contents.
@ -502,20 +503,20 @@ std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
// Pre-calculate the total size of abbrev section.
uint64_t Size = 0;
for (const auto &KV : CUAbbrevData) {
const AbbrevData &Data = KV.second;
Size += Data.Buffer->size();
const AbbrevData &UnitData = KV.second;
Size += UnitData.Buffer->size();
}
ReturnBuffer.reserve(Size);
uint64_t Pos = 0;
for (auto &KV : CUAbbrevData) {
AbbrevData &Data = KV.second;
ReturnBuffer.append(*Data.Buffer);
Data.Offset = Pos;
Pos += Data.Buffer->size();
AbbrevData &UnitData = KV.second;
ReturnBuffer.append(*UnitData.Buffer);
UnitData.Offset = Pos;
Pos += UnitData.Buffer->size();
Data.Buffer.reset();
Data.Stream.reset();
UnitData.Buffer.reset();
UnitData.Stream.reset();
}
return std::make_unique<DebugBufferVector>(ReturnBuffer);

View File

@ -443,7 +443,7 @@ class DebugAbbrevWriter {
std::unique_ptr<DebugBufferVector> Buffer;
std::unique_ptr<raw_svector_ostream> Stream;
};
/// Map CU offset to abbreviations data.
/// Map original CU abbrev offset to abbreviations data.
std::map<uint64_t, AbbrevData> CUAbbrevData;
/// Attributes Substitution information.
@ -490,9 +490,10 @@ public:
/// Return an offset in the finalized section corresponding to CU \p Unit.
uint64_t getAbbreviationsOffsetForUnit(const DWARFUnit &Unit) {
assert(CUAbbrevData.find(Unit.getOffset()) != CUAbbrevData.end() &&
assert(CUAbbrevData.find(Unit.getAbbreviationsOffset()) !=
CUAbbrevData.end() &&
"no abbrev data found for unit");
return CUAbbrevData[Unit.getOffset()].Offset;
return CUAbbrevData[Unit.getAbbreviationsOffset()].Offset;
}
};