forked from OSchip/llvm-project
[BOLT][DWARF] Fix writing out dwo with DWP as input
Summary: The code for writing out dwo files wasn't handling case where DWP is an input. Because all the sections are part of the same binary. One note with current implementation. .debug-str.dwo will have strings for all the dwo objects. This is because llvm-dwp de-duplicates strings and combines them in to one section. It then re-writes .debug-str-offsets.dwo to point to new .debug-str.dwo section. (cherry picked from FBD29244835)
This commit is contained in:
parent
3e5ce1f282
commit
f7499c6711
|
@ -1460,6 +1460,12 @@ Optional<DWARFUnit *> BinaryContext::getDWOCU(uint64_t DWOId) {
|
|||
return Iter->second;
|
||||
}
|
||||
|
||||
DWARFContext *BinaryContext::getDWOContext() {
|
||||
if (DWOCUs.empty())
|
||||
return nullptr;
|
||||
return &DWOCUs.begin()->second->getContext();
|
||||
}
|
||||
|
||||
/// Handles DWO sections that can either be in .o, .dwo or .dwp files.
|
||||
void BinaryContext::preprocessDWODebugInfo() {
|
||||
for (const std::unique_ptr<DWARFUnit> &CU : DwCtx->compile_units()) {
|
||||
|
|
|
@ -212,9 +212,12 @@ public:
|
|||
createBinaryContext(const ObjectFile *File, bool IsPIC,
|
||||
std::unique_ptr<DWARFContext> DwCtx);
|
||||
|
||||
/// Given DWOId returns CU if it existss in DWOCUs.
|
||||
/// Given DWOId returns CU if it exists in DWOCUs.
|
||||
Optional<DWARFUnit *> getDWOCU(uint64_t DWOId);
|
||||
|
||||
/// Returns DWOContext if it exists.
|
||||
DWARFContext *getDWOContext();
|
||||
|
||||
/// Get Number of DWOCUs in a map.
|
||||
uint32_t getNumDWOCUs() { return DWOCUs.size(); }
|
||||
|
||||
|
|
|
@ -824,12 +824,35 @@ void DWARFRewriter::finalizeDebugSections(
|
|||
void DWARFRewriter::writeOutDWOFiles(
|
||||
std::unordered_map<uint64_t, std::string> &DWOIdToName) {
|
||||
std::string DebugData = "";
|
||||
auto ApplyPatch = [&](BinaryPatcher *Patcher, StringRef Data) -> StringRef {
|
||||
auto applyPatch = [&](BinaryPatcher *Patcher, StringRef Data,
|
||||
uint32_t Offset) -> StringRef {
|
||||
DebugData = Data.str();
|
||||
Patcher->patchBinary(DebugData);
|
||||
Patcher->patchBinary(DebugData, Offset);
|
||||
return StringRef(DebugData.c_str(), DebugData.size());
|
||||
};
|
||||
|
||||
using DWOSectionContribution =
|
||||
const DWARFUnitIndex::Entry::SectionContribution;
|
||||
auto getSliceData = [&](const DWARFUnitIndex::Entry *DWOEntry,
|
||||
StringRef OutData, DWARFSectionKind Sec,
|
||||
uint32_t &DWPOffset) -> StringRef {
|
||||
if (DWOEntry) {
|
||||
DWOSectionContribution *DWOContrubution = DWOEntry->getContribution(Sec);
|
||||
DWPOffset = DWOContrubution->Offset;
|
||||
OutData = OutData.substr(DWPOffset, DWOContrubution->Length);
|
||||
}
|
||||
return OutData;
|
||||
};
|
||||
|
||||
// Setup DWP code once.
|
||||
DWARFContext *DWOCtx = BC.getDWOContext();
|
||||
const DWARFUnitIndex *CUIndex = nullptr;
|
||||
bool IsDWP = false;
|
||||
if (DWOCtx) {
|
||||
CUIndex = &DWOCtx->getCUIndex();
|
||||
IsDWP = !CUIndex->getRows().empty();
|
||||
}
|
||||
|
||||
for (const std::unique_ptr<DWARFUnit> &CU : BC.DwCtx->compile_units()) {
|
||||
Optional<uint64_t> DWOId = CU->getDWOId();
|
||||
if (!DWOId)
|
||||
|
@ -859,6 +882,10 @@ void DWARFRewriter::writeOutDWOFiles(
|
|||
std::unique_ptr<MCStreamer> Streamer = TmpBC->createStreamer(TempOut->os());
|
||||
const MCObjectFileInfo &MCOFI = *Streamer->getContext().getObjectFileInfo();
|
||||
|
||||
const DWARFUnitIndex::Entry *DWOEntry = nullptr;
|
||||
if (IsDWP)
|
||||
DWOEntry = CUIndex->getFromHash(*DWOId);
|
||||
|
||||
const StringMap<MCSection *> KnownSections = {
|
||||
{".debug_info.dwo", MCOFI.getDwarfInfoDWOSection()},
|
||||
{".debug_types.dwo", MCOFI.getDwarfTypesDWOSection()},
|
||||
|
@ -879,7 +906,28 @@ void DWARFRewriter::writeOutDWOFiles(
|
|||
assert(Contents && "Invalid contents.");
|
||||
StringRef OutData(*Contents);
|
||||
std::unique_ptr<LocBufferVector> Data;
|
||||
if (SectionName->equals(".debug_loc.dwo")) {
|
||||
uint32_t DWPOffset = 0;
|
||||
|
||||
if (SectionName->equals(".debug_info.dwo")) {
|
||||
OutData = getSliceData(DWOEntry, OutData,
|
||||
DWARFSectionKind::DW_SECT_INFO, DWPOffset);
|
||||
SimpleBinaryPatcher *Patcher = getBinaryDWODebugInfoPatcher(*DWOId);
|
||||
OutData = applyPatch(Patcher, OutData, DWPOffset);
|
||||
} else if (SectionName->equals(".debug_types.dwo")) {
|
||||
OutData = getSliceData(DWOEntry, OutData,
|
||||
DWARFSectionKind::DW_SECT_EXT_TYPES, DWPOffset);
|
||||
} else if (SectionName->equals(".debug_str.dwo")) {
|
||||
OutData = (*DWOCU)->getStringSection();
|
||||
} else if (SectionName->equals(".debug_str_offsets.dwo")) {
|
||||
OutData =
|
||||
getSliceData(DWOEntry, OutData,
|
||||
DWARFSectionKind::DW_SECT_STR_OFFSETS, DWPOffset);
|
||||
} else if (SectionName->equals(".debug_abbrev.dwo")) {
|
||||
OutData = getSliceData(DWOEntry, OutData,
|
||||
DWARFSectionKind::DW_SECT_ABBREV, DWPOffset);
|
||||
DebugAbbrevPatcher *Patcher = getBinaryDWOAbbrevPatcher(*DWOId);
|
||||
OutData = applyPatch(Patcher, OutData, DWPOffset);
|
||||
} else if (SectionName->equals(".debug_loc.dwo")) {
|
||||
DebugLocWriter *LocWriter = LocListWritersByCU[*DWOId].get();
|
||||
Data = LocWriter->finalize();
|
||||
// Creating explicit with creating of StringRef here, otherwise
|
||||
|
@ -887,12 +935,12 @@ void DWARFRewriter::writeOutDWOFiles(
|
|||
// string.
|
||||
OutData = StringRef(reinterpret_cast<const char *>(Data->data()),
|
||||
Data->size());
|
||||
} else if (SectionName->equals(".debug_info.dwo")) {
|
||||
SimpleBinaryPatcher *Patcher = getBinaryDWODebugInfoPatcher(*DWOId);
|
||||
OutData = ApplyPatch(Patcher, OutData);
|
||||
} else if (SectionName->equals(".debug_abbrev.dwo")) {
|
||||
DebugAbbrevPatcher *Patcher = getBinaryDWOAbbrevPatcher(*DWOId);
|
||||
OutData = ApplyPatch(Patcher, OutData);
|
||||
} else if (SectionName->equals(".debug_line.dwo")) {
|
||||
OutData = getSliceData(DWOEntry, OutData,
|
||||
DWARFSectionKind::DW_SECT_LINE, DWPOffset);
|
||||
} else {
|
||||
errs() << "BOLT-WARNING: Unsupported Debug section: " << *SectionName
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
Streamer->emitBytes(OutData);
|
||||
|
|
|
@ -371,9 +371,10 @@ void SimpleBinaryPatcher::addLE32Patch(uint32_t Offset, uint32_t NewValue) {
|
|||
addLEPatch(Offset, NewValue, 4);
|
||||
}
|
||||
|
||||
void SimpleBinaryPatcher::patchBinary(std::string &BinaryContents) {
|
||||
void SimpleBinaryPatcher::patchBinary(std::string &BinaryContents,
|
||||
uint32_t DWPOffset = 0) {
|
||||
for (const auto &Patch : Patches) {
|
||||
uint32_t Offset = Patch.first;
|
||||
uint32_t Offset = Patch.first - DWPOffset;
|
||||
const std::string &ByteSequence = Patch.second;
|
||||
assert(Offset + ByteSequence.size() <= BinaryContents.size() &&
|
||||
"Applied patch runs over binary size.");
|
||||
|
@ -396,7 +397,8 @@ void DebugAbbrevPatcher::addAttributePatch(
|
|||
AbbrevAttrPatch{Abbrev, AttrTag, NewAttrTag, NewAttrForm});
|
||||
}
|
||||
|
||||
void DebugAbbrevPatcher::patchBinary(std::string &Contents) {
|
||||
void DebugAbbrevPatcher::patchBinary(std::string &Contents,
|
||||
uint32_t DWPOffset = 0) {
|
||||
SimpleBinaryPatcher Patcher;
|
||||
|
||||
for (const AbbrevAttrPatch &Patch : AbbrevPatches) {
|
||||
|
@ -404,9 +406,9 @@ void DebugAbbrevPatcher::patchBinary(std::string &Contents) {
|
|||
Patch.Abbrev->findAttribute(Patch.Attr);
|
||||
assert(Attribute && "Specified attribute doesn't occur in abbreviation.");
|
||||
|
||||
Patcher.addBytePatch(Attribute->AttrOffset,
|
||||
Patcher.addBytePatch(Attribute->AttrOffset - DWPOffset,
|
||||
static_cast<uint8_t>(Patch.NewAttr));
|
||||
Patcher.addBytePatch(Attribute->FormOffset, Patch.NewForm);
|
||||
Patcher.addBytePatch(Attribute->FormOffset - DWPOffset, Patch.NewForm);
|
||||
}
|
||||
Patcher.patchBinary(Contents);
|
||||
|
||||
|
|
|
@ -364,7 +364,8 @@ class BinaryPatcher {
|
|||
public:
|
||||
virtual ~BinaryPatcher() {}
|
||||
/// Applies in-place modifications to the binary string \p BinaryContents .
|
||||
virtual void patchBinary(std::string &BinaryContents) = 0;
|
||||
/// \p DWPOffset used to correctly patch sections that come from DWP file.
|
||||
virtual void patchBinary(std::string &BinaryContents, uint32_t DWPOffset) = 0;
|
||||
};
|
||||
|
||||
/// Applies simple modifications to a binary string, such as directly replacing
|
||||
|
@ -424,7 +425,8 @@ public:
|
|||
/// Proxy for if we broke up low_pc/high_pc to ranges.
|
||||
bool getWasRangBasedUsed() const { return WasRangeBaseUsed; }
|
||||
|
||||
virtual void patchBinary(std::string &BinaryContents) override;
|
||||
virtual void patchBinary(std::string &BinaryContents,
|
||||
uint32_t DWPOffset) override;
|
||||
};
|
||||
|
||||
/// Apply small modifications to the .debug_abbrev DWARF section.
|
||||
|
@ -468,7 +470,7 @@ public:
|
|||
dwarf::Attribute AttrTag, dwarf::Attribute NewAttrTag,
|
||||
uint8_t NewAttrForm);
|
||||
|
||||
virtual void patchBinary(std::string &Contents) override;
|
||||
virtual void patchBinary(std::string &Contents, uint32_t DWPOffset) override;
|
||||
|
||||
/// Finds an abbreviation patch.
|
||||
/// \p AbbrevDecl the abbreviation declaration.
|
||||
|
|
|
@ -3843,7 +3843,7 @@ void RewriteInstance::rewriteNoteSections() {
|
|||
std::string Data =
|
||||
std::string(InputFile->getData().substr(Section.sh_offset, Size));
|
||||
if (BSec && BSec->getPatcher())
|
||||
BSec->getPatcher()->patchBinary(Data);
|
||||
BSec->getPatcher()->patchBinary(Data, 0);
|
||||
|
||||
// Section was expanded, so need to treat it as overwrite.
|
||||
if (Size != Data.size()) {
|
||||
|
|
Loading…
Reference in New Issue