[BOLT][DWARF] Implement new mechanism for DWARFRewriter
This revision implement new mechanism for DWARFRewriter. In the new mechanism, we adopt the same way with DWARFLinker did. By parsing Debug information into IR, we are allowed to handle debug information more flexible. Now the debug information updating process relies on IR and IR will be written out to binary once the updating finished. A new class was added: DIEBuilder. This class is responsible for parsing debug information and raising it to the IR level. This class is also used to write out the .debug_info and .debug_abbrev sections. Since we output brand new Abbrev section we won't need to always convert low_pc/high_pc into ranges. When conversion does happen we can also remove low_pc entry. Reviewed By: maksfb, ayermolo Differential Revision: https://reviews.llvm.org/D130315
This commit is contained in:
committed by
Alexander Yermolovich
parent
c1885d2dfa
commit
87fb0ea27e
307
bolt/include/bolt/Core/DIEBuilder.h
Normal file
307
bolt/include/bolt/Core/DIEBuilder.h
Normal file
@@ -0,0 +1,307 @@
|
||||
//===- bolt/Core/DIEBuilder.h -----------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
///
|
||||
/// \file
|
||||
/// This file contains the declaration of the DIEBuilder class, which is the
|
||||
/// base class for Debug Information IR construction.
|
||||
///
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef BOLT_CORE_DIE_BUILDER_H
|
||||
#define BOLT_CORE_DIE_BUILDER_H
|
||||
|
||||
#include "llvm/CodeGen/DIE.h"
|
||||
#include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
|
||||
#include "llvm/IR/Type.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <forward_list>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <shared_mutex>
|
||||
#include <sys/types.h>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
namespace bolt {
|
||||
|
||||
class DIEBuilder {
|
||||
struct DIEInfo {
|
||||
DIE *Die;
|
||||
uint32_t DieId;
|
||||
uint32_t UnitId;
|
||||
uint32_t CanonicalDIEOffset;
|
||||
};
|
||||
|
||||
struct UnitInfo {
|
||||
std::list<DIEInfo> DieInfoList;
|
||||
uint32_t UnitId;
|
||||
uint32_t UnitOffset;
|
||||
bool Isconstructed = false;
|
||||
uint32_t NewDieId = 0;
|
||||
std::unordered_map<uint64_t, uint32_t> DIEIDMap;
|
||||
std::unordered_map<uint32_t, DIEInfo *> DIEId2InfoMap;
|
||||
};
|
||||
|
||||
struct ForwardReferenceInfo {
|
||||
ForwardReferenceInfo(DIEInfo *Die,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec spec)
|
||||
: Dst(Die), AttrSpec(spec) {}
|
||||
DIEInfo *Dst;
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec;
|
||||
};
|
||||
|
||||
bool IsBuilt = false;
|
||||
std::unordered_map<DWARFUnit *, std::vector<DIE *>> UnitDIEs;
|
||||
std::unordered_map<DWARFUnit *, uint32_t> UnitIDMap;
|
||||
std::unordered_map<DWARFUnit *, DIE *> TypeDIEMap;
|
||||
std::vector<DWARFUnit *> DUList;
|
||||
std::vector<UnitInfo> CloneUnitCtxMap;
|
||||
std::vector<std::pair<DIEInfo *, ForwardReferenceInfo>> ForwardReferences;
|
||||
FoldingSet<DIEAbbrev> AbbreviationsSet;
|
||||
std::vector<std::unique_ptr<DIEAbbrev>> Abbreviations;
|
||||
std::vector<DWARFUnit *> DWARF4TUVector;
|
||||
std::vector<DWARFUnit *> DWARF4CUVector;
|
||||
BumpPtrAllocator DIEAlloc;
|
||||
|
||||
/// Resolve the reference in DIE, if target is not loaded into IR,
|
||||
/// pre-allocate it. \p RefCU will be updated to the Unit specific by \p
|
||||
/// RefValue.
|
||||
DWARFDie
|
||||
resolveDIEReference(const DWARFFormValue &RefValue,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
DWARFUnit *&RefCU,
|
||||
DWARFDebugInfoEntry &DwarfDebugInfoEntry,
|
||||
const std::vector<DWARFUnit *> &DUOffsetList);
|
||||
|
||||
/// Clone one attribute according the format. \return the size of this
|
||||
/// attribute.
|
||||
uint32_t
|
||||
cloneAttribute(DIE &Die, const DWARFDie &InputDIE, DWARFUnit &U,
|
||||
const DWARFFormValue &Val,
|
||||
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
unsigned AttrSize, bool IsLittleEndian,
|
||||
std::vector<DWARFUnit *> &DUOffsetList);
|
||||
|
||||
/// Clone an attribute in string format.
|
||||
uint32_t cloneStringAttribute(
|
||||
DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
unsigned AttrSize, const DWARFFormValue &Val, const DWARFUnit &U);
|
||||
|
||||
/// Clone an attribute in reference format.
|
||||
uint32_t cloneDieReferenceAttribute(
|
||||
DIE &Die, const DWARFDie &InputDIE,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, unsigned AttrSize,
|
||||
const DWARFFormValue &Val, DWARFUnit &U,
|
||||
std::vector<DWARFUnit *> &DUOffsetList);
|
||||
|
||||
/// Clone an attribute in block format.
|
||||
uint32_t
|
||||
cloneBlockAttribute(DIE &Die, DWARFUnit &U,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize,
|
||||
bool IsLittleEndian);
|
||||
|
||||
/// Clone an attribute in expression format. \p OutputBuffer will hold the
|
||||
/// output content.
|
||||
void cloneExpression(DataExtractor &Data, DWARFExpression &Expression,
|
||||
DWARFUnit &U, SmallVectorImpl<uint8_t> &OutputBuffer);
|
||||
|
||||
/// Clone an attribute in address format.
|
||||
uint32_t
|
||||
cloneAddressAttribute(DIE &Die,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, const DWARFUnit &U);
|
||||
|
||||
/// Clone an attribute in Refsig format.
|
||||
uint32_t
|
||||
cloneRefsigAttribute(DIE &Die,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
unsigned AttrSize, const DWARFFormValue &Val);
|
||||
|
||||
/// Clone an attribute in scalar format.
|
||||
uint32_t
|
||||
cloneScalarAttribute(DIE &Die, const DWARFDie &InputDIE,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize);
|
||||
|
||||
/// Clone an attribute in loclist format.
|
||||
uint32_t
|
||||
cloneLoclistAttrubute(DIE &Die, const DWARFDie &InputDIE,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize);
|
||||
|
||||
/// Update the Cross-CU reference offset.
|
||||
void computeReference();
|
||||
|
||||
/// Update the Offset and Size of DIE.
|
||||
uint32_t computeDIEOffset(DWARFUnit &CU, DIE &Die, uint32_t &CurOffset);
|
||||
|
||||
void registerUnit(DWARFUnit &Unit) {
|
||||
UnitIDMap[&Unit] = DUList.size();
|
||||
DUList.push_back(&Unit);
|
||||
}
|
||||
|
||||
/// \return the unique ID of \p U if it exists.
|
||||
std::optional<uint32_t> getUnitId(DWARFUnit &DU) {
|
||||
if (UnitIDMap.count(&DU))
|
||||
return UnitIDMap[&DU];
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
UnitInfo &getUnitInfo(uint32_t UnitId) { return CloneUnitCtxMap[UnitId]; }
|
||||
|
||||
DIEInfo &getDIEInfo(uint32_t UnitId, uint32_t DIEId) {
|
||||
if (CloneUnitCtxMap[UnitId].DIEId2InfoMap.count(DIEId))
|
||||
return *CloneUnitCtxMap[UnitId].DIEId2InfoMap[DIEId];
|
||||
|
||||
errs() << "BOLT-ERROR: The DIE is not allocated before looking up, some"
|
||||
<< "unexpected corner cases happened.\n";
|
||||
return CloneUnitCtxMap[UnitId].DieInfoList.front();
|
||||
}
|
||||
|
||||
UnitInfo &getUnitInfoByDwarfUnit(DWARFUnit &DwarfUnit) {
|
||||
std::optional<uint32_t> UnitId = getUnitId(DwarfUnit);
|
||||
return getUnitInfo(*UnitId);
|
||||
}
|
||||
|
||||
std::optional<uint32_t> getAllocDIEId(DWARFUnit &DU, DWARFDie &DDie) {
|
||||
UnitInfo &UnitInfo = getUnitInfoByDwarfUnit(DU);
|
||||
uint64_t Offset = DDie.getOffset();
|
||||
|
||||
if (!UnitInfo.DIEIDMap.count(Offset))
|
||||
return std::nullopt;
|
||||
return UnitInfo.DIEIDMap[Offset];
|
||||
}
|
||||
|
||||
std::optional<uint32_t> getAllocDIEId(DWARFUnit &DU, uint64_t Offset) {
|
||||
UnitInfo &UnitInfo = getUnitInfoByDwarfUnit(DU);
|
||||
|
||||
if (!UnitInfo.DIEIDMap.count(Offset))
|
||||
return std::nullopt;
|
||||
return UnitInfo.DIEIDMap[Offset];
|
||||
}
|
||||
|
||||
// To avoid overhead, do not use this unless we do get the UnitInfo first.
|
||||
// We can use getDIEInfo with UnitId and DieId
|
||||
DIEInfo &getDIEInfoByDwarfDie(DWARFDie *DwarfDie) {
|
||||
DWARFUnit *DwarfUnit = DwarfDie->getDwarfUnit();
|
||||
std::optional<uint32_t> UnitId = getUnitId(*DwarfUnit);
|
||||
std::optional<uint32_t> hasDIEId = getAllocDIEId(*DwarfUnit, *DwarfDie);
|
||||
assert(hasDIEId.has_value());
|
||||
|
||||
return getDIEInfo(*UnitId, *hasDIEId);
|
||||
}
|
||||
|
||||
std::optional<uint32_t> allocDIE(DWARFUnit &DU, DWARFDie &DDie,
|
||||
BumpPtrAllocator &Alloc, uint32_t UId,
|
||||
uint32_t offset = 0);
|
||||
|
||||
uint32_t AllocDIEId(DWARFUnit &DU) {
|
||||
UnitInfo &UnitInfo = getUnitInfoByDwarfUnit(DU);
|
||||
return UnitInfo.NewDieId++;
|
||||
}
|
||||
|
||||
/// Construct IR for \p DU. \p DUOffsetList specific the Unit in current
|
||||
/// Section.
|
||||
void constructFromUnit(DWARFUnit &DU, std::vector<DWARFUnit *> &DUOffsetList);
|
||||
|
||||
/// Construct a DIE for \p DDie in \p U. \p DUOffsetList specific the Unit in
|
||||
/// current Section.
|
||||
DIE *constructDIEFast(DWARFDie &DDie, DWARFUnit &U, bool IsLittleEndian,
|
||||
uint32_t UnitId,
|
||||
std::vector<DWARFUnit *> &DUOffsetList);
|
||||
|
||||
public:
|
||||
DIEBuilder(DWARFContext *DwarfContext, bool IsDWO = false);
|
||||
|
||||
std::vector<DIE *> getDIEsByUnit(DWARFUnit &DU) { return UnitDIEs[&DU]; }
|
||||
std::vector<std::unique_ptr<DIEAbbrev>> &getAbbrevs() {
|
||||
return Abbreviations;
|
||||
}
|
||||
DIE *getTypeDIE(DWARFUnit &DU) {
|
||||
if (TypeDIEMap.count(&DU))
|
||||
return TypeDIEMap[&DU];
|
||||
|
||||
errs() << "BOLT-ERROR: unable to find TypeUnit for Type Unit at offset 0x"
|
||||
<< DU.getOffset() << "\n";
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<DWARFUnit *> getDWARF4TUVector() { return DWARF4TUVector; }
|
||||
bool isEmpty() { return !IsBuilt; }
|
||||
|
||||
DIE *getUnitDIEbyUnit(DWARFUnit &DU) {
|
||||
assert(UnitDIEs.count(&DU) && UnitDIEs[&DU].size() &&
|
||||
"DU is not constructed in IR");
|
||||
return UnitDIEs[&DU].front();
|
||||
}
|
||||
|
||||
/// Generate and populate all Abbrevs.
|
||||
void generateAbbrevs();
|
||||
void generateUnitAbbrevs(DIE *die);
|
||||
void assignAbbrev(DIEAbbrev &Abbrev);
|
||||
|
||||
/// Finish current DIE construction.
|
||||
void finish();
|
||||
|
||||
// Interface to edit DIE
|
||||
template <class T> T *allocateDIEValue() { return new (DIEAlloc) T; }
|
||||
|
||||
DIEValueList::value_iterator addValue(DIEValueList *Die, const DIEValue &V) {
|
||||
return Die->addValue(DIEAlloc, V);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
DIEValueList::value_iterator addValue(DIEValueList *Die,
|
||||
dwarf::Attribute Attribute,
|
||||
dwarf::Form Form, T &&Value) {
|
||||
return Die->addValue(DIEAlloc, Attribute, Form, std::forward<T>(Value));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool replaceValue(DIEValueList *Die, dwarf::Attribute Attribute,
|
||||
dwarf::Form Form, T &&NewValue) {
|
||||
return Die->replaceValue(DIEAlloc, Attribute, Form,
|
||||
std::forward<T>(NewValue));
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool replaceValue(DIEValueList *Die, dwarf::Attribute Attribute,
|
||||
dwarf::Attribute NewAttribute, dwarf::Form Form,
|
||||
T &&NewValue) {
|
||||
return Die->replaceValue(DIEAlloc, Attribute, NewAttribute, Form,
|
||||
std::forward<T>(NewValue));
|
||||
}
|
||||
|
||||
bool replaceValue(DIEValueList *Die, dwarf::Attribute Attribute,
|
||||
dwarf::Form Form, DIEValue &NewValue) {
|
||||
return Die->replaceValue(DIEAlloc, Attribute, Form, NewValue);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool deleteValue(DIEValueList *Die, dwarf::Attribute Attribute) {
|
||||
return Die->deleteValue(Attribute);
|
||||
}
|
||||
};
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
@@ -15,6 +15,7 @@
|
||||
#define BOLT_CORE_DEBUG_DATA_H
|
||||
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/CodeGen/DIE.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/MC/MCDwarf.h"
|
||||
#include "llvm/Support/SMLoc.h"
|
||||
@@ -34,6 +35,7 @@ namespace llvm {
|
||||
|
||||
namespace bolt {
|
||||
|
||||
class DIEBuilder;
|
||||
struct AttrInfo {
|
||||
DWARFFormValue V;
|
||||
const DWARFAbbreviationDeclaration *AbbrevDecl;
|
||||
@@ -497,13 +499,11 @@ public:
|
||||
virtual ~DebugLocWriter(){};
|
||||
|
||||
/// Writes out location lists and stores internal patches.
|
||||
virtual void addList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
|
||||
DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter);
|
||||
virtual void addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo,
|
||||
DebugLocationsVector &LocList);
|
||||
|
||||
/// Writes out locations in to a local buffer, and adds Debug Info patches.
|
||||
virtual void finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter);
|
||||
virtual void finalize(DIEBuilder &DIEBldr, DIE &Die);
|
||||
|
||||
/// Return internal buffer.
|
||||
virtual std::unique_ptr<DebugBufferVector> getBuffer();
|
||||
@@ -569,13 +569,11 @@ public:
|
||||
static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; }
|
||||
|
||||
/// Stores location lists internally to be written out during finalize phase.
|
||||
void addList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
|
||||
DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter) override;
|
||||
virtual void addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo,
|
||||
DebugLocationsVector &LocList) override;
|
||||
|
||||
/// Writes out locations in to a local buffer and applies debug info patches.
|
||||
void finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter) override;
|
||||
void finalize(DIEBuilder &DIEBldr, DIE &Die) override;
|
||||
|
||||
/// Returns CU ID.
|
||||
/// For Skelton CU it is a CU Offset.
|
||||
@@ -596,8 +594,7 @@ public:
|
||||
|
||||
private:
|
||||
/// Writes out locations in to a local buffer and applies debug info patches.
|
||||
void finalizeDWARF5(DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter);
|
||||
void finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die);
|
||||
|
||||
static DebugAddrWriter *AddrWriter;
|
||||
DWARFUnit &CU;
|
||||
|
||||
@@ -9,11 +9,15 @@
|
||||
#ifndef BOLT_REWRITE_DWARF_REWRITER_H
|
||||
#define BOLT_REWRITE_DWARF_REWRITER_H
|
||||
|
||||
#include "bolt/Core/DIEBuilder.h"
|
||||
#include "bolt/Core/DebugData.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/CodeGen/DIE.h"
|
||||
#include "llvm/MC/MCAsmLayout.h"
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
@@ -89,15 +93,28 @@ private:
|
||||
|
||||
std::mutex LocListDebugInfoPatchesMutex;
|
||||
|
||||
/// Dwo id specific its .debug_info.dwo section content.
|
||||
std::unordered_map<uint64_t, std::string> DwoDebufInfoMap;
|
||||
|
||||
/// Dwo id specific its .debug_abbrev.dwo section content.
|
||||
std::unordered_map<uint64_t, std::string> DwoDebugAbbrevMap;
|
||||
|
||||
/// Dwo id specific its .debug_types.dwo section content.
|
||||
std::unordered_map<uint64_t, std::string> DwoDebugTypeMap;
|
||||
|
||||
/// Dwo id specific its RangesBase.
|
||||
std::unordered_map<uint64_t, uint64_t> DwoRangesBase;
|
||||
|
||||
std::unordered_map<DWARFUnit *, uint64_t> LineTablePatchMap;
|
||||
std::unordered_map<DWARFUnit *, uint64_t> TypeUnitRelocMap;
|
||||
|
||||
/// DWARFLegacy is all DWARF versions before DWARF 5.
|
||||
enum class DWARFVersion { DWARFLegacy, DWARF5 };
|
||||
|
||||
/// Update debug info for all DIEs in \p Unit.
|
||||
void updateUnitDebugInfo(DWARFUnit &Unit,
|
||||
DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter,
|
||||
void updateUnitDebugInfo(DWARFUnit &Unit, DIEBuilder &DIEBldr,
|
||||
DebugLocWriter &DebugLocWriter,
|
||||
DebugRangesSectionWriter &RangesWriter,
|
||||
DebugRangesSectionWriter &RangesSectionWriter,
|
||||
std::optional<uint64_t> RangesBase = std::nullopt);
|
||||
|
||||
/// Patches the binary for an object's address ranges to be updated.
|
||||
@@ -110,16 +127,15 @@ private:
|
||||
/// \p RangesBase if present, update \p DIE to use DW_AT_GNU_ranges_base
|
||||
/// attribute.
|
||||
void updateDWARFObjectAddressRanges(
|
||||
const DWARFDie DIE, uint64_t DebugRangesOffset,
|
||||
SimpleBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter,
|
||||
uint64_t LowPCToUse, std::optional<uint64_t> RangesBase = std::nullopt);
|
||||
DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
|
||||
uint64_t DebugRangesOffset, uint64_t LowPCToUse,
|
||||
std::optional<uint64_t> RangesBase = std::nullopt);
|
||||
|
||||
std::unique_ptr<DebugBufferVector>
|
||||
makeFinalLocListsSection(DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DWARFVersion Version);
|
||||
makeFinalLocListsSection(DWARFVersion Version);
|
||||
|
||||
/// Finalize debug sections in the main binary.
|
||||
CUOffsetMap finalizeDebugSections(DebugInfoBinaryPatcher &DebugInfoPatcher);
|
||||
CUOffsetMap finalizeDebugSections(DIEBuilder &DIEBlder);
|
||||
|
||||
/// Patches the binary for DWARF address ranges (e.g. in functions and lexical
|
||||
/// blocks) to be updated.
|
||||
@@ -170,8 +186,9 @@ private:
|
||||
/// Updates to the DIE should be synced with abbreviation updates using the
|
||||
/// function above.
|
||||
void convertToRangesPatchDebugInfo(
|
||||
DWARFDie DIE, uint64_t RangesSectionOffset,
|
||||
SimpleBinaryPatcher &DebugInfoPatcher, uint64_t LowPCToUse,
|
||||
DWARFUnit &Unit, DIEBuilder &DIEBldr, DIE &Die,
|
||||
uint64_t RangesSectionOffset, DIEValue &LowPCAttrInfo,
|
||||
DIEValue &HighPCAttrInfo, uint64_t LowPCToUse,
|
||||
std::optional<uint64_t> RangesBase = std::nullopt);
|
||||
|
||||
/// Helper function for creating and returning per-DWO patchers/writers.
|
||||
@@ -194,9 +211,8 @@ private:
|
||||
/// Uses \p AttrInfoVal to either update entry in a DIE for legacy DWARF using
|
||||
/// \p DebugInfoPatcher, or for DWARF5 update an index in .debug_str_offsets
|
||||
/// for this contribution of \p Unit.
|
||||
void addStringHelper(DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
const DWARFUnit &Unit, const AttrInfo &AttrInfoVal,
|
||||
StringRef Str);
|
||||
void addStringHelper(DIEBuilder &DIEBldr, DIE &Die, const DWARFUnit &Unit,
|
||||
DIEValue &DIEAttrInfo, StringRef Str);
|
||||
|
||||
public:
|
||||
DWARFRewriter(BinaryContext &BC) : BC(BC) {}
|
||||
@@ -237,6 +253,36 @@ public:
|
||||
return Iter == LocListWritersByCU.end() ? nullptr
|
||||
: LocListWritersByCU[DWOId].get();
|
||||
}
|
||||
|
||||
StringRef getDwoDebugInfoStr(uint64_t DWOId) {
|
||||
return DwoDebufInfoMap[DWOId];
|
||||
}
|
||||
|
||||
StringRef getDwoDebugAbbrevStr(uint64_t DWOId) {
|
||||
return DwoDebugAbbrevMap[DWOId];
|
||||
}
|
||||
|
||||
StringRef getDwoDebugTypeStr(uint64_t DWOId) {
|
||||
return DwoDebugTypeMap[DWOId];
|
||||
}
|
||||
|
||||
uint64_t getDwoRangesBase(uint64_t DWOId) { return DwoRangesBase[DWOId]; }
|
||||
|
||||
void setDwoDebugInfoStr(uint64_t DWOId, StringRef Str) {
|
||||
DwoDebufInfoMap[DWOId] = Str.str();
|
||||
}
|
||||
|
||||
void setDwoDebugAbbrevStr(uint64_t DWOId, StringRef Str) {
|
||||
DwoDebugAbbrevMap[DWOId] = Str.str();
|
||||
}
|
||||
|
||||
void setDwoDebugTypeStr(uint64_t DWOId, StringRef Str) {
|
||||
DwoDebugTypeMap[DWOId] = Str.str();
|
||||
}
|
||||
|
||||
void setDwoRangesBase(uint64_t DWOId, uint64_t RangesBase) {
|
||||
DwoRangesBase[DWOId] = RangesBase;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace bolt
|
||||
|
||||
@@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS
|
||||
MCDisassembler
|
||||
Object
|
||||
Support
|
||||
BinaryFormat
|
||||
AsmPrinter
|
||||
TargetParser
|
||||
)
|
||||
|
||||
@@ -17,6 +19,7 @@ add_llvm_library(LLVMBOLTCore
|
||||
BinaryFunctionProfile.cpp
|
||||
BinarySection.cpp
|
||||
DebugData.cpp
|
||||
DIEBuilder.cpp
|
||||
DynoStats.cpp
|
||||
Exceptions.cpp
|
||||
FunctionLayout.cpp
|
||||
|
||||
717
bolt/lib/Core/DIEBuilder.cpp
Normal file
717
bolt/lib/Core/DIEBuilder.cpp
Normal file
@@ -0,0 +1,717 @@
|
||||
#include "bolt/Core/DIEBuilder.h"
|
||||
#include "bolt/Core/BinaryContext.h"
|
||||
#include "bolt/Core/ParallelUtilities.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/CodeGen/DIE.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
|
||||
#include "llvm/ObjectYAML/DWARFYAML.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include "llvm/Support/Format.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
#include "llvm/Support/ThreadPool.h"
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
|
||||
#undef DEBUG_TYPE
|
||||
#define DEBUG_TYPE "bolt"
|
||||
namespace llvm {
|
||||
namespace bolt {
|
||||
|
||||
void DIEBuilder::computeReference() {
|
||||
for (auto &[SrcDIEInfo, ReferenceInfo] : ForwardReferences) {
|
||||
DIEInfo *DstDIEInfo = ReferenceInfo.Dst;
|
||||
UnitInfo &DstUnitInfo = getUnitInfo(DstDIEInfo->UnitId);
|
||||
dwarf::Attribute Attr = ReferenceInfo.AttrSpec.Attr;
|
||||
dwarf::Form Form = ReferenceInfo.AttrSpec.Form;
|
||||
uint64_t CUBase = 0;
|
||||
|
||||
// If DWARF 4, type unit is store in .debug_types. So we need to calibrate
|
||||
// the begin of .debug_info to the first Compile Unit offset.
|
||||
if (!DWARF4CUVector.empty()) {
|
||||
UnitInfo &FirstCUInfo = getUnitInfoByDwarfUnit(*DWARF4CUVector.front());
|
||||
CUBase = FirstCUInfo.UnitOffset;
|
||||
}
|
||||
|
||||
uint64_t NewAddr =
|
||||
DstDIEInfo->Die->getOffset() + DstUnitInfo.UnitOffset - CUBase;
|
||||
SrcDIEInfo->Die->replaceValue(DIEAlloc, Attr, Form, DIEInteger(NewAddr));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::optional<uint32_t> DIEBuilder::allocDIE(DWARFUnit &DU, DWARFDie &DDie,
|
||||
BumpPtrAllocator &Alloc,
|
||||
uint32_t UId, uint32_t offset) {
|
||||
auto &UnitInfo = getUnitInfo(UId);
|
||||
auto DDieOffset = DDie.getOffset();
|
||||
if (UnitInfo.DIEIDMap.count(DDieOffset))
|
||||
return UnitInfo.DIEIDMap[DDieOffset];
|
||||
uint32_t DId = AllocDIEId(DU);
|
||||
|
||||
DIE *Die = DIE::get(Alloc, dwarf::Tag(DDie.getTag()));
|
||||
UnitInfo.DIEIDMap[DDieOffset] = DId;
|
||||
UnitInfo.DieInfoList.push_back(DIEInfo{Die, DId, UId, offset});
|
||||
UnitInfo.DIEId2InfoMap[DId] = &UnitInfo.DieInfoList.back();
|
||||
|
||||
return DId;
|
||||
}
|
||||
|
||||
void DIEBuilder::constructFromUnit(DWARFUnit &DU,
|
||||
std::vector<DWARFUnit *> &DUOffsetList) {
|
||||
std::optional<uint32_t> UnitId = getUnitId(DU);
|
||||
if (!UnitId.has_value()) {
|
||||
errs() << "BOLT-WARNING: " << format("Skip Unit at 0x%x\n", DU.getOffset());
|
||||
return;
|
||||
}
|
||||
|
||||
const uint32_t UnitHeaderSize = DU.getHeaderSize();
|
||||
uint64_t DIEOffset = DU.getOffset() + UnitHeaderSize;
|
||||
uint64_t NextCUOffset = DU.getNextUnitOffset();
|
||||
DWARFDataExtractor DebugInfoData = DU.getDebugInfoExtractor();
|
||||
DWARFDebugInfoEntry DIEEntry;
|
||||
std::vector<DIE *> CurParentDIEStack;
|
||||
std::vector<uint32_t> Parents;
|
||||
uint32_t TUTypeOffset = 0;
|
||||
bool IsTypeDIE = false;
|
||||
bool IsCUDIE = true;
|
||||
|
||||
if (DWARFTypeUnit *TU = dyn_cast_or_null<DWARFTypeUnit>(&DU)) {
|
||||
TUTypeOffset = TU->getTypeOffset();
|
||||
}
|
||||
|
||||
assert(DebugInfoData.isValidOffset(NextCUOffset - 1));
|
||||
Parents.push_back(UINT32_MAX);
|
||||
do {
|
||||
if (TUTypeOffset == DIEOffset - DU.getOffset()) {
|
||||
IsTypeDIE = true;
|
||||
}
|
||||
|
||||
if (!DIEEntry.extractFast(DU, &DIEOffset, DebugInfoData, NextCUOffset,
|
||||
Parents.back()))
|
||||
break;
|
||||
|
||||
if (const DWARFAbbreviationDeclaration *AbbrDecl =
|
||||
DIEEntry.getAbbreviationDeclarationPtr()) {
|
||||
DWARFDie DDie(&DU, &DIEEntry);
|
||||
|
||||
DIE *CurDIE = constructDIEFast(DDie, DU, DU.getContext().isLittleEndian(),
|
||||
*UnitId, DUOffsetList);
|
||||
if (IsTypeDIE) {
|
||||
TypeDIEMap[&DU] = CurDIE;
|
||||
IsTypeDIE = false;
|
||||
}
|
||||
|
||||
if (!CurParentDIEStack.empty())
|
||||
CurParentDIEStack.back()->addChild(CurDIE);
|
||||
|
||||
if (AbbrDecl->hasChildren()) {
|
||||
CurParentDIEStack.push_back(CurDIE);
|
||||
} else if (IsCUDIE) {
|
||||
// Stop if we have single compile unit die w/o children.
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
// NULL DIE: finishes current children scope.
|
||||
CurParentDIEStack.pop_back();
|
||||
}
|
||||
|
||||
if (IsCUDIE)
|
||||
IsCUDIE = false;
|
||||
} while (CurParentDIEStack.size() > 0);
|
||||
|
||||
CloneUnitCtxMap[*UnitId].Isconstructed = true;
|
||||
}
|
||||
|
||||
DIEBuilder::DIEBuilder(DWARFContext *DwarfContext, bool IsDWO) {
|
||||
outs() << "BOLT-INFO: Constructing DIE...\n";
|
||||
IsBuilt = true;
|
||||
|
||||
const DWARFUnitIndex &TUIndex = DwarfContext->getTUIndex();
|
||||
if (!TUIndex.getRows().empty()) {
|
||||
for (auto &Row : TUIndex.getRows()) {
|
||||
uint64_t Signature = Row.getSignature();
|
||||
|
||||
// manually populate TypeUnit to UnitVector
|
||||
DwarfContext->getTypeUnitForHash(DwarfContext->getMaxVersion(), Signature,
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t MaxVersion =
|
||||
IsDWO ? DwarfContext->getMaxDWOVersion() : DwarfContext->getMaxVersion();
|
||||
unsigned int CUNum = IsDWO ? DwarfContext->getNumDWOCompileUnits()
|
||||
: DwarfContext->getNumCompileUnits();
|
||||
DWARFContext::compile_unit_range CU4Ranges =
|
||||
IsDWO ? DwarfContext->dwo_compile_units() : DwarfContext->compile_units();
|
||||
DWARFContext::unit_iterator_range CU5Ranges =
|
||||
IsDWO ? DwarfContext->dwo_info_section_units()
|
||||
: DwarfContext->info_section_units();
|
||||
|
||||
if (MaxVersion >= 5) {
|
||||
CUNum = IsDWO ? DwarfContext->getNumDWOCompileUnits() +
|
||||
DwarfContext->getNumDWOTypeUnits()
|
||||
: DwarfContext->getNumCompileUnits() +
|
||||
DwarfContext->getNumTypeUnits();
|
||||
}
|
||||
|
||||
CloneUnitCtxMap = std::vector<UnitInfo>(CUNum);
|
||||
|
||||
if (MaxVersion >= 5) {
|
||||
for (std::unique_ptr<DWARFUnit> &DU : CU5Ranges) {
|
||||
if (!DU.get())
|
||||
continue;
|
||||
registerUnit(*DU.get());
|
||||
}
|
||||
for (std::unique_ptr<DWARFUnit> &DU : CU5Ranges) {
|
||||
if (!DU.get())
|
||||
continue;
|
||||
constructFromUnit(*DU.get(), DUList);
|
||||
}
|
||||
} else {
|
||||
DWARFContext::unit_iterator_range CU4TURanges =
|
||||
IsDWO ? DwarfContext->dwo_types_section_units()
|
||||
: DwarfContext->types_section_units();
|
||||
for (std::unique_ptr<DWARFUnit> &DU : CU4TURanges) {
|
||||
CloneUnitCtxMap.resize(CloneUnitCtxMap.size() + 1);
|
||||
registerUnit(*DU.get());
|
||||
DWARF4TUVector.push_back(DU.get());
|
||||
}
|
||||
for (std::unique_ptr<DWARFUnit> &DU : CU4TURanges) {
|
||||
constructFromUnit(*DU.get(), DWARF4TUVector);
|
||||
}
|
||||
|
||||
for (std::unique_ptr<DWARFUnit> &DU : CU4Ranges) {
|
||||
registerUnit(*DU.get());
|
||||
DWARF4CUVector.push_back(DU.get());
|
||||
}
|
||||
for (std::unique_ptr<DWARFUnit> &DU : CU4Ranges) {
|
||||
constructFromUnit(*DU.get(), DWARF4CUVector);
|
||||
}
|
||||
}
|
||||
outs() << "BOLT-INFO: Finish constructing DIE\n";
|
||||
}
|
||||
|
||||
DIE *DIEBuilder::constructDIEFast(DWARFDie &DDie, DWARFUnit &U,
|
||||
bool IsLittleEndian, uint32_t UnitId,
|
||||
std::vector<DWARFUnit *> &DUOffsetList) {
|
||||
|
||||
std::optional<uint32_t> Idx = getAllocDIEId(U, DDie);
|
||||
if (Idx.has_value()) {
|
||||
UnitInfo &UnitInfo = getUnitInfo(UnitId);
|
||||
DIEInfo &DieInfo = getDIEInfo(UnitId, *Idx);
|
||||
if (UnitInfo.Isconstructed && DieInfo.Die)
|
||||
return DieInfo.Die;
|
||||
} else {
|
||||
Idx = allocDIE(U, DDie, DIEAlloc, UnitId);
|
||||
}
|
||||
|
||||
DIEInfo &DieInfo = getDIEInfo(UnitId, *Idx);
|
||||
DIE *Die = DieInfo.Die;
|
||||
UnitDIEs[&U].push_back(Die);
|
||||
|
||||
uint64_t Offset = DDie.getOffset();
|
||||
uint64_t NextOffset = Offset;
|
||||
DWARFDataExtractor Data = U.getDebugInfoExtractor();
|
||||
DWARFDebugInfoEntry DDIEntry;
|
||||
|
||||
if (DDIEntry.extractFast(U, &NextOffset, Data, U.getNextUnitOffset(), 0)) {
|
||||
assert(NextOffset - U.getOffset() <= Data.getData().size() &&
|
||||
"NextOffset OOB");
|
||||
}
|
||||
|
||||
SmallString<40> DIECopy(Data.getData().substr(Offset, NextOffset - Offset));
|
||||
Data =
|
||||
DWARFDataExtractor(DIECopy, Data.isLittleEndian(), Data.getAddressSize());
|
||||
Offset = 0;
|
||||
|
||||
const DWARFAbbreviationDeclaration *Abbrev =
|
||||
DDie.getAbbreviationDeclarationPtr();
|
||||
Offset += getULEB128Size(Abbrev->getCode());
|
||||
|
||||
for (const auto &AttrSpec : Abbrev->attributes()) {
|
||||
DWARFFormValue Val(AttrSpec.Form);
|
||||
uint64_t AttrSize = Offset;
|
||||
Val.extractValue(Data, &Offset, U.getFormParams(), &U);
|
||||
AttrSize = Offset - AttrSize;
|
||||
cloneAttribute(*Die, DDie, U, Val, AttrSpec, AttrSize, IsLittleEndian,
|
||||
DUOffsetList);
|
||||
}
|
||||
return Die;
|
||||
}
|
||||
|
||||
static DWARFUnit *getUnitForOffset(const std::vector<DWARFUnit *> &Units,
|
||||
uint64_t Offset) {
|
||||
auto CU =
|
||||
llvm::upper_bound(Units, Offset, [](uint64_t LHS, const DWARFUnit *RHS) {
|
||||
return LHS < RHS->getNextUnitOffset();
|
||||
});
|
||||
return CU != Units.end() ? *CU : nullptr;
|
||||
}
|
||||
|
||||
uint32_t DIEBuilder::computeDIEOffset(DWARFUnit &CU, DIE &Die,
|
||||
uint32_t &CurOffset) {
|
||||
uint32_t CurSize = 0;
|
||||
|
||||
Die.setOffset(CurOffset);
|
||||
for (DIEValue &Val : Die.values()) {
|
||||
CurSize += Val.sizeOf(CU.getFormParams());
|
||||
}
|
||||
CurSize += getULEB128Size(Die.getAbbrevNumber());
|
||||
CurOffset += CurSize;
|
||||
|
||||
for (DIE &Child : Die.children()) {
|
||||
uint32_t ChildSize = computeDIEOffset(CU, Child, CurOffset);
|
||||
CurSize += ChildSize;
|
||||
}
|
||||
// for children end mark.
|
||||
if (Die.hasChildren()) {
|
||||
CurSize += sizeof(uint8_t);
|
||||
CurOffset += sizeof(uint8_t);
|
||||
}
|
||||
|
||||
Die.setSize(CurSize);
|
||||
|
||||
return CurSize;
|
||||
}
|
||||
|
||||
void DIEBuilder::finish() {
|
||||
uint64_t UnitStartOffset = 0;
|
||||
|
||||
for (DWARFUnit *CU : DUList) {
|
||||
DIE *UnitDIE = getUnitDIEbyUnit(*CU);
|
||||
uint32_t HeaderSize = CU->getHeaderSize();
|
||||
uint32_t CurOffset = HeaderSize;
|
||||
computeDIEOffset(*CU, *UnitDIE, CurOffset);
|
||||
|
||||
UnitInfo &CurUnitInfo = getUnitInfoByDwarfUnit(*CU);
|
||||
CurUnitInfo.UnitOffset = UnitStartOffset;
|
||||
UnitStartOffset += HeaderSize + UnitDIE->getSize();
|
||||
}
|
||||
|
||||
computeReference();
|
||||
}
|
||||
|
||||
DWARFDie DIEBuilder::resolveDIEReference(
|
||||
const DWARFFormValue &RefValue,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, DWARFUnit *&RefCU,
|
||||
DWARFDebugInfoEntry &DwarfDebugInfoEntry,
|
||||
const std::vector<DWARFUnit *> &DUOffsetList) {
|
||||
assert(RefValue.isFormClass(DWARFFormValue::FC_Reference));
|
||||
uint64_t RefOffset = *RefValue.getAsReference();
|
||||
|
||||
if ((RefCU = getUnitForOffset(DUOffsetList, RefOffset))) {
|
||||
DWARFDataExtractor DebugInfoData = RefCU->getDebugInfoExtractor();
|
||||
if (DwarfDebugInfoEntry.extractFast(*RefCU, &RefOffset, DebugInfoData,
|
||||
RefCU->getNextUnitOffset(), 0)) {
|
||||
// In a file with broken references, an attribute might point to a NULL
|
||||
// DIE.
|
||||
DWARFDie RefDie = DWARFDie(RefCU, &DwarfDebugInfoEntry);
|
||||
if (!RefDie.isNULL()) {
|
||||
std::optional<uint32_t> UnitId = getUnitId(*RefCU);
|
||||
|
||||
// forward reference
|
||||
if (UnitId.has_value() && !CloneUnitCtxMap[*UnitId].Isconstructed) {
|
||||
std::optional<uint32_t> IsAllocId = getAllocDIEId(*RefCU, RefDie);
|
||||
if (!IsAllocId.has_value()) {
|
||||
// forward reference but need allocate a empty one
|
||||
IsAllocId = allocDIE(*RefCU, RefDie, DIEAlloc, *UnitId);
|
||||
}
|
||||
|
||||
uint32_t DIEId = *IsAllocId;
|
||||
DIEInfo &DieInfo = getDIEInfo(*UnitId, DIEId);
|
||||
DieInfo.CanonicalDIEOffset = 0xDEADBEEF;
|
||||
}
|
||||
return RefDie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("could not find referenced CU\n");
|
||||
return DWARFDie();
|
||||
}
|
||||
|
||||
uint32_t DIEBuilder::cloneDieReferenceAttribute(
|
||||
DIE &Die, const DWARFDie &InputDIE,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec, unsigned AttrSize,
|
||||
const DWARFFormValue &Val, DWARFUnit &U,
|
||||
std::vector<DWARFUnit *> &DUOffsetList) {
|
||||
uint64_t Ref = *Val.getAsReference();
|
||||
|
||||
DIE *NewRefDie = nullptr;
|
||||
DWARFUnit *RefUnit = nullptr;
|
||||
|
||||
DWARFDebugInfoEntry DDIEntry;
|
||||
DWARFDie RefDie =
|
||||
resolveDIEReference(Val, AttrSpec, RefUnit, DDIEntry, DUOffsetList);
|
||||
|
||||
if (!RefDie || AttrSpec.Attr == dwarf::DW_AT_sibling)
|
||||
return 0;
|
||||
|
||||
std::optional<uint32_t> UnitId = getUnitId(*RefUnit);
|
||||
std::optional<uint32_t> IsAllocId = getAllocDIEId(*RefUnit, RefDie);
|
||||
if (!IsAllocId.has_value())
|
||||
llvm_unreachable(
|
||||
"[error] encounter unexpected unallocated DIE. Should be alloc!");
|
||||
uint32_t DIEId = *IsAllocId;
|
||||
DIEInfo &DieInfo = getDIEInfo(*UnitId, DIEId);
|
||||
|
||||
if (!DieInfo.Die) {
|
||||
assert(Ref > InputDIE.getOffset());
|
||||
llvm_unreachable(
|
||||
"[error] encounter unexpected unallocated DIE. Should be alloc!");
|
||||
// We haven't cloned this DIE yet. Just create an empty one and
|
||||
// store it. It'll get really cloned when we process it.
|
||||
DieInfo.Die = DIE::get(DIEAlloc, dwarf::Tag(RefDie.getTag()));
|
||||
}
|
||||
NewRefDie = DieInfo.Die;
|
||||
|
||||
if (AttrSpec.Form == dwarf::DW_FORM_ref_addr) {
|
||||
// no matter forward reference or backward reference, we are supposed
|
||||
// to calculate them in `finish` due to the possible modification of
|
||||
// the DIE.
|
||||
DWARFDie CurDie = const_cast<DWARFDie &>(InputDIE);
|
||||
DIEInfo *CurDieInfo = &getDIEInfoByDwarfDie(&CurDie);
|
||||
ForwardReferences.push_back(
|
||||
std::make_pair(CurDieInfo, ForwardReferenceInfo(&DieInfo, AttrSpec)));
|
||||
|
||||
Die.addValue(DIEAlloc, AttrSpec.Attr, dwarf::DW_FORM_ref_addr,
|
||||
DIEInteger(0xDEADBEEF));
|
||||
return U.getRefAddrByteSize();
|
||||
}
|
||||
|
||||
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
|
||||
dwarf::Form(AttrSpec.Form), DIEEntry(*NewRefDie));
|
||||
|
||||
return AttrSize;
|
||||
}
|
||||
|
||||
uint32_t DIEBuilder::cloneStringAttribute(
|
||||
DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
unsigned AttrSize, const DWARFFormValue &Val, const DWARFUnit &U) {
|
||||
if (AttrSpec.Form == dwarf::DW_FORM_string) {
|
||||
auto StrAddr = Val.getAsCString();
|
||||
if (!StrAddr) {
|
||||
consumeError(StrAddr.takeError());
|
||||
return AttrSize;
|
||||
}
|
||||
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
|
||||
dwarf::DW_FORM_string,
|
||||
new (DIEAlloc) DIEInlineString(StrAddr.get(), DIEAlloc));
|
||||
} else {
|
||||
std::optional<uint64_t> OffsetIndex = Val.getRawUValue();
|
||||
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr), AttrSpec.Form,
|
||||
DIEInteger(*OffsetIndex));
|
||||
}
|
||||
return AttrSize;
|
||||
}
|
||||
|
||||
void DIEBuilder::cloneExpression(DataExtractor &Data,
|
||||
DWARFExpression &Expression, DWARFUnit &U,
|
||||
SmallVectorImpl<uint8_t> &OutputBuffer) {
|
||||
using Encoding = DWARFExpression::Operation::Encoding;
|
||||
|
||||
uint64_t OpOffset = 0;
|
||||
for (auto &Op : Expression) {
|
||||
auto Description = Op.getDescription();
|
||||
// DW_OP_const_type is variable-length and has 3
|
||||
// operands. Thus far we only support 2.
|
||||
if ((Description.Op.size() == 2 &&
|
||||
Description.Op[0] == Encoding::BaseTypeRef) ||
|
||||
(Description.Op.size() == 2 &&
|
||||
Description.Op[1] == Encoding::BaseTypeRef &&
|
||||
Description.Op[0] != Encoding::Size1))
|
||||
outs() << "BOLT-INFO: Unsupported DW_OP encoding.\n";
|
||||
|
||||
if ((Description.Op.size() == 1 &&
|
||||
Description.Op[0] == Encoding::BaseTypeRef) ||
|
||||
(Description.Op.size() == 2 &&
|
||||
Description.Op[1] == Encoding::BaseTypeRef &&
|
||||
Description.Op[0] == Encoding::Size1)) {
|
||||
// This code assumes that the other non-typeref operand fits into 1
|
||||
// byte.
|
||||
assert(OpOffset < Op.getEndOffset());
|
||||
uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;
|
||||
assert(ULEBsize <= 16);
|
||||
|
||||
// Copy over the operation.
|
||||
OutputBuffer.push_back(Op.getCode());
|
||||
uint64_t RefOffset;
|
||||
if (Description.Op.size() == 1) {
|
||||
RefOffset = Op.getRawOperand(0);
|
||||
} else {
|
||||
OutputBuffer.push_back(Op.getRawOperand(0));
|
||||
RefOffset = Op.getRawOperand(1);
|
||||
}
|
||||
uint32_t Offset = 0;
|
||||
if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
|
||||
DWARFDie RefDie = U.getDIEForOffset(RefOffset);
|
||||
std::optional<uint32_t> RefDieID = getAllocDIEId(U, RefOffset);
|
||||
std::optional<uint32_t> RefUnitID = getUnitId(U);
|
||||
if (RefDieID.has_value() && RefUnitID.has_value()) {
|
||||
DIEInfo &RefDieInfo = getDIEInfo(*RefUnitID, *RefDieID);
|
||||
if (DIE *Clone = RefDieInfo.Die)
|
||||
Offset = RefDie.getOffset();
|
||||
else
|
||||
errs() << "BOLT-WARNING: base type ref doesn't point to "
|
||||
"DW_TAG_base_type.\n";
|
||||
}
|
||||
}
|
||||
uint8_t ULEB[16];
|
||||
unsigned RealSize = encodeULEB128(Offset, ULEB, ULEBsize);
|
||||
if (RealSize > ULEBsize) {
|
||||
// Emit the generic type as a fallback.
|
||||
RealSize = encodeULEB128(0, ULEB, ULEBsize);
|
||||
errs() << "BOLT-WARNING: base type ref doesn't fit.\n";
|
||||
}
|
||||
assert(RealSize == ULEBsize && "padding failed");
|
||||
ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
|
||||
OutputBuffer.append(ULEBbytes.begin(), ULEBbytes.end());
|
||||
} else {
|
||||
// Copy over everything else unmodified.
|
||||
StringRef Bytes = Data.getData().slice(OpOffset, Op.getEndOffset());
|
||||
OutputBuffer.append(Bytes.begin(), Bytes.end());
|
||||
}
|
||||
OpOffset = Op.getEndOffset();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t DIEBuilder::cloneBlockAttribute(
|
||||
DIE &Die, DWARFUnit &U,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize, bool IsLittleEndian) {
|
||||
DIEValueList *Attr;
|
||||
DIEValue Value;
|
||||
DIELoc *Loc = nullptr;
|
||||
DIEBlock *Block = nullptr;
|
||||
|
||||
if (AttrSpec.Form == dwarf::DW_FORM_exprloc) {
|
||||
Loc = new (DIEAlloc) DIELoc;
|
||||
} else if (doesFormBelongToClass(AttrSpec.Form, DWARFFormValue::FC_Block,
|
||||
U.getVersion())) {
|
||||
Block = new (DIEAlloc) DIEBlock;
|
||||
} else {
|
||||
errs() << "BOLT-WARNING: Unexpected Form value in "
|
||||
"cloneBlockAttribute\n";
|
||||
return 0;
|
||||
}
|
||||
Attr = Loc ? static_cast<DIEValueList *>(Loc)
|
||||
: static_cast<DIEValueList *>(Block);
|
||||
|
||||
if (Loc)
|
||||
Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
|
||||
dwarf::Form(AttrSpec.Form), Loc);
|
||||
else
|
||||
Value = DIEValue(dwarf::Attribute(AttrSpec.Attr),
|
||||
dwarf::Form(AttrSpec.Form), Block);
|
||||
|
||||
SmallVector<uint8_t, 32> Buffer;
|
||||
ArrayRef<uint8_t> Bytes = *Val.getAsBlock();
|
||||
if (DWARFAttribute::mayHaveLocationExpr(AttrSpec.Attr) &&
|
||||
(Val.isFormClass(DWARFFormValue::FC_Block) ||
|
||||
Val.isFormClass(DWARFFormValue::FC_Exprloc))) {
|
||||
DataExtractor Data(StringRef((const char *)Bytes.data(), Bytes.size()),
|
||||
IsLittleEndian, U.getAddressByteSize());
|
||||
DWARFExpression Expr(Data, U.getAddressByteSize(),
|
||||
U.getFormParams().Format);
|
||||
cloneExpression(Data, Expr, U, Buffer);
|
||||
Bytes = Buffer;
|
||||
}
|
||||
for (auto Byte : Bytes)
|
||||
Attr->addValue(DIEAlloc, static_cast<dwarf::Attribute>(0),
|
||||
dwarf::DW_FORM_data1, DIEInteger(Byte));
|
||||
|
||||
if (Loc)
|
||||
Loc->setSize(Bytes.size());
|
||||
else
|
||||
Block->setSize(Bytes.size());
|
||||
|
||||
Die.addValue(DIEAlloc, Value);
|
||||
return AttrSize;
|
||||
}
|
||||
|
||||
uint32_t DIEBuilder::cloneAddressAttribute(
|
||||
DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, const DWARFUnit &U) {
|
||||
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
|
||||
dwarf::Form(AttrSpec.Form), DIEInteger(Val.getRawUValue()));
|
||||
return U.getAddressByteSize();
|
||||
}
|
||||
|
||||
uint32_t DIEBuilder::cloneRefsigAttribute(
|
||||
DIE &Die, DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
unsigned AttrSize, const DWARFFormValue &Val) {
|
||||
std::optional<uint64_t> SigVal = Val.getRawUValue();
|
||||
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
|
||||
dwarf::DW_FORM_ref_sig8, DIEInteger(*SigVal));
|
||||
return AttrSize;
|
||||
}
|
||||
|
||||
uint32_t DIEBuilder::cloneScalarAttribute(
|
||||
DIE &Die, const DWARFDie &InputDIE,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize) {
|
||||
uint64_t Value;
|
||||
|
||||
if (auto OptionalValue = Val.getAsUnsignedConstant())
|
||||
Value = *OptionalValue;
|
||||
else if (auto OptionalValue = Val.getAsSignedConstant())
|
||||
Value = *OptionalValue;
|
||||
else if (auto OptionalValue = Val.getAsSectionOffset())
|
||||
Value = *OptionalValue;
|
||||
else {
|
||||
errs() << "BOLT-WARNING: Unsupported scalar attribute form. Dropping "
|
||||
"attribute.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
|
||||
dwarf::Form(AttrSpec.Form), DIEInteger(Value));
|
||||
return AttrSize;
|
||||
}
|
||||
|
||||
uint32_t DIEBuilder::cloneLoclistAttrubute(
|
||||
DIE &Die, const DWARFDie &InputDIE,
|
||||
DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
const DWARFFormValue &Val, unsigned AttrSize) {
|
||||
uint64_t Value;
|
||||
|
||||
if (auto OptionalValue = Val.getAsUnsignedConstant())
|
||||
Value = *OptionalValue;
|
||||
else if (auto OptionalValue = Val.getAsSignedConstant())
|
||||
Value = *OptionalValue;
|
||||
else if (auto OptionalValue = Val.getAsSectionOffset())
|
||||
Value = *OptionalValue;
|
||||
else {
|
||||
errs() << "BOLT-WARNING: Unsupported scalar attribute form. Dropping "
|
||||
"attribute.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
Die.addValue(DIEAlloc, dwarf::Attribute(AttrSpec.Attr),
|
||||
dwarf::Form(AttrSpec.Form), DIELocList(Value));
|
||||
return AttrSize;
|
||||
}
|
||||
|
||||
uint32_t DIEBuilder::cloneAttribute(
|
||||
DIE &Die, const DWARFDie &InputDIE, DWARFUnit &U, const DWARFFormValue &Val,
|
||||
const DWARFAbbreviationDeclaration::AttributeSpec AttrSpec,
|
||||
unsigned AttrSize, bool IsLittleEndian,
|
||||
std::vector<DWARFUnit *> &DUOffsetList) {
|
||||
switch (AttrSpec.Form) {
|
||||
case dwarf::DW_FORM_strp:
|
||||
case dwarf::DW_FORM_string:
|
||||
case dwarf::DW_FORM_strx:
|
||||
case dwarf::DW_FORM_strx1:
|
||||
case dwarf::DW_FORM_strx2:
|
||||
case dwarf::DW_FORM_strx3:
|
||||
case dwarf::DW_FORM_strx4:
|
||||
case dwarf::DW_FORM_GNU_str_index:
|
||||
case dwarf::DW_FORM_line_strp:
|
||||
return cloneStringAttribute(Die, AttrSpec, AttrSize, Val, U);
|
||||
case dwarf::DW_FORM_ref_addr:
|
||||
case dwarf::DW_FORM_ref1:
|
||||
case dwarf::DW_FORM_ref2:
|
||||
case dwarf::DW_FORM_ref4:
|
||||
case dwarf::DW_FORM_ref8:
|
||||
return cloneDieReferenceAttribute(Die, InputDIE, AttrSpec, AttrSize, Val, U,
|
||||
DUOffsetList);
|
||||
case dwarf::DW_FORM_block:
|
||||
case dwarf::DW_FORM_block1:
|
||||
case dwarf::DW_FORM_block2:
|
||||
case dwarf::DW_FORM_block4:
|
||||
case dwarf::DW_FORM_exprloc:
|
||||
return cloneBlockAttribute(Die, U, AttrSpec, Val, AttrSize, IsLittleEndian);
|
||||
case dwarf::DW_FORM_addr:
|
||||
case dwarf::DW_FORM_addrx:
|
||||
case dwarf::DW_FORM_GNU_addr_index:
|
||||
return cloneAddressAttribute(Die, AttrSpec, Val, U);
|
||||
case dwarf::DW_FORM_data1:
|
||||
case dwarf::DW_FORM_data2:
|
||||
case dwarf::DW_FORM_data4:
|
||||
case dwarf::DW_FORM_data8:
|
||||
case dwarf::DW_FORM_udata:
|
||||
case dwarf::DW_FORM_sdata:
|
||||
case dwarf::DW_FORM_sec_offset:
|
||||
case dwarf::DW_FORM_rnglistx:
|
||||
case dwarf::DW_FORM_flag:
|
||||
case dwarf::DW_FORM_flag_present:
|
||||
case dwarf::DW_FORM_implicit_const:
|
||||
return cloneScalarAttribute(Die, InputDIE, AttrSpec, Val, AttrSize);
|
||||
case dwarf::DW_FORM_loclistx:
|
||||
return cloneLoclistAttrubute(Die, InputDIE, AttrSpec, Val, AttrSize);
|
||||
case dwarf::DW_FORM_ref_sig8:
|
||||
return cloneRefsigAttribute(Die, AttrSpec, AttrSize, Val);
|
||||
default:
|
||||
std::string Msg = "Unsupported attribute form " +
|
||||
dwarf::FormEncodingString(AttrSpec.Form).str() +
|
||||
" in cloneAttribute. Dropping.";
|
||||
llvm_unreachable(Msg.c_str());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
void DIEBuilder::assignAbbrev(DIEAbbrev &Abbrev) {
|
||||
// Check the set for priors.
|
||||
FoldingSetNodeID ID;
|
||||
Abbrev.Profile(ID);
|
||||
void *InsertToken;
|
||||
DIEAbbrev *InSet = AbbreviationsSet.FindNodeOrInsertPos(ID, InsertToken);
|
||||
|
||||
// If it's newly added.
|
||||
if (InSet) {
|
||||
// Assign existing abbreviation number.
|
||||
Abbrev.setNumber(InSet->getNumber());
|
||||
} else {
|
||||
// Add to abbreviation list.
|
||||
Abbreviations.push_back(
|
||||
std::make_unique<DIEAbbrev>(Abbrev.getTag(), Abbrev.hasChildren()));
|
||||
for (const auto &Attr : Abbrev.getData())
|
||||
Abbreviations.back()->AddAttribute(Attr.getAttribute(), Attr.getForm());
|
||||
AbbreviationsSet.InsertNode(Abbreviations.back().get(), InsertToken);
|
||||
// Assign the unique abbreviation number.
|
||||
Abbrev.setNumber(Abbreviations.size());
|
||||
Abbreviations.back()->setNumber(Abbreviations.size());
|
||||
}
|
||||
}
|
||||
|
||||
void DIEBuilder::generateAbbrevs() {
|
||||
if (!IsBuilt)
|
||||
return;
|
||||
|
||||
for (DWARFUnit *DU : DUList) {
|
||||
DIE *UnitDIE = getUnitDIEbyUnit(*DU);
|
||||
generateUnitAbbrevs(UnitDIE);
|
||||
}
|
||||
}
|
||||
|
||||
void DIEBuilder::generateUnitAbbrevs(DIE *Die) {
|
||||
DIEAbbrev NewAbbrev = Die->generateAbbrev();
|
||||
|
||||
if (Die->hasChildren())
|
||||
NewAbbrev.setChildrenFlag(dwarf::DW_CHILDREN_yes);
|
||||
assignAbbrev(NewAbbrev);
|
||||
Die->setAbbrevNumber(NewAbbrev.getNumber());
|
||||
|
||||
for (auto &Child : Die->children()) {
|
||||
generateUnitAbbrevs(&Child);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace bolt
|
||||
} // namespace llvm
|
||||
@@ -12,14 +12,18 @@
|
||||
|
||||
#include "bolt/Core/DebugData.h"
|
||||
#include "bolt/Core/BinaryContext.h"
|
||||
#include "bolt/Core/DIEBuilder.h"
|
||||
#include "bolt/Rewrite/RewriteInstance.h"
|
||||
#include "bolt/Utils/Utils.h"
|
||||
#include "llvm/BinaryFormat/Dwarf.h"
|
||||
#include "llvm/CodeGen/DIE.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFDebugAddr.h"
|
||||
#include "llvm/MC/MCAssembler.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCObjectStreamer.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/EndianStream.h"
|
||||
#include "llvm/Support/LEB128.h"
|
||||
@@ -43,6 +47,16 @@ class MCSymbol;
|
||||
|
||||
namespace bolt {
|
||||
|
||||
static void replaceLocValbyForm(DIEBuilder &DIEBldr, DIE &Die, DIEValue DIEVal,
|
||||
dwarf::Form Format, uint64_t NewVal) {
|
||||
if (Format == dwarf::DW_FORM_loclistx)
|
||||
DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,
|
||||
DIELocList(NewVal));
|
||||
else
|
||||
DIEBldr.replaceValue(&Die, DIEVal.getAttribute(), Format,
|
||||
DIEInteger(NewVal));
|
||||
}
|
||||
|
||||
std::optional<AttrInfo>
|
||||
findAttributeInfo(const DWARFDie DIE,
|
||||
const DWARFAbbreviationDeclaration *AbbrevDecl,
|
||||
@@ -580,12 +594,11 @@ void DebugLocWriter::init() {
|
||||
}
|
||||
|
||||
uint32_t DebugLocWriter::LocSectionOffset = 0;
|
||||
void DebugLocWriter::addList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
|
||||
DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter) {
|
||||
const uint64_t AttrOffset = AttrVal.Offset;
|
||||
void DebugLocWriter::addList(DIEBuilder &DIEBldr, DIE &Die, DIEValue &AttrInfo,
|
||||
DebugLocationsVector &LocList) {
|
||||
if (LocList.empty()) {
|
||||
DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset);
|
||||
replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),
|
||||
DebugLocWriter::EmptyListOffset);
|
||||
return;
|
||||
}
|
||||
// Since there is a separate DebugLocWriter for each thread,
|
||||
@@ -605,8 +618,9 @@ void DebugLocWriter::addList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
|
||||
}
|
||||
LocStream->write_zeros(16);
|
||||
LocSectionOffset += 16;
|
||||
LocListDebugInfoPatches.push_back({AttrOffset, EntryOffset});
|
||||
DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset);
|
||||
LocListDebugInfoPatches.push_back({0xdeadbeee, EntryOffset}); // never seen
|
||||
// use
|
||||
replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
|
||||
}
|
||||
|
||||
std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
|
||||
@@ -614,8 +628,7 @@ std::unique_ptr<DebugBufferVector> DebugLocWriter::getBuffer() {
|
||||
}
|
||||
|
||||
// DWARF 4: 2.6.2
|
||||
void DebugLocWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter) {}
|
||||
void DebugLocWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {}
|
||||
|
||||
static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {
|
||||
support::endian::write(Stream, static_cast<uint32_t>(4), support::little);
|
||||
@@ -629,14 +642,15 @@ static void writeEmptyListDwarf5(raw_svector_ostream &Stream) {
|
||||
Stream, static_cast<uint8_t>(dwarf::DW_LLE_end_of_list), support::little);
|
||||
}
|
||||
|
||||
static void writeLegacyLocList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
|
||||
DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
static void writeLegacyLocList(DIEValue &AttrInfo,
|
||||
DebugLocationsVector &LocList,
|
||||
DIEBuilder &DIEBldr, DIE &Die,
|
||||
DebugAddrWriter &AddrWriter,
|
||||
DebugBufferVector &LocBuffer, DWARFUnit &CU,
|
||||
DebugBufferVector LocBuffer, DWARFUnit &CU,
|
||||
raw_svector_ostream &LocStream) {
|
||||
const uint64_t AttrOffset = AttrVal.Offset;
|
||||
if (LocList.empty()) {
|
||||
DebugInfoPatcher.addLE32Patch(AttrOffset, DebugLocWriter::EmptyListOffset);
|
||||
replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(),
|
||||
DebugLocWriter::EmptyListOffset);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -659,21 +673,20 @@ static void writeLegacyLocList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
|
||||
support::endian::write(LocStream,
|
||||
static_cast<uint8_t>(dwarf::DW_LLE_end_of_list),
|
||||
support::little);
|
||||
DebugInfoPatcher.addLE32Patch(AttrOffset, EntryOffset);
|
||||
replaceLocValbyForm(DIEBldr, Die, AttrInfo, AttrInfo.getForm(), EntryOffset);
|
||||
}
|
||||
|
||||
static void writeDWARF5LocList(
|
||||
uint32_t &NumberOfEntries, AttrInfo &AttrVal, DebugLocationsVector &LocList,
|
||||
DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter,
|
||||
DebugAddrWriter &AddrWriter, DebugBufferVector &LocBodyBuffer,
|
||||
std::vector<uint32_t> &RelativeLocListOffsets, DWARFUnit &CU,
|
||||
raw_svector_ostream &LocBodyStream) {
|
||||
if (AttrVal.V.getForm() != dwarf::DW_FORM_loclistx) {
|
||||
AbbrevWriter.addAttributePatch(CU, AttrVal.AbbrevDecl,
|
||||
dwarf::DW_AT_location, dwarf::DW_AT_location,
|
||||
dwarf::DW_FORM_loclistx);
|
||||
}
|
||||
DebugInfoPatcher.addUDataPatch(AttrVal.Offset, NumberOfEntries, AttrVal.Size);
|
||||
static void writeDWARF5LocList(uint32_t &NumberOfEntries, DIEValue &AttrInfo,
|
||||
DebugLocationsVector &LocList, DIE &Die,
|
||||
DIEBuilder &DIEBldr, DebugAddrWriter &AddrWriter,
|
||||
DebugBufferVector &LocBodyBuffer,
|
||||
std::vector<uint32_t> &RelativeLocListOffsets,
|
||||
DWARFUnit &CU,
|
||||
raw_svector_ostream &LocBodyStream) {
|
||||
|
||||
replaceLocValbyForm(DIEBldr, Die, AttrInfo, dwarf::DW_FORM_loclistx,
|
||||
NumberOfEntries);
|
||||
|
||||
RelativeLocListOffsets.push_back(LocBodyBuffer.size());
|
||||
++NumberOfEntries;
|
||||
if (LocList.empty()) {
|
||||
@@ -716,30 +729,29 @@ static void writeDWARF5LocList(
|
||||
support::little);
|
||||
}
|
||||
|
||||
void DebugLoclistWriter::addList(AttrInfo &AttrVal,
|
||||
DebugLocationsVector &LocList,
|
||||
DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter) {
|
||||
void DebugLoclistWriter::addList(DIEBuilder &DIEBldr, DIE &Die,
|
||||
DIEValue &AttrInfo,
|
||||
DebugLocationsVector &LocList) {
|
||||
if (DwarfVersion < 5)
|
||||
writeLegacyLocList(AttrVal, LocList, DebugInfoPatcher, *AddrWriter,
|
||||
*LocBuffer, CU, *LocStream);
|
||||
writeLegacyLocList(AttrInfo, LocList, DIEBldr, Die, *AddrWriter, *LocBuffer,
|
||||
CU, *LocStream);
|
||||
else
|
||||
writeDWARF5LocList(NumberOfEntries, AttrVal, LocList, DebugInfoPatcher,
|
||||
AbbrevWriter, *AddrWriter, *LocBodyBuffer,
|
||||
RelativeLocListOffsets, CU, *LocBodyStream);
|
||||
writeDWARF5LocList(NumberOfEntries, AttrInfo, LocList, Die, DIEBldr,
|
||||
*AddrWriter, *LocBodyBuffer, RelativeLocListOffsets, CU,
|
||||
*LocBodyStream);
|
||||
}
|
||||
|
||||
uint32_t DebugLoclistWriter::LoclistBaseOffset = 0;
|
||||
void DebugLoclistWriter::finalizeDWARF5(
|
||||
DebugInfoBinaryPatcher &DebugInfoPatcher, DebugAbbrevWriter &AbbrevWriter) {
|
||||
void DebugLoclistWriter::finalizeDWARF5(DIEBuilder &DIEBldr, DIE &Die) {
|
||||
if (LocBodyBuffer->empty()) {
|
||||
std::optional<AttrInfo> AttrInfoVal =
|
||||
findAttributeInfo(CU.getUnitDIE(), dwarf::DW_AT_loclists_base);
|
||||
DIEValue LocListBaseAttrInfo =
|
||||
Die.findAttribute(dwarf::DW_AT_loclists_base);
|
||||
// Pointing to first one, because it doesn't matter. There are no uses of it
|
||||
// in this CU.
|
||||
if (!isSplitDwarf() && AttrInfoVal)
|
||||
DebugInfoPatcher.addLE32Patch(AttrInfoVal->Offset,
|
||||
getDWARF5RngListLocListHeaderSize());
|
||||
if (!isSplitDwarf() && LocListBaseAttrInfo.getType())
|
||||
DIEBldr.replaceValue(&Die, dwarf::DW_AT_loclists_base,
|
||||
LocListBaseAttrInfo.getForm(),
|
||||
DIEInteger(getDWARF5RngListLocListHeaderSize()));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -764,17 +776,16 @@ void DebugLoclistWriter::finalizeDWARF5(
|
||||
*LocStream << *LocBodyBuffer;
|
||||
|
||||
if (!isSplitDwarf()) {
|
||||
if (std::optional<AttrInfo> AttrInfoVal =
|
||||
findAttributeInfo(CU.getUnitDIE(), dwarf::DW_AT_loclists_base))
|
||||
DebugInfoPatcher.addLE32Patch(AttrInfoVal->Offset,
|
||||
LoclistBaseOffset +
|
||||
getDWARF5RngListLocListHeaderSize());
|
||||
else {
|
||||
AbbrevWriter.addAttribute(
|
||||
CU, CU.getUnitDIE().getAbbreviationDeclarationPtr(),
|
||||
dwarf::DW_AT_loclists_base, dwarf::DW_FORM_sec_offset);
|
||||
DebugInfoPatcher.insertNewEntry(CU.getUnitDIE(),
|
||||
LoclistBaseOffset + Header->size());
|
||||
DIEValue LocListBaseAttrInfo =
|
||||
Die.findAttribute(dwarf::DW_AT_loclists_base);
|
||||
if (LocListBaseAttrInfo.getType()) {
|
||||
DIEBldr.replaceValue(
|
||||
&Die, dwarf::DW_AT_loclists_base, LocListBaseAttrInfo.getForm(),
|
||||
DIEInteger(LoclistBaseOffset + getDWARF5RngListLocListHeaderSize()));
|
||||
} else {
|
||||
DIEBldr.addValue(&Die, dwarf::DW_AT_loclists_base,
|
||||
dwarf::DW_FORM_sec_offset,
|
||||
DIEInteger(LoclistBaseOffset + Header->size()));
|
||||
}
|
||||
LoclistBaseOffset += LocBuffer->size();
|
||||
}
|
||||
@@ -783,10 +794,9 @@ void DebugLoclistWriter::finalizeDWARF5(
|
||||
clearList(*LocBodyBuffer);
|
||||
}
|
||||
|
||||
void DebugLoclistWriter::finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
|
||||
DebugAbbrevWriter &AbbrevWriter) {
|
||||
void DebugLoclistWriter::finalize(DIEBuilder &DIEBldr, DIE &Die) {
|
||||
if (DwarfVersion >= 5)
|
||||
finalizeDWARF5(DebugInfoPatcher, AbbrevWriter);
|
||||
finalizeDWARF5(DIEBldr, Die);
|
||||
}
|
||||
|
||||
DebugAddrWriter *DebugLoclistWriter::AddrWriter = nullptr;
|
||||
|
||||
@@ -5,6 +5,8 @@ set(LLVM_LINK_COMPONENTS
|
||||
MC
|
||||
Object
|
||||
Support
|
||||
DWARFLinker
|
||||
AsmPrinter
|
||||
TargetParser
|
||||
)
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -257,7 +257,8 @@ constexpr const char *RewriteInstance::SectionsToOverwrite[];
|
||||
std::vector<std::string> RewriteInstance::DebugSectionsToOverwrite = {
|
||||
".debug_abbrev", ".debug_aranges", ".debug_line", ".debug_line_str",
|
||||
".debug_loc", ".debug_loclists", ".debug_ranges", ".debug_rnglists",
|
||||
".gdb_index", ".debug_addr", ".pseudo_probe"};
|
||||
".gdb_index", ".debug_addr", ".debug_abbrev", ".debug_info",
|
||||
".debug_types", ".pseudo_probe"};
|
||||
|
||||
const char RewriteInstance::TimerGroupName[] = "rewrite";
|
||||
const char RewriteInstance::TimerGroupDesc[] = "Rewrite passes";
|
||||
|
||||
@@ -13,7 +13,7 @@ CHECK-NEXT: DW_AT_stmt_list (0x00000000)
|
||||
CHECK-NEXT: DW_AT_low_pc (0x0000000000000000)
|
||||
CHECK-NEXT: DW_AT_ranges
|
||||
CHECK-NEXT: [0x0000000000[[#%x,ADDR:]],
|
||||
CHECK-SAME: 0x0000000000[[#ADDR+1]]))
|
||||
CHECK-SAME: 0x0000000000[[#ADDR+1]]))
|
||||
CHECK-NEXT: DW_AT_name ("{{.*}}asm_foo.s")
|
||||
|
||||
# Check .debug_aranges was updated for asm module
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
# POSTCHECK-SAME: DW_FORM_addr
|
||||
# POSTCHECK-SAME: (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges
|
||||
# POSTCHECK-SAME: DW_FORM_sec_offset
|
||||
# POSTCHECK-SAME: DW_FORM_data4
|
||||
# POSTCHECK-SAME: (0x[[#OFFSET]]
|
||||
# POSTCHECK-NEXT: [0x[[#ADDR_1_BEGIN]]
|
||||
# POSTCHECK-SAME: 0x[[#ADDR_1_END]]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# REQUIRES: system-linux
|
||||
# UNSUPPORTED: system-linux
|
||||
; RUN: rm -rf %t
|
||||
; RUN: mkdir %t
|
||||
; RUN: cd %t
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# REQUIRES: system-linux
|
||||
# UNSUPPORTED: true
|
||||
; RUN: rm -rf %t
|
||||
; RUN: mkdir %t
|
||||
; RUN: cd %t
|
||||
|
||||
@@ -226,15 +226,15 @@
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_subprogram [7]
|
||||
# POSTCHECK: DW_TAG_subprogram [22]
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_variable [9]
|
||||
# POSTCHECK: DW_TAG_variable [24]
|
||||
# POSTCHECK-NEXT: DW_AT_location [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [10]
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [25]
|
||||
# POSTCHECK-NEXT: DW_AT_abstract_origin
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
@@ -242,7 +242,7 @@
|
||||
|
||||
# helper1.cpp
|
||||
# POSTCHECK: version = 0x0005
|
||||
# POSTCHECK: DW_TAG_compile_unit [1] *
|
||||
# POSTCHECK: DW_TAG_compile_unit [26] *
|
||||
# POSTCHECK-NEXT: DW_AT_producer
|
||||
# POSTCHECK-NEXT: DW_AT_language
|
||||
# POSTCHECK-NEXT: DW_AT_name
|
||||
@@ -255,22 +255,22 @@
|
||||
# POSTCHECK-NEXT: DW_AT_addr_base [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: DW_AT_loclists_base [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: DW_AT_rnglists_base [DW_FORM_sec_offset]
|
||||
# POSTCHECK: DW_TAG_variable [2]
|
||||
# POSTCHECK: DW_TAG_variable [27]
|
||||
# POSTCHECK-NEXT: DW_AT_name
|
||||
# POSTCHECK-NEXT: DW_AT_type
|
||||
# POSTCHECK-NEXT: DW_AT_external
|
||||
# POSTCHECK-NEXT: DW_AT_decl_file
|
||||
# POSTCHECK-NEXT: DW_AT_decl_line
|
||||
# POSTCHECK: DW_AT_location [DW_FORM_exprloc] (DW_OP_addrx 0x2)
|
||||
# POSTCHECK: DW_TAG_subprogram [7]
|
||||
# POSTCHECK: DW_TAG_subprogram [29]
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000001)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x1)
|
||||
# POSTCHECK-NEXT: [0x[[#ADDRB]], 0x[[#ADDRB + 0x4]]
|
||||
# POSTCHECK: DW_TAG_variable [9]
|
||||
# POSTCHECK: DW_TAG_variable [10]
|
||||
# POSTCHECK-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0)
|
||||
# POSTCHECK-NEXT: [0x[[#ADDRB]], 0x[[#ADDRB + 0x3]]
|
||||
# POSTCHECK-NEXT: [0x[[#ADDRB + 0x3]], 0x[[#ADDRB + 0x4]]
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [10]
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [31]
|
||||
# POSTCHECK-NEXT: DW_AT_abstract_origin
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addrx] (indexed (00000001)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_rnglistx] (indexed (0x2) rangelist
|
||||
@@ -278,7 +278,7 @@
|
||||
|
||||
# helper2.cpp
|
||||
# POSTCHECK: version = 0x0004
|
||||
# POSTCHECK: DW_TAG_compile_unit [1] *
|
||||
# POSTCHECK: DW_TAG_compile_unit [17] *
|
||||
# POSTCHECK-NEXT: DW_AT_producer
|
||||
# POSTCHECK-NEXT: DW_AT_language
|
||||
# POSTCHECK-NEXT: DW_AT_name
|
||||
@@ -287,15 +287,15 @@
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_subprogram [7]
|
||||
# POSTCHECK: DW_TAG_subprogram [22]
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_variable [9]
|
||||
# POSTCHECK: DW_TAG_variable [24]
|
||||
# POSTCHECK-NEXT: DW_AT_location [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [10]
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [25]
|
||||
# POSTCHECK-NEXT: DW_AT_abstract_origin
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
# POSTCHECK: DW_TAG_compile_unit
|
||||
# POSTCHECK: DW_AT_loclists_base [DW_FORM_sec_offset] (0x00000045)
|
||||
# POSTCHECK: DW_TAG_variable [11]
|
||||
# POSTCHECK: DW_TAG_variable [5]
|
||||
# POSTCHECK-NEXT: DW_AT_location [DW_FORM_loclistx] (indexed (0x0)
|
||||
# POSTCHECK-NEXT: [0x[[#ADDR7]]
|
||||
# POSTCHECK-SAME: 0x[[#ADDR7 + 0x3]]
|
||||
|
||||
@@ -170,15 +170,15 @@
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_subprogram [7]
|
||||
# POSTCHECK: DW_TAG_subprogram [8]
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_variable [9]
|
||||
# POSTCHECK: DW_TAG_variable [10]
|
||||
# POSTCHECK-NEXT: DW_AT_location [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [10]
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [11]
|
||||
# POSTCHECK-NEXT: DW_AT_abstract_origin
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
@@ -186,7 +186,7 @@
|
||||
|
||||
# helper1.cpp
|
||||
# POSTCHECK: version = 0x0005
|
||||
# POSTCHECK: DW_TAG_skeleton_unit [1]
|
||||
# POSTCHECK: DW_TAG_skeleton_unit [12]
|
||||
# POSTCHECK-NEXT: DW_AT_stmt_list [DW_FORM_sec_offset] (0x000000fe)
|
||||
# POSTCHECK-NEXT: DW_AT_str_offsets_base [DW_FORM_sec_offset] (0x00000018)
|
||||
# POSTCHECK-NEXT: DW_AT_comp_dir [DW_FORM_strx1] (indexed (00000000) string = ".")
|
||||
@@ -200,7 +200,7 @@
|
||||
|
||||
# helper2.cpp
|
||||
# POSTCHECK: version = 0x0004
|
||||
# POSTCHECK: DW_TAG_compile_unit [1] *
|
||||
# POSTCHECK: DW_TAG_compile_unit [2] *
|
||||
# POSTCHECK-NEXT: DW_AT_producer
|
||||
# POSTCHECK-NEXT: DW_AT_language
|
||||
# POSTCHECK-NEXT: DW_AT_name
|
||||
@@ -209,15 +209,15 @@
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_subprogram [7]
|
||||
# POSTCHECK: DW_TAG_subprogram [8]
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_variable [9]
|
||||
# POSTCHECK: DW_TAG_variable [10]
|
||||
# POSTCHECK-NEXT: DW_AT_location [DW_FORM_sec_offset]
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK-NEXT: [0x
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [10]
|
||||
# POSTCHECK: DW_TAG_inlined_subroutine [11]
|
||||
# POSTCHECK-NEXT: DW_AT_abstract_origin
|
||||
# POSTCHECK-NEXT: DW_AT_low_pc [DW_FORM_addr] (0x0000000000000000)
|
||||
# POSTCHECK-NEXT: DW_AT_ranges [DW_FORM_sec_offset]
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
# CHECK-NEXT: DW_AT_low_pc
|
||||
# CHECK-NEXT: DW_AT_ranges
|
||||
# CHECK: 0x0000001c:
|
||||
# CHECK-SAME: abbr_offset = 0x0017
|
||||
# CHECK-SAME: abbr_offset = 0x0000
|
||||
# CHECK-EMPTY:
|
||||
# CHECK: DW_TAG_compile_unit
|
||||
# CHECK-NEXT: DW_AT_stmt_list
|
||||
# CHECK-NEXT: DW_AT_low_pc
|
||||
# CHECK-NEXT: DW_AT_ranges
|
||||
# CHECK: 0x00000039:
|
||||
# CHECK: 0x00000038:
|
||||
# CHECK-SAME: abbr_offset = 0x0000
|
||||
# CHECK-EMPTY:
|
||||
# CHECK-NEXT: DW_TAG_compile_unit
|
||||
|
||||
@@ -566,6 +566,7 @@ public:
|
||||
|
||||
void push_back(T &N) { IntrusiveBackListBase::push_back(N); }
|
||||
void push_front(T &N) { IntrusiveBackListBase::push_front(N); }
|
||||
|
||||
T &back() { return *static_cast<T *>(Last); }
|
||||
const T &back() const { return *static_cast<T *>(Last); }
|
||||
T &front() {
|
||||
@@ -594,6 +595,25 @@ public:
|
||||
Other.Last = nullptr;
|
||||
}
|
||||
|
||||
bool deleteNode(T &N) {
|
||||
if (Last == &N) {
|
||||
Last = Last->Next.getPointer();
|
||||
Last->Next.setInt(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
Node *cur = Last;
|
||||
while (cur && cur->Next.getPointer()) {
|
||||
if (cur->Next.getPointer() == &N) {
|
||||
cur->Next.setPointer(cur->Next.getPointer()->Next.getPointer());
|
||||
return true;
|
||||
}
|
||||
cur = cur->Next.getPointer();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
class const_iterator;
|
||||
class iterator
|
||||
: public iterator_facade_base<iterator, std::forward_iterator_tag, T> {
|
||||
@@ -723,10 +743,63 @@ public:
|
||||
}
|
||||
template <class T>
|
||||
value_iterator addValue(BumpPtrAllocator &Alloc, dwarf::Attribute Attribute,
|
||||
dwarf::Form Form, T &&Value) {
|
||||
dwarf::Form Form, T &&Value) {
|
||||
return addValue(Alloc, DIEValue(Attribute, Form, std::forward<T>(Value)));
|
||||
}
|
||||
|
||||
/* zr33: add method here */
|
||||
template <class T>
|
||||
bool replaceValue(BumpPtrAllocator &Alloc, dwarf::Attribute Attribute,
|
||||
dwarf::Attribute NewAttribute, dwarf::Form Form,
|
||||
T &&NewValue) {
|
||||
for (llvm::DIEValue &val : values()) {
|
||||
if (val.getAttribute() == Attribute) {
|
||||
val = *new (Alloc)
|
||||
DIEValue(NewAttribute, Form, std::forward<T>(NewValue));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
bool replaceValue(BumpPtrAllocator &Alloc, dwarf::Attribute Attribute,
|
||||
dwarf::Form Form, T &&NewValue) {
|
||||
for (llvm::DIEValue &val : values()) {
|
||||
if (val.getAttribute() == Attribute) {
|
||||
val = *new (Alloc) DIEValue(Attribute, Form, std::forward<T>(NewValue));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool replaceValue(BumpPtrAllocator &Alloc, dwarf::Attribute Attribute,
|
||||
dwarf::Form Form, DIEValue &NewValue) {
|
||||
for (llvm::DIEValue &val : values()) {
|
||||
if (val.getAttribute() == Attribute) {
|
||||
val = NewValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool deleteValue(dwarf::Attribute Attribute) {
|
||||
|
||||
for (auto &node : List) {
|
||||
if (node.V.getAttribute() == Attribute) {
|
||||
return List.deleteNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
/* end */
|
||||
|
||||
/// Take ownership of the nodes in \p Other, and append them to the back of
|
||||
/// the list.
|
||||
void takeValues(DIEValueList &Other) { List.takeNodes(Other.List); }
|
||||
|
||||
@@ -38,7 +38,6 @@ public:
|
||||
FC_Exprloc
|
||||
};
|
||||
|
||||
private:
|
||||
struct ValueType {
|
||||
ValueType() { uval = 0; }
|
||||
ValueType(int64_t V) : sval(V) {}
|
||||
@@ -51,10 +50,11 @@ private:
|
||||
const char *cstr;
|
||||
};
|
||||
const uint8_t *data = nullptr;
|
||||
uint64_t SectionIndex; /// Section index for reference forms.
|
||||
uint64_t SectionIndex; /// Section index for reference forms.
|
||||
};
|
||||
|
||||
dwarf::Form Form; /// Form for this value.
|
||||
private:
|
||||
dwarf::Form Form; /// Form for this value.
|
||||
dwarf::DwarfFormat Format =
|
||||
dwarf::DWARF32; /// Remember the DWARF format at extract time.
|
||||
ValueType Value; /// Contains all data for the form.
|
||||
@@ -73,6 +73,9 @@ public:
|
||||
ArrayRef<uint8_t> D);
|
||||
static DWARFFormValue createFromUnit(dwarf::Form F, const DWARFUnit *Unit,
|
||||
uint64_t *OffsetPtr);
|
||||
static std::optional<object::SectionedAddress>
|
||||
getAsSectionedAddress(const ValueType &Val, const dwarf::Form Form,
|
||||
const DWARFUnit *U);
|
||||
|
||||
dwarf::Form getForm() const { return Form; }
|
||||
uint64_t getRawUValue() const { return Value.uval; }
|
||||
|
||||
@@ -637,9 +637,9 @@ std::optional<uint64_t> DWARFFormValue::getAsAddress() const {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::optional<object::SectionedAddress>
|
||||
DWARFFormValue::getAsSectionedAddress() const {
|
||||
if (!isFormClass(FC_Address))
|
||||
std::optional<object::SectionedAddress> DWARFFormValue::getAsSectionedAddress(
|
||||
const ValueType &Value, const dwarf::Form Form, const DWARFUnit *U) {
|
||||
if (!doesFormBelongToClass(Form, FC_Address, U ? U->getVersion() : 3))
|
||||
return std::nullopt;
|
||||
bool AddrOffset = Form == dwarf::DW_FORM_LLVM_addrx_offset;
|
||||
if (Form == DW_FORM_GNU_addr_index || Form == DW_FORM_addrx ||
|
||||
@@ -660,6 +660,11 @@ DWARFFormValue::getAsSectionedAddress() const {
|
||||
return {{Value.uval, Value.SectionIndex}};
|
||||
}
|
||||
|
||||
std::optional<object::SectionedAddress>
|
||||
DWARFFormValue::getAsSectionedAddress() const {
|
||||
return getAsSectionedAddress(Value, Form, U);
|
||||
}
|
||||
|
||||
std::optional<uint64_t> DWARFFormValue::getAsReference() const {
|
||||
if (auto R = getAsRelativeReference())
|
||||
return R->Unit ? R->Unit->getOffset() + R->Offset : R->Offset;
|
||||
|
||||
Reference in New Issue
Block a user