Skip to content

Commit

Permalink
[BOLT]DWARF] Eagerly write out loclists
Browse files Browse the repository at this point in the history
Taking advantage of us being able to re-write .debug_info to reduce memory
footprint loclists. Writing out loc-list as they are added, similar to how
we handle ranges.

Collected on clang-14
trunk
4:41.20 real,   389.50 user,    59.50 sys,      0 amem, 38412532 mmem
4:30.08 real,   376.10 user,    63.75 sys,      0 amem, 38477844 mmem
4:25.58 real,   373.76 user,    54.71 sys,      0 amem, 38439660 mmem
diff
4:34.66 real,   392.83 user,    57.73 sys,      0 amem, 38382560 mmem
4:35.96 real,   377.70 user,    58.62 sys,      0 amem, 38255840 mmem
4:27.61 real,    390.18 user,    57.02 sys,      0 amem, 38223224 mmem

Reviewed By: maksfb

Differential Revision: https://reviews.llvm.org/D126999
  • Loading branch information
ayermolo committed Jun 8, 2022
1 parent f4da30b commit 1c6dc43
Show file tree
Hide file tree
Showing 8 changed files with 1,122 additions and 274 deletions.
126 changes: 68 additions & 58 deletions bolt/include/bolt/Core/DebugData.h
Expand Up @@ -34,6 +34,30 @@ namespace llvm {

namespace bolt {

struct AttrInfo {
DWARFFormValue V;
const DWARFAbbreviationDeclaration *AbbrevDecl;
uint64_t Offset;
uint32_t Size; // Size of the attribute.
};

/// Finds attributes FormValue and Offset.
///
/// \param DIE die to look up in.
/// \param AbbrevDecl abbrev declaration for the die.
/// \param Index an index in Abbrev declaration entry.
Optional<AttrInfo>
findAttributeInfo(const DWARFDie DIE,
const DWARFAbbreviationDeclaration *AbbrevDecl,
uint32_t Index);

/// Finds attributes FormValue and Offset.
///
/// \param DIE die to look up in.
/// \param Attr the attribute to extract.
/// \return an optional AttrInfo with DWARFFormValue and Offset.
Optional<AttrInfo> findAttributeInfo(const DWARFDie DIE, dwarf::Attribute Attr);

// DWARF5 Header in order of encoding.
// Types represent encodnig sizes.
using UnitLengthType = uint32_t;
Expand Down Expand Up @@ -447,23 +471,31 @@ class DebugStrWriter {
BinaryContext &BC;
};

class DebugInfoBinaryPatcher;
class DebugAbbrevWriter;
enum class LocWriterKind { DebugLocWriter, DebugLoclistWriter };

/// Serializes part of a .debug_loc DWARF section with LocationLists.
class SimpleBinaryPatcher;
class DebugLocWriter {
protected:
DebugLocWriter(uint8_t DwarfVersion, LocWriterKind Kind)
: DwarfVersion(DwarfVersion), Kind(Kind) {
init();
}

public:
DebugLocWriter() = delete;
DebugLocWriter(BinaryContext *BC);
DebugLocWriter() { init(); };
virtual ~DebugLocWriter(){};

/// Writes out location lists and stores internal patches.
virtual void addList(uint64_t AttrOffset, uint32_t LocListIndex,
DebugLocationsVector &&LocList);
virtual void addList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
DebugInfoBinaryPatcher &DebugInfoPatcher,
DebugAbbrevWriter &AbbrevWriter);

/// Writes out locations in to a local buffer, and adds Debug Info patches.
virtual void finalize(uint64_t SectionOffset,
SimpleBinaryPatcher &DebugInfoPatcher);
virtual void finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
DebugAbbrevWriter &AbbrevWriter);

/// Return internal buffer.
virtual std::unique_ptr<DebugBufferVector> getBuffer();
Expand All @@ -485,13 +517,15 @@ class DebugLocWriter {
std::unique_ptr<raw_svector_ostream> LocStream;
/// Current offset in the section (updated as new entries are written).
/// Starts with 0 here since this only writes part of a full location lists
/// section. In the final section, the first 16 bytes are reserved for an
/// empty list.
uint32_t SectionOffset{0};
/// section. In the final section, for DWARF4, the first 16 bytes are reserved
/// for an empty list.
static uint32_t LocSectionOffset;
uint8_t DwarfVersion{4};
LocWriterKind Kind{LocWriterKind::DebugLocWriter};

private:
/// Inits all the related data structures.
void init();
struct LocListDebugInfoPatchType {
uint64_t DebugInfoAttrOffset;
uint64_t LocListOffset;
Expand All @@ -501,36 +535,39 @@ class DebugLocWriter {
/// The list of debug info patches to be made once individual
/// location list writers have been filled
VectorLocListDebugInfoPatchType LocListDebugInfoPatches;

using VectorEmptyLocListAttributes = std::vector<uint64_t>;
/// Contains all the attributes pointing to empty location list.
VectorEmptyLocListAttributes EmptyAttrLists;
};

class DebugLoclistWriter : public DebugLocWriter {
public:
~DebugLoclistWriter() {}
DebugLoclistWriter() = delete;
DebugLoclistWriter(BinaryContext *BC, DWARFUnit &Unit,
uint32_t LocListsBaseAttrOffset, uint8_t DV, bool SD)
: DebugLocWriter(BC), CU(Unit),
LocListsBaseAttrOffset(LocListsBaseAttrOffset), IsSplitDwarf(SD) {
Kind = LocWriterKind::DebugLoclistWriter;
DwarfVersion = DV;
DebugLoclistWriter(DWARFUnit &Unit, uint8_t DV, bool SD)
: DebugLocWriter(DV, LocWriterKind::DebugLoclistWriter), CU(Unit),
IsSplitDwarf(SD) {
assert(DebugLoclistWriter::AddrWriter &&
"Please use SetAddressWriter to initialize "
"DebugAddrWriter before instantiation.");
if (DwarfVersion >= 5) {
LocBodyBuffer = std::make_unique<DebugBufferVector>();
LocBodyStream = std::make_unique<raw_svector_ostream>(*LocBodyBuffer);
} else {
// Writing out empty location list to which all references to empty
// location lists will point.
const char Zeroes[16] = {0};
*LocStream << StringRef(Zeroes, 16);
}
}

static void setAddressWriter(DebugAddrWriter *AddrW) { AddrWriter = AddrW; }

/// Stores location lists internally to be written out during finalize phase.
virtual void addList(uint64_t AttrOffset, uint32_t LocListIndex,
DebugLocationsVector &&LocList) override;
virtual void addList(AttrInfo &AttrVal, DebugLocationsVector &LocList,
DebugInfoBinaryPatcher &DebugInfoPatcher,
DebugAbbrevWriter &AbbrevWriter) override;

/// Writes out locations in to a local buffer and applies debug info patches.
void finalize(uint64_t SectionOffset,
SimpleBinaryPatcher &DebugInfoPatcher) override;
void finalize(DebugInfoBinaryPatcher &DebugInfoPatcher,
DebugAbbrevWriter &AbbrevWriter) override;

/// Returns CU ID.
/// For Skelton CU it is a CU Offset.
Expand All @@ -548,36 +585,21 @@ class DebugLoclistWriter : public DebugLocWriter {
bool isSplitDwarf() const { return IsSplitDwarf; }

constexpr static uint32_t InvalidIndex = UINT32_MAX;
constexpr static uint32_t InvalidLocListsBaseAttrOffset = UINT32_MAX;

private:
/// Writes out locations in to a local buffer and applies debug info patches.
void finalizeDWARFLegacy(uint64_t SectionOffset,
SimpleBinaryPatcher &DebugInfoPatcher);

/// Writes out locations in to a local buffer and applies debug info patches.
void finalizeDWARF5(uint64_t SectionOffset,
SimpleBinaryPatcher &DebugInfoPatcher);

struct LocPatch {
uint64_t AttrOffset{0};
uint32_t Index;
DebugLocationsVector LocList;
};
using LocPatchVec = SmallVector<LocPatch, 4>;
LocPatchVec Patches;
void finalizeDWARF5(DebugInfoBinaryPatcher &DebugInfoPatcher,
DebugAbbrevWriter &AbbrevWriter);

class Patch {
public:
Patch() = delete;
Patch(uint64_t O, uint64_t A) : Offset(O), Address(A) {}
uint64_t Offset{0};
uint64_t Address{0};
};
static DebugAddrWriter *AddrWriter;
DWARFUnit &CU;
uint32_t LocListsBaseAttrOffset{InvalidLocListsBaseAttrOffset};
bool IsSplitDwarf{false};
// Used for DWARF5 to store location lists before being finalized.
std::unique_ptr<DebugBufferVector> LocBodyBuffer;
std::unique_ptr<raw_svector_ostream> LocBodyStream;
std::vector<uint32_t> RelativeLocListOffsets;
uint32_t NumberOfEntries{0};
static uint32_t LoclistBaseOffset;
};

enum class PatcherKind { SimpleBinaryPatcher, DebugInfoBinaryPatcher };
Expand Down Expand Up @@ -1156,18 +1178,6 @@ class DwarfLineTable {
// Returns DWARF Version for this line table.
uint16_t getDwarfVersion() const { return DwarfVersion; }
};

struct AttrInfo {
DWARFFormValue V;
uint64_t Offset;
uint32_t Size; // Size of the attribute.
};

Optional<AttrInfo>
findAttributeInfo(const DWARFDie DIE,
const DWARFAbbreviationDeclaration *AbbrevDecl,
uint32_t Index);

} // namespace bolt
} // namespace llvm

Expand Down
2 changes: 1 addition & 1 deletion bolt/include/bolt/Rewrite/DWARFRewriter.h
Expand Up @@ -112,7 +112,7 @@ class DWARFRewriter {
Optional<uint64_t> RangesBase = None);

std::unique_ptr<DebugBufferVector>
makeFinalLocListsSection(SimpleBinaryPatcher &DebugInfoPatcher,
makeFinalLocListsSection(DebugInfoBinaryPatcher &DebugInfoPatcher,
DWARFVersion Version);

/// Finalize debug sections in the main binary.
Expand Down

0 comments on commit 1c6dc43

Please sign in to comment.