[llvm] [BOLT][DWARF][NFC] Refactor GDB Index into a new file (PR #94405)
Sayhaan Siddiqui via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 5 11:23:05 PDT 2024
https://github.com/sayhaan updated https://github.com/llvm/llvm-project/pull/94405
>From 8223e75b600fb87fbcf47913c7b5e3fb585dd959 Mon Sep 17 00:00:00 2001
From: Sayhaan Siddiqui <sayhaan at meta.com>
Date: Tue, 4 Jun 2024 13:03:53 -0700
Subject: [PATCH 1/5] Refactor GDBIndex into new file
Summary:
Test Plan:
Reviewers:
Subscribers:
Tasks:
Tags:
Differential Revision: https://phabricator.intern.facebook.com/D58156977
---
bolt/include/bolt/Core/GDBIndex.h | 60 ++++++++++
bolt/lib/Core/CMakeLists.txt | 1 +
bolt/lib/Core/GDBIndex.cpp | 182 ++++++++++++++++++++++++++++++
3 files changed, 243 insertions(+)
create mode 100644 bolt/include/bolt/Core/GDBIndex.h
create mode 100644 bolt/lib/Core/GDBIndex.cpp
diff --git a/bolt/include/bolt/Core/GDBIndex.h b/bolt/include/bolt/Core/GDBIndex.h
new file mode 100644
index 0000000000000..0ea588e9cba46
--- /dev/null
+++ b/bolt/include/bolt/Core/GDBIndex.h
@@ -0,0 +1,60 @@
+//===-- bolt/Core/GDBIndex.h - GDB Index support -------*- 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
+//
+//===----------------------------------------------------------------------===//
+///
+/// This file contains declaration of classes required for generation of
+/// .gdb_index section.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef BOLT_CORE_GDB_INDEX_H
+#define BOLT_CORE_GDB_INDEX_H
+
+#include "bolt/Core/BinaryContext.h"
+#include <vector>
+
+namespace llvm {
+namespace bolt {
+
+class GDBIndex {
+public:
+ /// Contains information about TU so we can write out correct entries in GDB
+ /// index.
+ struct GDBIndexTUEntry {
+ uint64_t UnitOffset;
+ uint64_t TypeHash;
+ uint64_t TypeDIERelativeOffset;
+ };
+
+private:
+ BinaryContext &BC;
+
+ /// Entries for GDB Index Types CU List
+ using GDBIndexTUEntryType = std::vector<GDBIndexTUEntry>;
+ GDBIndexTUEntryType GDBIndexTUEntryVector;
+
+public:
+ GDBIndex(BinaryContext &BC) : BC(BC) {}
+
+ /// Adds an GDBIndexTUEntry if .gdb_index section exists.
+ void addGDBTypeUnitEntry(const GDBIndexTUEntry &Entry);
+
+ /// Rewrite .gdb_index section if present.
+ void updateGdbIndexSection(
+ CUOffsetMap &CUMap, uint32_t NumCUs,
+ std::unique_ptr<DebugARangesSectionWriter> &ARangesSectionWriter);
+
+ /// Returns all entries needed for Types CU list
+ const GDBIndexTUEntryType &getGDBIndexTUEntryVector() const {
+ return GDBIndexTUEntryVector;
+ }
+};
+
+} // namespace bolt
+} // namespace llvm
+
+#endif
diff --git a/bolt/lib/Core/CMakeLists.txt b/bolt/lib/Core/CMakeLists.txt
index 441df9fe08464..873cf67a56291 100644
--- a/bolt/lib/Core/CMakeLists.txt
+++ b/bolt/lib/Core/CMakeLists.txt
@@ -25,6 +25,7 @@ add_llvm_library(LLVMBOLTCore
DynoStats.cpp
Exceptions.cpp
FunctionLayout.cpp
+ GDBIndex.cpp
HashUtilities.cpp
JumpTable.cpp
MCPlusBuilder.cpp
diff --git a/bolt/lib/Core/GDBIndex.cpp b/bolt/lib/Core/GDBIndex.cpp
new file mode 100644
index 0000000000000..fda19a2c8cb3e
--- /dev/null
+++ b/bolt/lib/Core/GDBIndex.cpp
@@ -0,0 +1,182 @@
+//===- bolt/Rewrite/GDBIndex.cpp -------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "bolt/Core/GDBIndex.h"
+
+using namespace llvm::bolt;
+using namespace llvm::support::endian;
+
+void GDBIndex::addGDBTypeUnitEntry(const GDBIndexTUEntry &Entry) {
+ GDBIndexTUEntryVector.push_back(Entry);
+}
+
+void GDBIndex::updateGdbIndexSection(
+ CUOffsetMap &CUMap, uint32_t NumCUs,
+ std::unique_ptr<DebugARangesSectionWriter> &ARangesSectionWriter) {
+ if (!BC.getGdbIndexSection())
+ return;
+
+ // See https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html
+ // for .gdb_index section format.
+
+ StringRef GdbIndexContents = BC.getGdbIndexSection()->getContents();
+
+ const char *Data = GdbIndexContents.data();
+
+ // Parse the header.
+ const uint32_t Version = read32le(Data);
+ if (Version != 7 && Version != 8) {
+ errs() << "BOLT-ERROR: can only process .gdb_index versions 7 and 8\n";
+ exit(1);
+ }
+
+ // Some .gdb_index generators use file offsets while others use section
+ // offsets. Hence we can only rely on offsets relative to each other,
+ // and ignore their absolute values.
+ const uint32_t CUListOffset = read32le(Data + 4);
+ const uint32_t CUTypesOffset = read32le(Data + 8);
+ const uint32_t AddressTableOffset = read32le(Data + 12);
+ const uint32_t SymbolTableOffset = read32le(Data + 16);
+ const uint32_t ConstantPoolOffset = read32le(Data + 20);
+ Data += 24;
+
+ // Map CUs offsets to indices and verify existing index table.
+ std::map<uint32_t, uint32_t> OffsetToIndexMap;
+ const uint32_t CUListSize = CUTypesOffset - CUListOffset;
+ const uint32_t TUListSize = AddressTableOffset - CUTypesOffset;
+ const unsigned NUmCUsEncoded = CUListSize / 16;
+ unsigned MaxDWARFVersion = BC.DwCtx->getMaxVersion();
+ unsigned NumDWARF5TUs =
+ getGDBIndexTUEntryVector().size() - BC.DwCtx->getNumTypeUnits();
+ bool SkipTypeUnits = false;
+ // For DWARF5 Types are in .debug_info.
+ // LLD doesn't generate Types CU List, and in CU list offset
+ // only includes CUs.
+ // GDB 11+ includes only CUs in CU list and generates Types
+ // list.
+ // GDB 9 includes CUs and TUs in CU list and generates TYpes
+ // list. The NumCUs is CUs + TUs, so need to modify the check.
+ // For split-dwarf
+ // GDB-11, DWARF5: TU units from dwo are not included.
+ // GDB-11, DWARF4: TU units from dwo are included.
+ if (MaxDWARFVersion >= 5)
+ SkipTypeUnits = !TUListSize ? true
+ : ((NUmCUsEncoded + NumDWARF5TUs) ==
+ BC.DwCtx->getNumCompileUnits());
+
+ if (!((CUListSize == NumCUs * 16) ||
+ (CUListSize == (NumCUs + NumDWARF5TUs) * 16))) {
+ errs() << "BOLT-ERROR: .gdb_index: CU count mismatch\n";
+ exit(1);
+ }
+ DenseSet<uint64_t> OriginalOffsets;
+ for (unsigned Index = 0, Units = BC.DwCtx->getNumCompileUnits();
+ Index < Units; ++Index) {
+ const DWARFUnit *CU = BC.DwCtx->getUnitAtIndex(Index);
+ if (SkipTypeUnits && CU->isTypeUnit())
+ continue;
+ const uint64_t Offset = read64le(Data);
+ Data += 16;
+ if (CU->getOffset() != Offset) {
+ errs() << "BOLT-ERROR: .gdb_index CU offset mismatch\n";
+ exit(1);
+ }
+
+ OriginalOffsets.insert(Offset);
+ OffsetToIndexMap[Offset] = Index;
+ }
+
+ // Ignore old address table.
+ const uint32_t OldAddressTableSize = SymbolTableOffset - AddressTableOffset;
+ // Move Data to the beginning of symbol table.
+ Data += SymbolTableOffset - CUTypesOffset;
+
+ // Calculate the size of the new address table.
+ uint32_t NewAddressTableSize = 0;
+ for (const auto &CURangesPair : ARangesSectionWriter->getCUAddressRanges()) {
+ const SmallVector<DebugAddressRange, 2> &Ranges = CURangesPair.second;
+ NewAddressTableSize += Ranges.size() * 20;
+ }
+
+ // Difference between old and new table (and section) sizes.
+ // Could be negative.
+ int32_t Delta = NewAddressTableSize - OldAddressTableSize;
+
+ size_t NewGdbIndexSize = GdbIndexContents.size() + Delta;
+
+ // Free'd by ExecutableFileMemoryManager.
+ auto *NewGdbIndexContents = new uint8_t[NewGdbIndexSize];
+ uint8_t *Buffer = NewGdbIndexContents;
+
+ write32le(Buffer, Version);
+ write32le(Buffer + 4, CUListOffset);
+ write32le(Buffer + 8, CUTypesOffset);
+ write32le(Buffer + 12, AddressTableOffset);
+ write32le(Buffer + 16, SymbolTableOffset + Delta);
+ write32le(Buffer + 20, ConstantPoolOffset + Delta);
+ Buffer += 24;
+
+ using MapEntry = std::pair<uint32_t, CUInfo>;
+ std::vector<MapEntry> CUVector(CUMap.begin(), CUMap.end());
+ // Need to sort since we write out all of TUs in .debug_info before CUs.
+ std::sort(CUVector.begin(), CUVector.end(),
+ [](const MapEntry &E1, const MapEntry &E2) -> bool {
+ return E1.second.Offset < E2.second.Offset;
+ });
+ // Writing out CU List <Offset, Size>
+ for (auto &CUInfo : CUVector) {
+ // Skipping TU for DWARF5 when they are not included in CU list.
+ if (!OriginalOffsets.count(CUInfo.first))
+ continue;
+ write64le(Buffer, CUInfo.second.Offset);
+ // Length encoded in CU doesn't contain first 4 bytes that encode length.
+ write64le(Buffer + 8, CUInfo.second.Length + 4);
+ Buffer += 16;
+ }
+
+ // Rewrite TU CU List, since abbrevs can be different.
+ // Entry example:
+ // 0: offset = 0x00000000, type_offset = 0x0000001e, type_signature =
+ // 0x418503b8111e9a7b Spec says " triplet, the first value is the CU offset,
+ // the second value is the type offset in the CU, and the third value is the
+ // type signature" Looking at what is being generated by gdb-add-index. The
+ // first entry is TU offset, second entry is offset from it, and third entry
+ // is the type signature.
+ if (TUListSize)
+ for (const GDBIndexTUEntry &Entry : getGDBIndexTUEntryVector()) {
+ write64le(Buffer, Entry.UnitOffset);
+ write64le(Buffer + 8, Entry.TypeDIERelativeOffset);
+ write64le(Buffer + 16, Entry.TypeHash);
+ Buffer += sizeof(GDBIndexTUEntry);
+ }
+
+ // Generate new address table.
+ for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
+ ARangesSectionWriter->getCUAddressRanges()) {
+ const uint32_t CUIndex = OffsetToIndexMap[CURangesPair.first];
+ const DebugAddressRangesVector &Ranges = CURangesPair.second;
+ for (const DebugAddressRange &Range : Ranges) {
+ write64le(Buffer, Range.LowPC);
+ write64le(Buffer + 8, Range.HighPC);
+ write32le(Buffer + 16, CUIndex);
+ Buffer += 20;
+ }
+ }
+
+ const size_t TrailingSize =
+ GdbIndexContents.data() + GdbIndexContents.size() - Data;
+ assert(Buffer + TrailingSize == NewGdbIndexContents + NewGdbIndexSize &&
+ "size calculation error");
+
+ // Copy over the rest of the original data.
+ memcpy(Buffer, Data, TrailingSize);
+
+ // Register the new section.
+ BC.registerOrUpdateNoteSection(".gdb_index", NewGdbIndexContents,
+ NewGdbIndexSize);
+}
>From a2c2121de6cbb6e3dc4bf8fb7cd5e66af0f8eaca Mon Sep 17 00:00:00 2001
From: Sayhaan Siddiqui <sayhaan at meta.com>
Date: Wed, 5 Jun 2024 09:33:53 -0700
Subject: [PATCH 2/5] Formatting changes and readding code
Summary:
Test Plan:
Reviewers:
Subscribers:
Tasks:
Tags:
Differential Revision: https://phabricator.intern.facebook.com/D58193743
---
bolt/include/bolt/Core/GDBIndex.h | 10 ++++++----
bolt/lib/Core/GDBIndex.cpp | 5 ++++-
2 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/bolt/include/bolt/Core/GDBIndex.h b/bolt/include/bolt/Core/GDBIndex.h
index 0ea588e9cba46..9d88b7b11bf37 100644
--- a/bolt/include/bolt/Core/GDBIndex.h
+++ b/bolt/include/bolt/Core/GDBIndex.h
@@ -1,4 +1,4 @@
-//===-- bolt/Core/GDBIndex.h - GDB Index support -------*- C++ -*-===//
+//===-- bolt/Core/GDBIndex.h - GDB Index support ----------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -33,13 +33,15 @@ class GDBIndex {
private:
BinaryContext &BC;
- /// Entries for GDB Index Types CU List
+ /// Entries for GDB Index Types CU List.
using GDBIndexTUEntryType = std::vector<GDBIndexTUEntry>;
GDBIndexTUEntryType GDBIndexTUEntryVector;
public:
GDBIndex(BinaryContext &BC) : BC(BC) {}
-
+
+ std::mutex DWARFRewriterMutex;
+
/// Adds an GDBIndexTUEntry if .gdb_index section exists.
void addGDBTypeUnitEntry(const GDBIndexTUEntry &Entry);
@@ -48,7 +50,7 @@ class GDBIndex {
CUOffsetMap &CUMap, uint32_t NumCUs,
std::unique_ptr<DebugARangesSectionWriter> &ARangesSectionWriter);
- /// Returns all entries needed for Types CU list
+ /// Returns all entries needed for Types CU list.
const GDBIndexTUEntryType &getGDBIndexTUEntryVector() const {
return GDBIndexTUEntryVector;
}
diff --git a/bolt/lib/Core/GDBIndex.cpp b/bolt/lib/Core/GDBIndex.cpp
index fda19a2c8cb3e..df6f2324d4e91 100644
--- a/bolt/lib/Core/GDBIndex.cpp
+++ b/bolt/lib/Core/GDBIndex.cpp
@@ -1,4 +1,4 @@
-//===- bolt/Rewrite/GDBIndex.cpp -------------------------------------===//
+//===- bolt/Core/GDBIndex.cpp - GDB Index support ------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
@@ -12,6 +12,9 @@ using namespace llvm::bolt;
using namespace llvm::support::endian;
void GDBIndex::addGDBTypeUnitEntry(const GDBIndexTUEntry &Entry) {
+ std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
+ if (!BC.getGdbIndexSection())
+ return;
GDBIndexTUEntryVector.push_back(Entry);
}
>From 7791a0d95daacd1af4bd2f698e6ee9b5b9b92ebd Mon Sep 17 00:00:00 2001
From: Sayhaan Siddiqui <sayhaan at meta.com>
Date: Wed, 5 Jun 2024 09:42:22 -0700
Subject: [PATCH 3/5] Formatting changes
Summary:
Test Plan:
Reviewers:
Subscribers:
Tasks:
Tags:
---
bolt/include/bolt/Core/GDBIndex.h | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/bolt/include/bolt/Core/GDBIndex.h b/bolt/include/bolt/Core/GDBIndex.h
index 9d88b7b11bf37..242a1fa6dd1b4 100644
--- a/bolt/include/bolt/Core/GDBIndex.h
+++ b/bolt/include/bolt/Core/GDBIndex.h
@@ -39,9 +39,9 @@ class GDBIndex {
public:
GDBIndex(BinaryContext &BC) : BC(BC) {}
-
+
std::mutex DWARFRewriterMutex;
-
+
/// Adds an GDBIndexTUEntry if .gdb_index section exists.
void addGDBTypeUnitEntry(const GDBIndexTUEntry &Entry);
>From 05fb415e85338653983c133ce7b36c830e9a7f7e Mon Sep 17 00:00:00 2001
From: Sayhaan Siddiqui <sayhaan at meta.com>
Date: Wed, 5 Jun 2024 10:27:20 -0700
Subject: [PATCH 4/5] Make variable name more relevant
Summary:
Test Plan:
Reviewers:
Subscribers:
Tasks:
Tags:
---
bolt/include/bolt/Core/GDBIndex.h | 2 +-
bolt/lib/Core/GDBIndex.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/bolt/include/bolt/Core/GDBIndex.h b/bolt/include/bolt/Core/GDBIndex.h
index 242a1fa6dd1b4..9b7c8f8e24aa2 100644
--- a/bolt/include/bolt/Core/GDBIndex.h
+++ b/bolt/include/bolt/Core/GDBIndex.h
@@ -40,7 +40,7 @@ class GDBIndex {
public:
GDBIndex(BinaryContext &BC) : BC(BC) {}
- std::mutex DWARFRewriterMutex;
+ std::mutex GDBIndexMutex;
/// Adds an GDBIndexTUEntry if .gdb_index section exists.
void addGDBTypeUnitEntry(const GDBIndexTUEntry &Entry);
diff --git a/bolt/lib/Core/GDBIndex.cpp b/bolt/lib/Core/GDBIndex.cpp
index df6f2324d4e91..07a9c4c04488c 100644
--- a/bolt/lib/Core/GDBIndex.cpp
+++ b/bolt/lib/Core/GDBIndex.cpp
@@ -12,7 +12,7 @@ using namespace llvm::bolt;
using namespace llvm::support::endian;
void GDBIndex::addGDBTypeUnitEntry(const GDBIndexTUEntry &Entry) {
- std::lock_guard<std::mutex> Lock(DWARFRewriterMutex);
+ std::lock_guard<std::mutex> Lock(GDBIndexMutex);
if (!BC.getGdbIndexSection())
return;
GDBIndexTUEntryVector.push_back(Entry);
>From e612e8ccf967b4e6cae69d3cb9b01b2ea6597c9f Mon Sep 17 00:00:00 2001
From: Sayhaan Siddiqui <sayhaan at meta.com>
Date: Wed, 5 Jun 2024 11:22:04 -0700
Subject: [PATCH 5/5] Refactoring functions
Summary:
Test Plan:
Reviewers:
Subscribers:
Tasks:
Tags:
---
bolt/include/bolt/Core/GDBIndex.h | 4 ++--
bolt/lib/Core/GDBIndex.cpp | 10 +++++-----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/bolt/include/bolt/Core/GDBIndex.h b/bolt/include/bolt/Core/GDBIndex.h
index 9b7c8f8e24aa2..62f8c9f7e6ac5 100644
--- a/bolt/include/bolt/Core/GDBIndex.h
+++ b/bolt/include/bolt/Core/GDBIndex.h
@@ -43,12 +43,12 @@ class GDBIndex {
std::mutex GDBIndexMutex;
/// Adds an GDBIndexTUEntry if .gdb_index section exists.
- void addGDBTypeUnitEntry(const GDBIndexTUEntry &Entry);
+ void addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry);
/// Rewrite .gdb_index section if present.
void updateGdbIndexSection(
CUOffsetMap &CUMap, uint32_t NumCUs,
- std::unique_ptr<DebugARangesSectionWriter> &ARangesSectionWriter);
+ DebugARangesSectionWriter &ARangesSectionWriter);
/// Returns all entries needed for Types CU list.
const GDBIndexTUEntryType &getGDBIndexTUEntryVector() const {
diff --git a/bolt/lib/Core/GDBIndex.cpp b/bolt/lib/Core/GDBIndex.cpp
index 07a9c4c04488c..f5bfcd1e54b54 100644
--- a/bolt/lib/Core/GDBIndex.cpp
+++ b/bolt/lib/Core/GDBIndex.cpp
@@ -11,16 +11,16 @@
using namespace llvm::bolt;
using namespace llvm::support::endian;
-void GDBIndex::addGDBTypeUnitEntry(const GDBIndexTUEntry &Entry) {
+void GDBIndex::addGDBTypeUnitEntry(const GDBIndexTUEntry &&Entry) {
std::lock_guard<std::mutex> Lock(GDBIndexMutex);
if (!BC.getGdbIndexSection())
return;
- GDBIndexTUEntryVector.push_back(Entry);
+ GDBIndexTUEntryVector.emplace_back(Entry);
}
void GDBIndex::updateGdbIndexSection(
CUOffsetMap &CUMap, uint32_t NumCUs,
- std::unique_ptr<DebugARangesSectionWriter> &ARangesSectionWriter) {
+ DebugARangesSectionWriter &ARangesSectionWriter) {
if (!BC.getGdbIndexSection())
return;
@@ -101,7 +101,7 @@ void GDBIndex::updateGdbIndexSection(
// Calculate the size of the new address table.
uint32_t NewAddressTableSize = 0;
- for (const auto &CURangesPair : ARangesSectionWriter->getCUAddressRanges()) {
+ for (const auto &CURangesPair : ARangesSectionWriter.getCUAddressRanges()) {
const SmallVector<DebugAddressRange, 2> &Ranges = CURangesPair.second;
NewAddressTableSize += Ranges.size() * 20;
}
@@ -160,7 +160,7 @@ void GDBIndex::updateGdbIndexSection(
// Generate new address table.
for (const std::pair<const uint64_t, DebugAddressRangesVector> &CURangesPair :
- ARangesSectionWriter->getCUAddressRanges()) {
+ ARangesSectionWriter.getCUAddressRanges()) {
const uint32_t CUIndex = OffsetToIndexMap[CURangesPair.first];
const DebugAddressRangesVector &Ranges = CURangesPair.second;
for (const DebugAddressRange &Range : Ranges) {
More information about the llvm-commits
mailing list