forked from OSchip/llvm-project
[BOLT][DWARF] Write new .debug_abbrev sections
Summary: Instead of patching the original .debug_abbrev section contents, generate new section data based on parsed compilation unit abbreviations. This eliminates the dependency on the LLVM extension that records abbreviation attribute offsets while parsing .debug_abbrev contents. The output with this patch should stay the same (NFC). (cherry picked from FBD31133611)
This commit is contained in:
parent
e1da1539e3
commit
4d5cd1bf82
|
@ -163,17 +163,11 @@ static bool isHighPcFormEightBytes(dwarf::Form DwarfForm) {
|
|||
}
|
||||
|
||||
void DWARFRewriter::updateDebugInfo() {
|
||||
ErrorOr<BinarySection &> DebugAbbrev =
|
||||
BC.getUniqueSectionByName(".debug_abbrev");
|
||||
ErrorOr<BinarySection &> DebugInfo = BC.getUniqueSectionByName(".debug_info");
|
||||
|
||||
if (!DebugAbbrev || !DebugInfo)
|
||||
if (!DebugInfo)
|
||||
return;
|
||||
|
||||
DebugAbbrev->registerPatcher(std::make_unique<DebugAbbrevPatcher>());
|
||||
auto *AbbrevPatcher =
|
||||
static_cast<DebugAbbrevPatcher *>(DebugAbbrev->getPatcher());
|
||||
|
||||
DebugInfo->registerPatcher(std::make_unique<SimpleBinaryPatcher>());
|
||||
auto *DebugInfoPatcher =
|
||||
static_cast<SimpleBinaryPatcher *>(DebugInfo->getPatcher());
|
||||
|
@ -181,6 +175,7 @@ void DWARFRewriter::updateDebugInfo() {
|
|||
ARangesSectionWriter = std::make_unique<DebugARangesSectionWriter>();
|
||||
RangesSectionWriter = std::make_unique<DebugRangesSectionWriter>();
|
||||
StrWriter = std::make_unique<DebugStrWriter>(&BC);
|
||||
AbbrevWriter = std::make_unique<DebugAbbrevWriter>();
|
||||
|
||||
AddrWriter = std::make_unique<DebugAddrWriter>(&BC);
|
||||
DebugLoclistWriter::setAddressWriter(AddrWriter.get());
|
||||
|
@ -223,7 +218,6 @@ void DWARFRewriter::updateDebugInfo() {
|
|||
}
|
||||
};
|
||||
|
||||
uint32_t AbbrevOffsetModifier = 0;
|
||||
// Case 1) Range_base found: patch .debug_info
|
||||
// Case 2) Range_base not found, but Ranges will be used: patch
|
||||
// .debug_info/.debug_abbrev
|
||||
|
@ -234,7 +228,6 @@ void DWARFRewriter::updateDebugInfo() {
|
|||
findAttributeInfo(DIE, dwarf::DW_AT_GNU_ranges_base);
|
||||
const bool NeedToPatch = AttrInfoVal.hasValue();
|
||||
uint64_t AttrOffset = NeedToPatch ? AttrInfoVal->Offset : 0;
|
||||
const uint32_t PrevAbbrevOffsetModifier = AbbrevOffsetModifier;
|
||||
// Case where Skeleton CU doesn't have DW_AT_GNU_ranges_base
|
||||
if (!NeedToPatch && WasRangeBaseUsed) {
|
||||
const DWARFAbbreviationDeclaration *AbbreviationDecl =
|
||||
|
@ -252,15 +245,15 @@ void DWARFRewriter::updateDebugInfo() {
|
|||
Optional<DWARFFormValue> ValHighPC = DIE.find(dwarf::DW_AT_high_pc);
|
||||
uint32_t NumBytesToFill = 7;
|
||||
|
||||
AbbrevPatcher->addAttributePatch(AbbreviationDecl, dwarf::DW_AT_low_pc,
|
||||
dwarf::DW_AT_GNU_ranges_base,
|
||||
dwarf::DW_FORM_indirect);
|
||||
AbbrevWriter->addAttributePatch(
|
||||
Unit, AbbreviationDecl, dwarf::DW_AT_low_pc,
|
||||
dwarf::DW_AT_GNU_ranges_base, dwarf::DW_FORM_indirect);
|
||||
// Bolt converts DW_AT_low_pc/DW_AT_high_pc to DW_AT_low_pc/DW_at_ranges
|
||||
// DW_AT_high_pc can be 4 or 8 bytes. If it's 8 bytes need to use first
|
||||
// 4 bytes.
|
||||
if (ValHighPC && isHighPcFormEightBytes(ValHighPC->getForm()))
|
||||
if (ValHighPC && isHighPcFormEightBytes(ValHighPC->getForm())) {
|
||||
NumBytesToFill += 4;
|
||||
|
||||
}
|
||||
LLVM_DEBUG(if (opts::DebugSkeletonCu) dbgs()
|
||||
<< "AttrOffset: " << Twine::utohexstr(AttrOffset) << "\n"
|
||||
<< "Die Offset: " << Twine::utohexstr(DIE.getOffset())
|
||||
|
@ -272,56 +265,49 @@ void DWARFRewriter::updateDebugInfo() {
|
|||
DebugInfoPatcher->addUDataPatch(AttrOffset, dwarf::DW_FORM_udata, 1);
|
||||
DebugInfoPatcher->addUDataPatch(AttrOffset + 1, RangeBase,
|
||||
NumBytesToFill);
|
||||
|
||||
// 1 Byte for DW_AT_GNU_ranges_base (since it's 2 bytes vs DW_AT_low_pc)
|
||||
AbbrevOffsetModifier += 1;
|
||||
}
|
||||
if (NeedToPatch)
|
||||
DebugInfoPatcher->addLE32Patch(AttrOffset,
|
||||
static_cast<uint32_t>(RangeBase));
|
||||
|
||||
// DWARF4
|
||||
// unit_length - 4 bytes
|
||||
// version - 2 bytes
|
||||
// So + 6 to patch debug_abbrev_offset
|
||||
if (PrevAbbrevOffsetModifier)
|
||||
DebugInfoPatcher->addLE32Patch(
|
||||
Unit.getOffset() + 6, static_cast<uint32_t>(Unit.getAbbrOffset()) +
|
||||
PrevAbbrevOffsetModifier);
|
||||
};
|
||||
|
||||
auto processUnitDIE = [&](size_t CUIndex, DWARFUnit *Unit) {
|
||||
uint64_t RangeBase = RangesSectionWriter->getSectionOffset();
|
||||
updateUnitDebugInfo(CUIndex, *Unit, *DebugInfoPatcher, *AbbrevPatcher);
|
||||
updateUnitDebugInfo(CUIndex, *Unit, *DebugInfoPatcher, *AbbrevWriter);
|
||||
|
||||
// Check if the unit is a skeleton and we need more updates for the CU and
|
||||
// its matching split CU.
|
||||
Optional<DWARFUnit *> SplitCU;
|
||||
llvm::Optional<uint64_t> DWOId = Unit->getDWOId();
|
||||
if (!DWOId)
|
||||
return;
|
||||
if (DWOId)
|
||||
SplitCU = BC.getDWOCU(*DWOId);
|
||||
|
||||
// Skipping CUs that failed to load.
|
||||
Optional<DWARFUnit *> SplitCU = BC.getDWOCU(*DWOId);
|
||||
if (!SplitCU)
|
||||
return;
|
||||
if (SplitCU) {
|
||||
updateDWONameCompDir(*Unit);
|
||||
|
||||
updateDWONameCompDir(*Unit);
|
||||
// Assuming there is unique DWOID per binary. i.e. two or more CUs don't
|
||||
// have same DWO ID.
|
||||
assert(LocListWritersByCU.count(*DWOId) == 0 &&
|
||||
"LocList writer for DWO unit already exists.");
|
||||
LocListWritersByCU[*DWOId] =
|
||||
std::make_unique<DebugLoclistWriter>(&BC, *DWOId);
|
||||
SimpleBinaryPatcher *DwoDebugInfoPatcher =
|
||||
getBinaryDWODebugInfoPatcher(*DWOId);
|
||||
DwoDebugInfoPatcher->setRangeBase(RangeBase);
|
||||
DebugAbbrevWriter *DWOAbbrevWriter = getBinaryDWOAbbrevWriter(*DWOId);
|
||||
updateUnitDebugInfo(*DWOId, *(*SplitCU), *DwoDebugInfoPatcher,
|
||||
*DWOAbbrevWriter);
|
||||
DWOAbbrevWriter->addUnitAbbreviations(*(*SplitCU));
|
||||
static_cast<DebugLoclistWriter *>(LocListWritersByCU[*DWOId].get())
|
||||
->finalizePatches();
|
||||
updateRangeBase(*Unit, RangeBase,
|
||||
DwoDebugInfoPatcher->getWasRangBasedUsed());
|
||||
}
|
||||
|
||||
// Assuming there is unique DWOID per binary. i.e. two or more CUs don't
|
||||
// have same DWO ID.
|
||||
assert(LocListWritersByCU.count(*DWOId) == 0 &&
|
||||
"LocList writer for DWO unit already exists.");
|
||||
LocListWritersByCU[*DWOId] =
|
||||
std::make_unique<DebugLoclistWriter>(&BC, *DWOId);
|
||||
SimpleBinaryPatcher *DwoDebugInfoPatcher =
|
||||
getBinaryDWODebugInfoPatcher(*DWOId);
|
||||
DwoDebugInfoPatcher->setRangeBase(RangeBase);
|
||||
updateUnitDebugInfo(*DWOId, *(*SplitCU), *DwoDebugInfoPatcher,
|
||||
*getBinaryDWOAbbrevPatcher(*DWOId));
|
||||
static_cast<DebugLoclistWriter *>(LocListWritersByCU[*DWOId].get())
|
||||
->finalizePatches();
|
||||
updateRangeBase(*Unit, RangeBase,
|
||||
DwoDebugInfoPatcher->getWasRangBasedUsed());
|
||||
// Add abbreviations for the main unit. Note: the action is delayed until
|
||||
// after updateRangeBase() call.
|
||||
AbbrevWriter->addUnitAbbreviations(*Unit);
|
||||
};
|
||||
|
||||
if (opts::NoThreads || opts::DeterministicDebugInfo) {
|
||||
|
@ -354,7 +340,7 @@ void DWARFRewriter::updateDebugInfo() {
|
|||
|
||||
void DWARFRewriter::updateUnitDebugInfo(uint64_t CUIndex, DWARFUnit &Unit,
|
||||
SimpleBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevPatcher &AbbrevPatcher) {
|
||||
DebugAbbrevWriter &AbbrevWriter) {
|
||||
// Cache debug ranges so that the offset for identical ranges could be reused.
|
||||
std::map<DebugAddressRangesVector, uint64_t> CachedRanges;
|
||||
|
||||
|
@ -398,7 +384,7 @@ void DWARFRewriter::updateUnitDebugInfo(uint64_t CUIndex, DWARFUnit &Unit,
|
|||
ARangesSectionWriter->addCURanges(Unit.getOffset(),
|
||||
std::move(OutputRanges));
|
||||
updateDWARFObjectAddressRanges(DIE, RangesSectionOffset, DebugInfoPatcher,
|
||||
AbbrevPatcher);
|
||||
AbbrevWriter);
|
||||
break;
|
||||
}
|
||||
case dwarf::DW_TAG_subprogram: {
|
||||
|
@ -433,7 +419,7 @@ void DWARFRewriter::updateUnitDebugInfo(uint64_t CUIndex, DWARFUnit &Unit,
|
|||
if (UsesRanges) {
|
||||
updateDWARFObjectAddressRanges(
|
||||
DIE, RangesSectionWriter->addRanges(FunctionRanges),
|
||||
DebugInfoPatcher, AbbrevPatcher);
|
||||
DebugInfoPatcher, AbbrevWriter);
|
||||
} else {
|
||||
// Delay conversion of [LowPC, HighPC) into DW_AT_ranges if possible.
|
||||
const DWARFAbbreviationDeclaration *Abbrev =
|
||||
|
@ -445,7 +431,7 @@ void DWARFRewriter::updateUnitDebugInfo(uint64_t CUIndex, DWARFUnit &Unit,
|
|||
std::unique_lock<std::shared_timed_mutex> Lock(CriticalSectionMutex);
|
||||
|
||||
if (FunctionRanges.size() > 1) {
|
||||
convertPending(Abbrev, DebugInfoPatcher, AbbrevPatcher);
|
||||
convertPending(Unit, Abbrev, DebugInfoPatcher, AbbrevWriter);
|
||||
// Exit critical section early.
|
||||
Lock.unlock();
|
||||
convertToRanges(DIE, FunctionRanges, DebugInfoPatcher);
|
||||
|
@ -486,7 +472,7 @@ void DWARFRewriter::updateUnitDebugInfo(uint64_t CUIndex, DWARFUnit &Unit,
|
|||
consumeError(RangesOrError.takeError());
|
||||
}
|
||||
updateDWARFObjectAddressRanges(DIE, RangesSectionOffset, DebugInfoPatcher,
|
||||
AbbrevPatcher);
|
||||
AbbrevWriter);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
|
@ -662,7 +648,7 @@ void DWARFRewriter::updateUnitDebugInfo(uint64_t CUIndex, DWARFUnit &Unit,
|
|||
|
||||
void DWARFRewriter::updateDWARFObjectAddressRanges(
|
||||
const DWARFDie DIE, uint64_t DebugRangesOffset,
|
||||
SimpleBinaryPatcher &DebugInfoPatcher, DebugAbbrevPatcher &AbbrevPatcher) {
|
||||
SimpleBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter) {
|
||||
|
||||
// Some objects don't have an associated DIE and cannot be updated (such as
|
||||
// compiler-generated functions).
|
||||
|
@ -704,7 +690,7 @@ void DWARFRewriter::updateDWARFObjectAddressRanges(
|
|||
// large size.
|
||||
if (AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_low_pc) &&
|
||||
AbbreviationDecl->findAttributeIndex(dwarf::DW_AT_high_pc)) {
|
||||
convertToRanges(AbbreviationDecl, AbbrevPatcher);
|
||||
convertToRanges(*DIE.getDwarfUnit(), AbbreviationDecl, AbbrevWriter);
|
||||
convertToRanges(DIE, DebugRangesOffset, DebugInfoPatcher);
|
||||
} else {
|
||||
if (opts::Verbosity >= 1) {
|
||||
|
@ -862,17 +848,41 @@ void DWARFRewriter::finalizeDebugSections(
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<RangesBufferVector> RangesSectionContents =
|
||||
std::unique_ptr<DebugBufferVector> RangesSectionContents =
|
||||
RangesSectionWriter->finalize();
|
||||
BC.registerOrUpdateNoteSection(".debug_ranges",
|
||||
copyByteArray(*RangesSectionContents),
|
||||
RangesSectionContents->size());
|
||||
copyByteArray(*RangesSectionContents),
|
||||
RangesSectionContents->size());
|
||||
|
||||
std::unique_ptr<LocBufferVector> LocationListSectionContents =
|
||||
std::unique_ptr<DebugBufferVector> LocationListSectionContents =
|
||||
makeFinalLocListsSection(DebugInfoPatcher);
|
||||
BC.registerOrUpdateNoteSection(".debug_loc",
|
||||
copyByteArray(*LocationListSectionContents),
|
||||
LocationListSectionContents->size());
|
||||
copyByteArray(*LocationListSectionContents),
|
||||
LocationListSectionContents->size());
|
||||
|
||||
std::unique_ptr<DebugBufferVector> AbbrevSectionContents =
|
||||
AbbrevWriter->finalize();
|
||||
BC.registerOrUpdateNoteSection(".debug_abbrev",
|
||||
copyByteArray(*AbbrevSectionContents),
|
||||
AbbrevSectionContents->size());
|
||||
|
||||
// Update abbreviation offsets if they were changed.
|
||||
for (auto &CU : BC.DwCtx->compile_units()) {
|
||||
if (CU->isDWOUnit())
|
||||
continue;
|
||||
|
||||
const uint64_t NewAbbrevOffset =
|
||||
AbbrevWriter->getAbbreviationsOffsetForUnit(*CU);
|
||||
if (CU->getAbbreviationsOffset() == NewAbbrevOffset)
|
||||
continue;
|
||||
|
||||
// DWARFv4
|
||||
// unit_length - 4 bytes
|
||||
// version - 2 bytes
|
||||
// So + 6 to patch debug_abbrev_offset
|
||||
DebugInfoPatcher.addLE32Patch(CU->getOffset() + 6,
|
||||
static_cast<uint32_t>(NewAbbrevOffset));
|
||||
}
|
||||
}
|
||||
|
||||
// Creates all the data structures necessary for creating MCStreamer.
|
||||
|
@ -915,13 +925,13 @@ StringRef getSectionName(const SectionRef &Section) {
|
|||
}
|
||||
|
||||
// Exctracts an appropriate slice if input is DWP.
|
||||
// Applies patches to debug and its abbrev section.
|
||||
// Applies patches or overwrites the section.
|
||||
Optional<StringRef>
|
||||
patchDebugData(std::string &Storage, const SectionRef &Section,
|
||||
const StringMap<KnownSectionsEntry> &KnownSections,
|
||||
MCStreamer &Streamer, DWARFRewriter &Writer,
|
||||
const DWARFUnitIndex::Entry *DWOEntry, uint64_t DWOId,
|
||||
std::unique_ptr<LocBufferVector> &LocVectorOut) {
|
||||
updateDebugData(std::string &Storage, const SectionRef &Section,
|
||||
const StringMap<KnownSectionsEntry> &KnownSections,
|
||||
MCStreamer &Streamer, DWARFRewriter &Writer,
|
||||
const DWARFUnitIndex::Entry *DWOEntry, uint64_t DWOId,
|
||||
std::unique_ptr<DebugBufferVector> &OutputBuffer) {
|
||||
auto applyPatch = [&](BinaryPatcher *Patcher, StringRef Data,
|
||||
uint32_t Offset) -> StringRef {
|
||||
Storage = Data.str();
|
||||
|
@ -973,19 +983,22 @@ patchDebugData(std::string &Storage, const SectionRef &Section,
|
|||
DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);
|
||||
}
|
||||
case DWARFSectionKind::DW_SECT_ABBREV: {
|
||||
OutData = getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_ABBREV,
|
||||
DWPOffset);
|
||||
DebugAbbrevPatcher *Patcher = Writer.getBinaryDWOAbbrevPatcher(DWOId);
|
||||
return applyPatch(Patcher, OutData, DWPOffset);
|
||||
}
|
||||
case DWARFSectionKind::DW_SECT_EXT_LOC: {
|
||||
DebugLocWriter *LocWriter = Writer.getDebugLocWriter(DWOId);
|
||||
LocVectorOut = LocWriter->finalize();
|
||||
DebugAbbrevWriter *AbbrevWriter = Writer.getBinaryDWOAbbrevWriter(DWOId);
|
||||
OutputBuffer = AbbrevWriter->finalize();
|
||||
// Creating explicit StringRef here, otherwise
|
||||
// with impicit conversion it will take null byte as end of
|
||||
// string.
|
||||
return StringRef(reinterpret_cast<const char *>(LocVectorOut->data()),
|
||||
LocVectorOut->size());
|
||||
return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
|
||||
OutputBuffer->size());
|
||||
}
|
||||
case DWARFSectionKind::DW_SECT_EXT_LOC: {
|
||||
DebugLocWriter *LocWriter = Writer.getDebugLocWriter(DWOId);
|
||||
OutputBuffer = LocWriter->finalize();
|
||||
// Creating explicit StringRef here, otherwise
|
||||
// with impicit conversion it will take null byte as end of
|
||||
// string.
|
||||
return StringRef(reinterpret_cast<const char *>(OutputBuffer->data()),
|
||||
OutputBuffer->size());
|
||||
}
|
||||
case DWARFSectionKind::DW_SECT_LINE: {
|
||||
return getSliceData(DWOEntry, OutData, DWARFSectionKind::DW_SECT_LINE,
|
||||
|
@ -1080,10 +1093,10 @@ void DWARFRewriter::writeDWP(
|
|||
(*DWOCU)->getContext().getDWARFObj().getFile();
|
||||
for (const SectionRef &Section : DWOFile->sections()) {
|
||||
std::string Storage = "";
|
||||
std::unique_ptr<LocBufferVector> LocData;
|
||||
std::unique_ptr<DebugBufferVector> OutputData;
|
||||
Optional<StringRef> TOutData =
|
||||
patchDebugData(Storage, Section, KnownSections, *Streamer, *this,
|
||||
DWOEntry, *DWOId, LocData);
|
||||
updateDebugData(Storage, Section, KnownSections, *Streamer, *this,
|
||||
DWOEntry, *DWOId, OutputData);
|
||||
if (!TOutData)
|
||||
continue;
|
||||
|
||||
|
@ -1180,10 +1193,10 @@ void DWARFRewriter::writeDWOFiles(
|
|||
|
||||
for (const SectionRef &Section : File->sections()) {
|
||||
std::string Storage = "";
|
||||
std::unique_ptr<LocBufferVector> LocData;
|
||||
std::unique_ptr<DebugBufferVector> OutputData;
|
||||
if (Optional<StringRef> OutData =
|
||||
patchDebugData(Storage, Section, KnownSections, *Streamer, *this,
|
||||
DWOEntry, *DWOId, LocData))
|
||||
updateDebugData(Storage, Section, KnownSections, *Streamer, *this,
|
||||
DWOEntry, *DWOId, OutputData))
|
||||
Streamer->emitBytes(*OutData);
|
||||
}
|
||||
Streamer->Finish();
|
||||
|
@ -1299,25 +1312,25 @@ void DWARFRewriter::updateGdbIndexSection() {
|
|||
NewGdbIndexSize);
|
||||
}
|
||||
|
||||
void DWARFRewriter::convertToRanges(const DWARFAbbreviationDeclaration *Abbrev,
|
||||
DebugAbbrevPatcher &AbbrevPatcher) {
|
||||
void DWARFRewriter::convertToRanges(const DWARFUnit &Unit,
|
||||
const DWARFAbbreviationDeclaration *Abbrev,
|
||||
DebugAbbrevWriter &AbbrevWriter) {
|
||||
dwarf::Form HighPCForm = Abbrev->findAttribute(dwarf::DW_AT_high_pc)->Form;
|
||||
dwarf::Form LowPCForm = Abbrev->findAttribute(dwarf::DW_AT_low_pc)->Form;
|
||||
|
||||
std::lock_guard<std::mutex> Lock(AbbrevPatcherMutex);
|
||||
// DW_FORM_GNU_addr_index is already variable encoding so nothing to do
|
||||
// there. If HighForm is 8 bytes need to change low_pc to be variable
|
||||
// encoding to consume extra bytes from high_pc, since DW_FORM_sec_offset is
|
||||
// 4 bytes for DWARF32.
|
||||
if (LowPCForm != dwarf::DW_FORM_GNU_addr_index &&
|
||||
isHighPcFormEightBytes(HighPCForm))
|
||||
AbbrevPatcher.addAttributePatch(Abbrev, dwarf::DW_AT_low_pc,
|
||||
dwarf::DW_AT_low_pc,
|
||||
dwarf::DW_FORM_indirect);
|
||||
AbbrevWriter.addAttributePatch(Unit, Abbrev, dwarf::DW_AT_low_pc,
|
||||
dwarf::DW_AT_low_pc,
|
||||
dwarf::DW_FORM_indirect);
|
||||
|
||||
AbbrevPatcher.addAttributePatch(Abbrev, dwarf::DW_AT_high_pc,
|
||||
dwarf::DW_AT_ranges,
|
||||
dwarf::DW_FORM_sec_offset);
|
||||
AbbrevWriter.addAttributePatch(Unit, Abbrev, dwarf::DW_AT_high_pc,
|
||||
dwarf::DW_AT_ranges,
|
||||
dwarf::DW_FORM_sec_offset);
|
||||
}
|
||||
|
||||
void DWARFRewriter::convertToRanges(DWARFDie DIE,
|
||||
|
@ -1333,13 +1346,14 @@ void DWARFRewriter::convertToRanges(DWARFDie DIE,
|
|||
convertToRanges(DIE, RangesSectionOffset, DebugInfoPatcher);
|
||||
}
|
||||
|
||||
void DWARFRewriter::convertPending(const DWARFAbbreviationDeclaration *Abbrev,
|
||||
void DWARFRewriter::convertPending(const DWARFUnit &Unit,
|
||||
const DWARFAbbreviationDeclaration *Abbrev,
|
||||
SimpleBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevPatcher &AbbrevPatcher) {
|
||||
DebugAbbrevWriter &AbbrevWriter) {
|
||||
if (ConvertedRangesAbbrevs.count(Abbrev))
|
||||
return;
|
||||
|
||||
convertToRanges(Abbrev, AbbrevPatcher);
|
||||
convertToRanges(Unit, Abbrev, AbbrevWriter);
|
||||
|
||||
auto I = PendingRanges.find(Abbrev);
|
||||
if (I != PendingRanges.end()) {
|
||||
|
@ -1382,9 +1396,9 @@ void DWARFRewriter::addToPendingRanges(
|
|||
std::make_pair(DWARFDieWrapper(DIE), FunctionRanges.front()));
|
||||
}
|
||||
|
||||
std::unique_ptr<LocBufferVector>
|
||||
std::unique_ptr<DebugBufferVector>
|
||||
DWARFRewriter::makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher) {
|
||||
auto LocBuffer = std::make_unique<LocBufferVector>();
|
||||
auto LocBuffer = std::make_unique<DebugBufferVector>();
|
||||
auto LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
|
||||
auto Writer =
|
||||
std::unique_ptr<MCObjectWriter>(BC.createObjectWriter(*LocStream));
|
||||
|
@ -1406,7 +1420,7 @@ DWARFRewriter::makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher) {
|
|||
if (llvm::isa<DebugLoclistWriter>(*LocWriter))
|
||||
continue;
|
||||
SectionOffsetByCU[CUIndex] = SectionOffset;
|
||||
std::unique_ptr<LocBufferVector> CurrCULocationLists =
|
||||
std::unique_ptr<DebugBufferVector> CurrCULocationLists =
|
||||
LocWriter->finalize();
|
||||
*LocStream << *CurrCULocationLists;
|
||||
SectionOffset += CurrCULocationLists->size();
|
||||
|
|
|
@ -33,8 +33,6 @@ class DWARFRewriter {
|
|||
|
||||
std::mutex DebugInfoPatcherMutex;
|
||||
|
||||
std::mutex AbbrevPatcherMutex;
|
||||
|
||||
/// Stores and serializes information that will be put into the
|
||||
/// .debug_ranges DWARF section.
|
||||
std::unique_ptr<DebugRangesSectionWriter> RangesSectionWriter;
|
||||
|
@ -52,15 +50,18 @@ class DWARFRewriter {
|
|||
/// Does not do de-duplication.
|
||||
std::unique_ptr<DebugStrWriter> StrWriter;
|
||||
|
||||
/// .debug_abbrev section writer for the main binary.
|
||||
std::unique_ptr<DebugAbbrevWriter> AbbrevWriter;
|
||||
|
||||
using LocWriters =
|
||||
std::unordered_map<uint64_t, std::unique_ptr<DebugLocWriter>>;
|
||||
/// Use a separate location list writer for each compilation unit
|
||||
LocWriters LocListWritersByCU;
|
||||
|
||||
using DebugAbbrevDWOPatchers =
|
||||
std::unordered_map<uint64_t, std::unique_ptr<DebugAbbrevPatcher>>;
|
||||
/// Binary patchers for DWO Abbrev sections.
|
||||
DebugAbbrevDWOPatchers BinaryDWOAbbrevPatchers;
|
||||
using DebugAbbrevDWOWriters =
|
||||
std::unordered_map<uint64_t, std::unique_ptr<DebugAbbrevWriter>>;
|
||||
/// Abbrev section writers for DWOs.
|
||||
DebugAbbrevDWOWriters BinaryDWOAbbrevWriters;
|
||||
|
||||
using DebugInfoDWOPatchers =
|
||||
std::unordered_map<uint64_t, std::unique_ptr<SimpleBinaryPatcher>>;
|
||||
|
@ -86,7 +87,7 @@ class DWARFRewriter {
|
|||
/// Update debug info for all DIEs in \p Unit.
|
||||
void updateUnitDebugInfo(uint64_t CUIndex, DWARFUnit &Unit,
|
||||
SimpleBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevPatcher &AbbrevPatcher);
|
||||
DebugAbbrevWriter &AbbrevWriter);
|
||||
|
||||
/// Patches the binary for an object's address ranges to be updated.
|
||||
/// The object can be a anything that has associated address ranges via either
|
||||
|
@ -98,12 +99,12 @@ class DWARFRewriter {
|
|||
void updateDWARFObjectAddressRanges(const DWARFDie DIE,
|
||||
uint64_t DebugRangesOffset,
|
||||
SimpleBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevPatcher &AbbrevPatcher);
|
||||
DebugAbbrevWriter &AbbrevWriter);
|
||||
|
||||
std::unique_ptr<LocBufferVector>
|
||||
std::unique_ptr<DebugBufferVector>
|
||||
makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher);
|
||||
|
||||
/// Generate new contents for .debug_ranges and .debug_aranges section.
|
||||
/// Finalize debug sections in the main binary.
|
||||
void finalizeDebugSections(SimpleBinaryPatcher &DebugInfoPatcher);
|
||||
|
||||
/// Patches the binary for DWARF address ranges (e.g. in functions and lexical
|
||||
|
@ -154,8 +155,9 @@ class DWARFRewriter {
|
|||
|
||||
/// Convert \p Abbrev from using a simple DW_AT_(low|high)_pc range to
|
||||
/// DW_AT_ranges.
|
||||
void convertToRanges(const DWARFAbbreviationDeclaration *Abbrev,
|
||||
DebugAbbrevPatcher &AbbrevPatcher);
|
||||
void convertToRanges(const DWARFUnit &Unit,
|
||||
const DWARFAbbreviationDeclaration *Abbrev,
|
||||
DebugAbbrevWriter &AbbrevWriter);
|
||||
|
||||
/// Update \p DIE that was using DW_AT_(low|high)_pc with DW_AT_ranges offset.
|
||||
void convertToRanges(DWARFDie DIE, uint64_t RangesSectionOffset,
|
||||
|
@ -170,9 +172,10 @@ class DWARFRewriter {
|
|||
SimpleBinaryPatcher &DebugInfoPatcher);
|
||||
|
||||
/// Convert pending ranges associated with the given \p Abbrev.
|
||||
void convertPending(const DWARFAbbreviationDeclaration *Abbrev,
|
||||
void convertPending(const DWARFUnit &Unit,
|
||||
const DWARFAbbreviationDeclaration *Abbrev,
|
||||
SimpleBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevPatcher &AbbrevPatcher);
|
||||
DebugAbbrevWriter &AbbrevWriter);
|
||||
|
||||
/// Adds to Pending Ranges.
|
||||
/// For Debug Fission also adding to .debug_addr to take care of a case where
|
||||
|
@ -185,8 +188,7 @@ class DWARFRewriter {
|
|||
/// Once all DIEs were seen, update DW_AT_(low|high)_pc values.
|
||||
void flushPendingRanges(SimpleBinaryPatcher &DebugInfoPatcher);
|
||||
|
||||
/// Helper function for creating and returnning DWO DebugInfo and Abbrev
|
||||
/// patchers.
|
||||
/// Helper function for creating and returning per-DWO patchers/writers.
|
||||
template <class T, class Patcher>
|
||||
Patcher *getBinaryDWOPatcherHelper(T &BinaryPatchers, uint64_t DwoId) {
|
||||
auto Iter = BinaryPatchers.find(DwoId);
|
||||
|
@ -218,12 +220,11 @@ public:
|
|||
BinaryDWODebugInfoPatchers, DwoId);
|
||||
}
|
||||
|
||||
/// Returns a DWO Abbrev Patcher for DWO ID.
|
||||
/// Creates a new instance if it's not already exists.
|
||||
DebugAbbrevPatcher *getBinaryDWOAbbrevPatcher(uint64_t DwoId) {
|
||||
return getBinaryDWOPatcherHelper<DebugAbbrevDWOPatchers,
|
||||
DebugAbbrevPatcher>(
|
||||
BinaryDWOAbbrevPatchers, DwoId);
|
||||
/// Returns a DWO abbrev writer for DWO ID.
|
||||
/// Creates a new instance if it does not already exists.
|
||||
DebugAbbrevWriter *getBinaryDWOAbbrevWriter(uint64_t DwoId) {
|
||||
return getBinaryDWOPatcherHelper<DebugAbbrevDWOWriters, DebugAbbrevWriter>(
|
||||
BinaryDWOAbbrevWriters, DwoId);
|
||||
}
|
||||
|
||||
/// Given a DWO ID, return its DebugLocWriter if it exists.
|
||||
|
|
|
@ -59,7 +59,7 @@ uint64_t writeAddressRanges(
|
|||
} // namespace
|
||||
|
||||
DebugRangesSectionWriter::DebugRangesSectionWriter() {
|
||||
RangesBuffer = std::make_unique<RangesBufferVector>();
|
||||
RangesBuffer = std::make_unique<DebugBufferVector>();
|
||||
RangesStream = std::make_unique<raw_svector_ostream>(*RangesBuffer);
|
||||
|
||||
// Add an empty range as the first entry;
|
||||
|
@ -257,7 +257,7 @@ uint64_t DebugAddrWriter::getOffset(uint64_t DWOId) {
|
|||
}
|
||||
|
||||
DebugLocWriter::DebugLocWriter(BinaryContext *BC) {
|
||||
LocBuffer = std::make_unique<LocBufferVector>();
|
||||
LocBuffer = std::make_unique<DebugBufferVector>();
|
||||
LocStream = std::make_unique<raw_svector_ostream>(*LocBuffer);
|
||||
}
|
||||
|
||||
|
@ -385,71 +385,6 @@ void SimpleBinaryPatcher::patchBinary(std::string &BinaryContents,
|
|||
}
|
||||
}
|
||||
|
||||
void DebugAbbrevPatcher::addAttributePatch(
|
||||
const DWARFAbbreviationDeclaration *Abbrev, dwarf::Attribute AttrTag,
|
||||
dwarf::Attribute NewAttrTag, uint8_t NewAttrForm) {
|
||||
assert(Abbrev && "no abbreviation specified");
|
||||
|
||||
if (std::numeric_limits<uint8_t>::max() >= NewAttrTag)
|
||||
AbbrevPatches.emplace(
|
||||
AbbrevAttrPatch{Abbrev, AttrTag, NewAttrTag, NewAttrForm});
|
||||
else
|
||||
AbbrevNonStandardPatches.emplace_back(
|
||||
AbbrevAttrPatch{Abbrev, AttrTag, NewAttrTag, NewAttrForm});
|
||||
}
|
||||
|
||||
void DebugAbbrevPatcher::patchBinary(std::string &Contents,
|
||||
uint32_t DWPOffset = 0) {
|
||||
SimpleBinaryPatcher Patcher;
|
||||
|
||||
for (const AbbrevAttrPatch &Patch : AbbrevPatches) {
|
||||
const DWARFAbbreviationDeclaration::AttributeSpec *const Attribute =
|
||||
Patch.Abbrev->findAttribute(Patch.Attr);
|
||||
assert(Attribute && "Specified attribute doesn't occur in abbreviation.");
|
||||
|
||||
Patcher.addBytePatch(Attribute->AttrOffset - DWPOffset,
|
||||
static_cast<uint8_t>(Patch.NewAttr));
|
||||
Patcher.addBytePatch(Attribute->FormOffset - DWPOffset, Patch.NewForm);
|
||||
}
|
||||
Patcher.patchBinary(Contents);
|
||||
|
||||
if (AbbrevNonStandardPatches.empty())
|
||||
return;
|
||||
|
||||
std::string Section;
|
||||
Section.reserve(Contents.size() + AbbrevNonStandardPatches.size() / 2);
|
||||
|
||||
const char *Ptr = Contents.c_str();
|
||||
uint32_t Start = 0;
|
||||
std::string Buff;
|
||||
auto Encode = [&](uint16_t Value) -> std::string {
|
||||
Buff.clear();
|
||||
raw_string_ostream OS(Buff);
|
||||
encodeULEB128(Value, OS, 2);
|
||||
return Buff;
|
||||
};
|
||||
|
||||
for (const AbbrevAttrPatch &Patch : AbbrevNonStandardPatches) {
|
||||
const DWARFAbbreviationDeclaration::AttributeSpec *const Attribute =
|
||||
Patch.Abbrev->findAttribute(Patch.Attr);
|
||||
assert(Attribute && "Specified attribute doesn't occur in abbreviation.");
|
||||
assert(Start <= Attribute->AttrOffset &&
|
||||
"Offsets are not in sequential order.");
|
||||
// Assuming old attribute is 1 byte. Otherwise will need to add logic to
|
||||
// determine it's size at runtime.
|
||||
assert(std::numeric_limits<uint8_t>::max() >= Patch.Attr &&
|
||||
"Old attribute is greater then 1 byte.");
|
||||
|
||||
Section.append(Ptr + Start, Attribute->AttrOffset - Start);
|
||||
Section.append(Encode(Patch.NewAttr));
|
||||
Section.append(std::string(1, Patch.NewForm));
|
||||
|
||||
Start = Attribute->FormOffset + 1;
|
||||
}
|
||||
Section.append(Ptr + Start, Contents.size() - Start);
|
||||
Contents = std::move(Section);
|
||||
}
|
||||
|
||||
void DebugStrWriter::create() {
|
||||
StrBuffer = std::make_unique<DebugStrBufferVector>();
|
||||
StrStream = std::make_unique<raw_svector_ostream>(*StrBuffer);
|
||||
|
@ -469,5 +404,122 @@ uint32_t DebugStrWriter::addString(StringRef Str) {
|
|||
return Offset;
|
||||
}
|
||||
|
||||
void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) {
|
||||
const DWARFAbbreviationDeclarationSet *Abbrevs = Unit.getAbbreviations();
|
||||
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);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> Lock(WriterMutex);
|
||||
const auto &UnitPatches = Patches[&Unit];
|
||||
|
||||
raw_svector_ostream &OS = *CUAbbrevData[CUIndex].Stream.get();
|
||||
|
||||
// Take a fast path if there are no patches to apply. Simply copy the original
|
||||
// contents.
|
||||
if (UnitPatches.empty()) {
|
||||
StringRef AbbrevSectionContents =
|
||||
Unit.isDWOUnit() ? Unit.getContext().getDWARFObj().getAbbrevDWOSection()
|
||||
: Unit.getContext().getDWARFObj().getAbbrevSection();
|
||||
StringRef AbbrevContents;
|
||||
|
||||
const DWARFUnitIndex &CUIndex = Unit.getContext().getCUIndex();
|
||||
if (!CUIndex.getRows().empty()) {
|
||||
// Handle DWP section contribution.
|
||||
const DWARFUnitIndex::Entry *DWOEntry =
|
||||
CUIndex.getFromHash(*Unit.getDWOId());
|
||||
if (!DWOEntry)
|
||||
return;
|
||||
|
||||
const DWARFUnitIndex::Entry::SectionContribution *DWOContrubution =
|
||||
DWOEntry->getContribution(DWARFSectionKind::DW_SECT_ABBREV);
|
||||
AbbrevContents = AbbrevSectionContents.substr(DWOContrubution->Offset,
|
||||
DWOContrubution->Length);
|
||||
} else {
|
||||
DWARFCompileUnit *NextUnit =
|
||||
Unit.getContext().getCompileUnitForOffset(Unit.getNextUnitOffset());
|
||||
const uint64_t StartOffset = Unit.getAbbreviationsOffset();
|
||||
const uint64_t EndOffset = NextUnit ? NextUnit->getAbbreviationsOffset()
|
||||
: AbbrevSectionContents.size();
|
||||
AbbrevContents = AbbrevSectionContents.slice(StartOffset, EndOffset);
|
||||
}
|
||||
|
||||
OS.reserveExtraSpace(AbbrevContents.size());
|
||||
OS << AbbrevContents;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto I = Abbrevs->begin(), E = Abbrevs->end(); I != E; ++I) {
|
||||
const DWARFAbbreviationDeclaration &Abbrev = *I;
|
||||
auto Patch = UnitPatches.find(&Abbrev);
|
||||
|
||||
encodeULEB128(Abbrev.getCode(), OS);
|
||||
encodeULEB128(Abbrev.getTag(), OS);
|
||||
encodeULEB128(Abbrev.hasChildren(), OS);
|
||||
for (const DWARFAbbreviationDeclaration::AttributeSpec &AttrSpec :
|
||||
Abbrev.attributes()) {
|
||||
if (Patch != UnitPatches.end()) {
|
||||
bool Patched = false;
|
||||
// Patches added later take a precedence over earlier ones.
|
||||
for (auto I = Patch->second.rbegin(), E = Patch->second.rend(); I != E;
|
||||
++I) {
|
||||
if (I->OldAttr != AttrSpec.Attr)
|
||||
continue;
|
||||
|
||||
encodeULEB128(I->NewAttr, OS);
|
||||
encodeULEB128(I->NewAttrForm, OS);
|
||||
Patched = true;
|
||||
break;
|
||||
}
|
||||
if (Patched)
|
||||
continue;
|
||||
}
|
||||
|
||||
encodeULEB128(AttrSpec.Attr, OS);
|
||||
encodeULEB128(AttrSpec.Form, OS);
|
||||
if (AttrSpec.isImplicitConst())
|
||||
encodeSLEB128(AttrSpec.getImplicitConstValue(), OS);
|
||||
}
|
||||
|
||||
encodeULEB128(0, OS);
|
||||
encodeULEB128(0, OS);
|
||||
}
|
||||
encodeULEB128(0, OS);
|
||||
}
|
||||
|
||||
std::unique_ptr<DebugBufferVector> DebugAbbrevWriter::finalize() {
|
||||
DebugBufferVector ReturnBuffer;
|
||||
|
||||
// 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();
|
||||
}
|
||||
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();
|
||||
|
||||
Data.Buffer.reset();
|
||||
Data.Stream.reset();
|
||||
}
|
||||
|
||||
return std::make_unique<DebugBufferVector>(ReturnBuffer);
|
||||
}
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
namespace llvm {
|
||||
|
||||
class DWARFAbbreviationDeclarationSet;
|
||||
|
||||
namespace bolt {
|
||||
|
||||
class BinaryContext;
|
||||
|
@ -100,7 +102,8 @@ struct DebugLineTableRowRef {
|
|||
}
|
||||
};
|
||||
|
||||
using RangesBufferVector = SmallVector<char, 16>;
|
||||
/// Common buffer vector used for debug info handling.
|
||||
using DebugBufferVector = SmallVector<char, 16>;
|
||||
|
||||
/// Serializes the .debug_ranges DWARF section.
|
||||
class DebugRangesSectionWriter {
|
||||
|
@ -122,12 +125,12 @@ public:
|
|||
/// Returns the SectionOffset.
|
||||
uint64_t getSectionOffset();
|
||||
|
||||
std::unique_ptr<RangesBufferVector> finalize() {
|
||||
std::unique_ptr<DebugBufferVector> finalize() {
|
||||
return std::move(RangesBuffer);
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<RangesBufferVector> RangesBuffer;
|
||||
std::unique_ptr<DebugBufferVector> RangesBuffer;
|
||||
|
||||
std::unique_ptr<raw_svector_ostream> RangesStream;
|
||||
|
||||
|
@ -277,8 +280,6 @@ private:
|
|||
BinaryContext *BC;
|
||||
};
|
||||
|
||||
using LocBufferVector = SmallVector<char, 16>;
|
||||
|
||||
enum class LocWriterKind { DebugLocWriter, DebugLoclistWriter };
|
||||
|
||||
/// Serializes part of a .debug_loc DWARF section with LocationLists.
|
||||
|
@ -290,7 +291,7 @@ public:
|
|||
|
||||
virtual uint64_t addList(const DebugLocationsVector &LocList);
|
||||
|
||||
virtual std::unique_ptr<LocBufferVector> finalize() {
|
||||
virtual std::unique_ptr<DebugBufferVector> finalize() {
|
||||
return std::move(LocBuffer);
|
||||
}
|
||||
|
||||
|
@ -309,7 +310,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<LocBufferVector> LocBuffer;
|
||||
std::unique_ptr<DebugBufferVector> LocBuffer;
|
||||
|
||||
std::unique_ptr<raw_svector_ostream> LocStream;
|
||||
/// Current offset in the section (updated as new entries are written).
|
||||
|
@ -429,59 +430,69 @@ public:
|
|||
uint32_t DWPOffset) override;
|
||||
};
|
||||
|
||||
/// Apply small modifications to the .debug_abbrev DWARF section.
|
||||
class DebugAbbrevPatcher : public BinaryPatcher {
|
||||
public:
|
||||
/// Patch of changing one attribute to another.
|
||||
struct AbbrevAttrPatch {
|
||||
const DWARFAbbreviationDeclaration *Abbrev;
|
||||
dwarf::Attribute Attr; // ID of attribute to be replaced.
|
||||
dwarf::Attribute NewAttr; // ID of the new attribute.
|
||||
uint8_t NewForm; // Form of the new attribute.
|
||||
/// Class to facilitate modifying and writing abbreviations for compilation
|
||||
/// units. One class instance manages all abbreviation sections in a file
|
||||
/// or in a section contribution for DWPs.
|
||||
class DebugAbbrevWriter {
|
||||
|
||||
bool operator==(const AbbrevAttrPatch &RHS) const {
|
||||
return Abbrev == RHS.Abbrev && Attr == RHS.Attr;
|
||||
}
|
||||
std::mutex WriterMutex;
|
||||
|
||||
struct AbbrevData {
|
||||
/// Offset in the final section.
|
||||
uint64_t Offset{0};
|
||||
std::unique_ptr<DebugBufferVector> Buffer;
|
||||
std::unique_ptr<raw_svector_ostream> Stream;
|
||||
};
|
||||
/// Map CU offset to abbreviations data.
|
||||
std::map<uint64_t, AbbrevData> CUAbbrevData;
|
||||
|
||||
/// Attributes Substitution information.
|
||||
struct PatchInfo {
|
||||
dwarf::Attribute OldAttr;
|
||||
dwarf::Attribute NewAttr;
|
||||
uint8_t NewAttrForm;
|
||||
};
|
||||
|
||||
struct AbbrevHash {
|
||||
size_t operator()(const AbbrevAttrPatch &P) const {
|
||||
return std::hash<uint64_t>()(((uint64_t)P.Abbrev << 16) + P.Attr);
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
std::unordered_set<AbbrevAttrPatch, AbbrevHash> AbbrevPatches;
|
||||
/// Using Vector because this is currently being used for specific purpose of
|
||||
/// patching DW_AT_GNU_ranges_base. So don't need fast look up, but do need
|
||||
/// them to be in order.
|
||||
std::vector<AbbrevAttrPatch> AbbrevNonStandardPatches;
|
||||
using PatchesTy = std::unordered_map<const DWARFAbbreviationDeclaration *,
|
||||
SmallVector<PatchInfo, 2>>;
|
||||
std::unordered_map<const DWARFUnit *, PatchesTy> Patches;
|
||||
|
||||
public:
|
||||
virtual ~DebugAbbrevPatcher() {}
|
||||
/// Adds a patch to change an attribute of the abbreviation
|
||||
/// \p Abbrev the abbreviation to be modified.
|
||||
/// \p AttrTag ID of the attribute to be replaced.
|
||||
/// \p NewAttrTag ID of the new attribute.
|
||||
/// \p NewAttrForm Form of the new attribute.
|
||||
/// If None standard form is added through this API it will expand the section
|
||||
/// to accomidate it.
|
||||
void addAttributePatch(const DWARFAbbreviationDeclaration *Abbrev,
|
||||
DebugAbbrevWriter() = default;
|
||||
|
||||
DebugAbbrevWriter(const DebugAbbrevWriter &) = delete;
|
||||
DebugAbbrevWriter &operator=(const DebugAbbrevWriter &) = delete;
|
||||
|
||||
DebugAbbrevWriter(DebugAbbrevWriter &&) = delete;
|
||||
DebugAbbrevWriter &operator=(DebugAbbrevWriter &&) = delete;
|
||||
|
||||
virtual ~DebugAbbrevWriter() = default;
|
||||
|
||||
/// Substitute attribute \p AttrTag in abbreviation declaration \p Abbrev
|
||||
/// belonging to CU \p Unit with new attribute \p NewAttrTag having
|
||||
/// \p NewAttrForm form.
|
||||
void addAttributePatch(const DWARFUnit &Unit,
|
||||
const DWARFAbbreviationDeclaration *Abbrev,
|
||||
dwarf::Attribute AttrTag, dwarf::Attribute NewAttrTag,
|
||||
uint8_t NewAttrForm);
|
||||
uint8_t NewAttrForm) {
|
||||
std::lock_guard<std::mutex> Lock(WriterMutex);
|
||||
Patches[&Unit][Abbrev].emplace_back(
|
||||
PatchInfo{AttrTag, NewAttrTag, NewAttrForm});
|
||||
}
|
||||
|
||||
virtual void patchBinary(std::string &Contents, uint32_t DWPOffset) override;
|
||||
/// Add abbreviations from CU \p Unit to the writer.
|
||||
void addUnitAbbreviations(DWARFUnit &Unit);
|
||||
|
||||
/// Finds an abbreviation patch.
|
||||
/// \p AbbrevDecl the abbreviation declaration.
|
||||
/// \p AttrTag Attribute to search for.
|
||||
/// Returns nullptr if patch doesn't exist.
|
||||
const AbbrevAttrPatch *find(const DWARFAbbreviationDeclaration *AbbrevDecl,
|
||||
dwarf::Attribute AttrTag) {
|
||||
auto Iter = AbbrevPatches.find({AbbrevDecl, AttrTag, AttrTag, 0});
|
||||
if (Iter == AbbrevPatches.end())
|
||||
return nullptr;
|
||||
return &(*Iter);
|
||||
/// Return a buffer with concatenated abbrev sections for all added CUs.
|
||||
/// Section offsets for CUs could be queried using
|
||||
/// getAbbreviationsOffsetForUnit() interface.
|
||||
std::unique_ptr<DebugBufferVector> finalize();
|
||||
|
||||
/// 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() &&
|
||||
"no abbrev data found for unit");
|
||||
return CUAbbrevData[Unit.getOffset()].Offset;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -446,8 +446,8 @@ bool processAllFunctions() {
|
|||
|
||||
constexpr const char *RewriteInstance::SectionsToOverwrite[];
|
||||
std::vector<std::string> RewriteInstance::DebugSectionsToOverwrite = {
|
||||
".debug_aranges", ".debug_line", ".debug_loc",
|
||||
".debug_ranges", ".gdb_index", ".debug_addr"};
|
||||
".debug_abbrev", ".debug_aranges", ".debug_line", ".debug_loc",
|
||||
".debug_ranges", ".gdb_index", ".debug_addr"};
|
||||
|
||||
const char RewriteInstance::TimerGroupName[] = "rewrite";
|
||||
const char RewriteInstance::TimerGroupDesc[] = "Rewrite passes";
|
||||
|
|
Loading…
Reference in New Issue