Update prebuilt Clang to r416183b from Android.
https://android.googlesource.com/platform/prebuilts/clang/host/
linux-x86/+/06a71ddac05c22edb2d10b590e1769b3f8619bef
clang 12.0.5 (based on r416183b) from build 7284624.
Change-Id: I277a316abcf47307562d8b748b84870f31a72866
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h
index 0ac8b65..3867d78 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h
@@ -38,7 +38,7 @@
explicit AppendingTypeTableBuilder(BumpPtrAllocator &Storage);
~AppendingTypeTableBuilder();
- // TypeTableCollection overrides
+ // TypeCollection overrides
Optional<TypeIndex> getFirst() override;
Optional<TypeIndex> getNext(TypeIndex Prev) override;
CVType getType(TypeIndex Index) override;
@@ -46,6 +46,7 @@
bool contains(TypeIndex Index) override;
uint32_t size() override;
uint32_t capacity() override;
+ bool replaceType(TypeIndex &Index, CVType Data, bool Stabilize) override;
// public interface
void reset();
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVRecord.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVRecord.h
index 784c47e..bb29ef5 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVRecord.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVRecord.h
@@ -11,9 +11,9 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
@@ -61,12 +61,9 @@
ArrayRef<uint8_t> RecordData;
};
-template <typename Kind> struct RemappedRecord {
- explicit RemappedRecord(const CVRecord<Kind> &R) : OriginalRecord(R) {}
-
- CVRecord<Kind> OriginalRecord;
- SmallVector<std::pair<uint32_t, TypeIndex>, 8> Mappings;
-};
+// There are two kinds of codeview records: type and symbol records.
+using CVType = CVRecord<TypeLeafKind>;
+using CVSymbol = CVRecord<SymbolKind>;
template <typename Record, typename Func>
Error forEachCodeViewRecord(ArrayRef<uint8_t> StreamBuffer, Func F) {
@@ -126,6 +123,12 @@
}
};
+namespace codeview {
+using CVSymbolArray = VarStreamArray<CVSymbol>;
+using CVTypeArray = VarStreamArray<CVType>;
+using CVTypeRange = iterator_range<CVTypeArray::Iterator>;
+} // namespace codeview
+
} // end namespace llvm
#endif // LLVM_DEBUGINFO_CODEVIEW_RECORDITERATOR_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
index 1615ff4..82ef8c1 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVSymbolVisitor.h
@@ -10,9 +10,6 @@
#define LLVM_DEBUGINFO_CODEVIEW_CVSYMBOLVISITOR_H
#include "llvm/DebugInfo/CodeView/CVRecord.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/CodeView/SymbolVisitorDelegate.h"
#include "llvm/Support/ErrorOr.h"
namespace llvm {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
index 7d20bb0..7538cb2 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CVTypeVisitor.h
@@ -11,7 +11,6 @@
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -31,9 +30,6 @@
Error visitTypeRecord(CVType &Record, TypeIndex Index,
TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source = VDS_BytesPresent);
-Error visitTypeRecord(CVType &Record, TypeIndex Index,
- TypeVisitorCallbackPipeline &Callbacks,
- VisitorDataSource Source = VDS_BytesPresent);
Error visitTypeRecord(CVType &Record, TypeVisitorCallbacks &Callbacks,
VisitorDataSource Source = VDS_BytesPresent);
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
index d3bad4c..d851dea 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CodeViewRecordIO.h
@@ -15,7 +15,8 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeViewError.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/GUID.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Error.h"
@@ -29,9 +30,13 @@
class CodeViewRecordStreamer {
public:
- virtual void EmitBytes(StringRef Data) = 0;
- virtual void EmitIntValue(uint64_t Value, unsigned Size) = 0;
- virtual void EmitBinaryData(StringRef Data) = 0;
+ virtual void emitBytes(StringRef Data) = 0;
+ virtual void emitIntValue(uint64_t Value, unsigned Size) = 0;
+ virtual void emitBinaryData(StringRef Data) = 0;
+ virtual void AddComment(const Twine &T) = 0;
+ virtual void AddRawComment(const Twine &T) = 0;
+ virtual bool isVerboseAsm() = 0;
+ virtual std::string getTypeName(TypeIndex TI) = 0;
virtual ~CodeViewRecordStreamer() = default;
};
@@ -59,7 +64,7 @@
Error beginRecord(Optional<uint32_t> MaxLength);
Error endRecord();
- Error mapInteger(TypeIndex &TypeInd);
+ Error mapInteger(TypeIndex &TypeInd, const Twine &Comment = "");
bool isStreaming() const {
return (Streamer != nullptr) && (Reader == nullptr) && (Writer == nullptr);
@@ -77,7 +82,7 @@
if (isStreaming()) {
StringRef BytesSR =
StringRef((reinterpret_cast<const char *>(&Value)), sizeof(Value));
- Streamer->EmitBytes(BytesSR);
+ Streamer->emitBytes(BytesSR);
incrStreamedLen(sizeof(T));
return Error::success();
}
@@ -92,9 +97,10 @@
return Error::success();
}
- template <typename T> Error mapInteger(T &Value) {
+ template <typename T> Error mapInteger(T &Value, const Twine &Comment = "") {
if (isStreaming()) {
- Streamer->EmitIntValue((int)Value, sizeof(T));
+ emitComment(Comment);
+ Streamer->emitIntValue((int)Value, sizeof(T));
incrStreamedLen(sizeof(T));
return Error::success();
}
@@ -105,17 +111,17 @@
return Reader->readInteger(Value);
}
- template <typename T> Error mapEnum(T &Value) {
+ template <typename T> Error mapEnum(T &Value, const Twine &Comment = "") {
if (!isStreaming() && sizeof(Value) > maxFieldLength())
return make_error<CodeViewError>(cv_error_code::insufficient_buffer);
- using U = typename std::underlying_type<T>::type;
+ using U = std::underlying_type_t<T>;
U X;
if (isWriting() || isStreaming())
X = static_cast<U>(Value);
- if (auto EC = mapInteger(X))
+ if (auto EC = mapInteger(X, Comment))
return EC;
if (isReading())
@@ -124,20 +130,23 @@
return Error::success();
}
- Error mapEncodedInteger(int64_t &Value);
- Error mapEncodedInteger(uint64_t &Value);
- Error mapEncodedInteger(APSInt &Value);
- Error mapStringZ(StringRef &Value);
- Error mapGuid(GUID &Guid);
+ Error mapEncodedInteger(int64_t &Value, const Twine &Comment = "");
+ Error mapEncodedInteger(uint64_t &Value, const Twine &Comment = "");
+ Error mapEncodedInteger(APSInt &Value, const Twine &Comment = "");
+ Error mapStringZ(StringRef &Value, const Twine &Comment = "");
+ Error mapGuid(GUID &Guid, const Twine &Comment = "");
- Error mapStringZVectorZ(std::vector<StringRef> &Value);
+ Error mapStringZVectorZ(std::vector<StringRef> &Value,
+ const Twine &Comment = "");
template <typename SizeType, typename T, typename ElementMapper>
- Error mapVectorN(T &Items, const ElementMapper &Mapper) {
+ Error mapVectorN(T &Items, const ElementMapper &Mapper,
+ const Twine &Comment = "") {
SizeType Size;
if (isStreaming()) {
Size = static_cast<SizeType>(Items.size());
- Streamer->EmitIntValue(Size, sizeof(Size));
+ emitComment(Comment);
+ Streamer->emitIntValue(Size, sizeof(Size));
incrStreamedLen(sizeof(Size)); // add 1 for the delimiter
for (auto &X : Items) {
@@ -168,7 +177,9 @@
}
template <typename T, typename ElementMapper>
- Error mapVectorTail(T &Items, const ElementMapper &Mapper) {
+ Error mapVectorTail(T &Items, const ElementMapper &Mapper,
+ const Twine &Comment = "") {
+ emitComment(Comment);
if (isStreaming() || isWriting()) {
for (auto &Item : Items) {
if (auto EC = Mapper(*this, Item))
@@ -186,8 +197,9 @@
return Error::success();
}
- Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes);
- Error mapByteVectorTail(std::vector<uint8_t> &Bytes);
+ Error mapByteVectorTail(ArrayRef<uint8_t> &Bytes, const Twine &Comment = "");
+ Error mapByteVectorTail(std::vector<uint8_t> &Bytes,
+ const Twine &Comment = "");
Error padToAlignment(uint32_t Align);
Error skipPadding();
@@ -198,9 +210,16 @@
return 0;
}
+ void emitRawComment(const Twine &T) {
+ if (isStreaming() && Streamer->isVerboseAsm())
+ Streamer->AddRawComment(T);
+ }
+
private:
- void emitEncodedSignedInteger(const int64_t &Value);
- void emitEncodedUnsignedInteger(const uint64_t &Value);
+ void emitEncodedSignedInteger(const int64_t &Value,
+ const Twine &Comment = "");
+ void emitEncodedUnsignedInteger(const uint64_t &Value,
+ const Twine &Comment = "");
Error writeEncodedSignedInteger(const int64_t &Value);
Error writeEncodedUnsignedInteger(const uint64_t &Value);
@@ -214,6 +233,14 @@
StreamedLen = 4; // The record prefix is 4 bytes long
}
+ void emitComment(const Twine &Comment) {
+ if (isStreaming() && Streamer->isVerboseAsm()) {
+ Twine TComment(Comment);
+ if (!TComment.isTriviallyEmpty())
+ Streamer->AddComment(TComment);
+ }
+ }
+
struct RecordLimit {
uint32_t BeginOffset;
Optional<uint32_t> MaxLength;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
index 9767e49..48ea7e5 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
@@ -15,6 +15,7 @@
#endif
#if !defined(CV_REGISTERS_ALL) && !defined(CV_REGISTERS_X86) && \
+ !defined(CV_REGISTERS_ARM) && \
!defined(CV_REGISTERS_ARM64)
#error Need include at least one register set.
#endif
@@ -366,8 +367,167 @@
#endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_X86)
+#if defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM)
+
+// ARM registers
+
+CV_REGISTER(ARM_NOREG, 0)
+
+// General purpose 32-bit integer regisers
+
+CV_REGISTER(ARM_R0, 10)
+CV_REGISTER(ARM_R1, 11)
+CV_REGISTER(ARM_R2, 12)
+CV_REGISTER(ARM_R3, 13)
+CV_REGISTER(ARM_R4, 14)
+CV_REGISTER(ARM_R5, 15)
+CV_REGISTER(ARM_R6, 16)
+CV_REGISTER(ARM_R7, 17)
+CV_REGISTER(ARM_R8, 18)
+CV_REGISTER(ARM_R9, 19)
+CV_REGISTER(ARM_R10, 20)
+CV_REGISTER(ARM_R11, 21)
+CV_REGISTER(ARM_R12, 22)
+CV_REGISTER(ARM_SP, 23)
+CV_REGISTER(ARM_LR, 24)
+CV_REGISTER(ARM_PC, 25)
+
+// Status register
+
+CV_REGISTER(ARM_CPSR, 26)
+
+// ARM VFPv1 registers
+
+CV_REGISTER(ARM_FPSCR, 40)
+CV_REGISTER(ARM_FPEXC, 41)
+
+CV_REGISTER(ARM_FS0, 50)
+CV_REGISTER(ARM_FS1, 51)
+CV_REGISTER(ARM_FS2, 52)
+CV_REGISTER(ARM_FS3, 53)
+CV_REGISTER(ARM_FS4, 54)
+CV_REGISTER(ARM_FS5, 55)
+CV_REGISTER(ARM_FS6, 56)
+CV_REGISTER(ARM_FS7, 57)
+CV_REGISTER(ARM_FS8, 58)
+CV_REGISTER(ARM_FS9, 59)
+CV_REGISTER(ARM_FS10, 60)
+CV_REGISTER(ARM_FS11, 61)
+CV_REGISTER(ARM_FS12, 62)
+CV_REGISTER(ARM_FS13, 63)
+CV_REGISTER(ARM_FS14, 64)
+CV_REGISTER(ARM_FS15, 65)
+CV_REGISTER(ARM_FS16, 66)
+CV_REGISTER(ARM_FS17, 67)
+CV_REGISTER(ARM_FS18, 68)
+CV_REGISTER(ARM_FS19, 69)
+CV_REGISTER(ARM_FS20, 70)
+CV_REGISTER(ARM_FS21, 71)
+CV_REGISTER(ARM_FS22, 72)
+CV_REGISTER(ARM_FS23, 73)
+CV_REGISTER(ARM_FS24, 74)
+CV_REGISTER(ARM_FS25, 75)
+CV_REGISTER(ARM_FS26, 76)
+CV_REGISTER(ARM_FS27, 77)
+CV_REGISTER(ARM_FS28, 78)
+CV_REGISTER(ARM_FS29, 79)
+CV_REGISTER(ARM_FS30, 80)
+CV_REGISTER(ARM_FS31, 81)
+
+// ARM VFPv3/NEON registers
+
+CV_REGISTER(ARM_FS32, 200)
+CV_REGISTER(ARM_FS33, 201)
+CV_REGISTER(ARM_FS34, 202)
+CV_REGISTER(ARM_FS35, 203)
+CV_REGISTER(ARM_FS36, 204)
+CV_REGISTER(ARM_FS37, 205)
+CV_REGISTER(ARM_FS38, 206)
+CV_REGISTER(ARM_FS39, 207)
+CV_REGISTER(ARM_FS40, 208)
+CV_REGISTER(ARM_FS41, 209)
+CV_REGISTER(ARM_FS42, 210)
+CV_REGISTER(ARM_FS43, 211)
+CV_REGISTER(ARM_FS44, 212)
+CV_REGISTER(ARM_FS45, 213)
+CV_REGISTER(ARM_FS46, 214)
+CV_REGISTER(ARM_FS47, 215)
+CV_REGISTER(ARM_FS48, 216)
+CV_REGISTER(ARM_FS49, 217)
+CV_REGISTER(ARM_FS50, 218)
+CV_REGISTER(ARM_FS51, 219)
+CV_REGISTER(ARM_FS52, 220)
+CV_REGISTER(ARM_FS53, 221)
+CV_REGISTER(ARM_FS54, 222)
+CV_REGISTER(ARM_FS55, 223)
+CV_REGISTER(ARM_FS56, 224)
+CV_REGISTER(ARM_FS57, 225)
+CV_REGISTER(ARM_FS58, 226)
+CV_REGISTER(ARM_FS59, 227)
+CV_REGISTER(ARM_FS60, 228)
+CV_REGISTER(ARM_FS61, 229)
+CV_REGISTER(ARM_FS62, 230)
+CV_REGISTER(ARM_FS63, 231)
+
+CV_REGISTER(ARM_ND0, 300)
+CV_REGISTER(ARM_ND1, 301)
+CV_REGISTER(ARM_ND2, 302)
+CV_REGISTER(ARM_ND3, 303)
+CV_REGISTER(ARM_ND4, 304)
+CV_REGISTER(ARM_ND5, 305)
+CV_REGISTER(ARM_ND6, 306)
+CV_REGISTER(ARM_ND7, 307)
+CV_REGISTER(ARM_ND8, 308)
+CV_REGISTER(ARM_ND9, 309)
+CV_REGISTER(ARM_ND10, 310)
+CV_REGISTER(ARM_ND11, 311)
+CV_REGISTER(ARM_ND12, 312)
+CV_REGISTER(ARM_ND13, 313)
+CV_REGISTER(ARM_ND14, 314)
+CV_REGISTER(ARM_ND15, 315)
+CV_REGISTER(ARM_ND16, 316)
+CV_REGISTER(ARM_ND17, 317)
+CV_REGISTER(ARM_ND18, 318)
+CV_REGISTER(ARM_ND19, 319)
+CV_REGISTER(ARM_ND20, 320)
+CV_REGISTER(ARM_ND21, 321)
+CV_REGISTER(ARM_ND22, 322)
+CV_REGISTER(ARM_ND23, 323)
+CV_REGISTER(ARM_ND24, 324)
+CV_REGISTER(ARM_ND25, 325)
+CV_REGISTER(ARM_ND26, 326)
+CV_REGISTER(ARM_ND27, 327)
+CV_REGISTER(ARM_ND28, 328)
+CV_REGISTER(ARM_ND29, 329)
+CV_REGISTER(ARM_ND30, 330)
+CV_REGISTER(ARM_ND31, 331)
+
+CV_REGISTER(ARM_NQ0, 400)
+CV_REGISTER(ARM_NQ1, 401)
+CV_REGISTER(ARM_NQ2, 402)
+CV_REGISTER(ARM_NQ3, 403)
+CV_REGISTER(ARM_NQ4, 404)
+CV_REGISTER(ARM_NQ5, 405)
+CV_REGISTER(ARM_NQ6, 406)
+CV_REGISTER(ARM_NQ7, 407)
+CV_REGISTER(ARM_NQ8, 408)
+CV_REGISTER(ARM_NQ9, 409)
+CV_REGISTER(ARM_NQ10, 410)
+CV_REGISTER(ARM_NQ11, 411)
+CV_REGISTER(ARM_NQ12, 412)
+CV_REGISTER(ARM_NQ13, 413)
+CV_REGISTER(ARM_NQ14, 414)
+CV_REGISTER(ARM_NQ15, 415)
+
+#endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM)
+
#if defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM64)
+// arm64intr.h from MSVC defines ARM64_FPSR, which conflicts with
+// these declarations.
+#pragma push_macro("ARM64_FPSR")
+#undef ARM64_FPSR
+
// ARM64 registers
CV_REGISTER(ARM64_NOREG, 0)
@@ -556,4 +716,6 @@
CV_REGISTER(ARM64_FPSR, 220)
+#pragma pop_macro("ARM64_FPSR")
+
#endif // defined(CV_REGISTERS_ALL) || defined(CV_REGISTERS_ARM64)
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h
index cd67f78..0e2f5d9 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h
@@ -18,7 +18,6 @@
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/BinaryStreamWriter.h"
#include "llvm/Support/Error.h"
@@ -61,4 +60,4 @@
} // namespace codeview
} // namespace llvm
-#endif
\ No newline at end of file
+#endif
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h
index bcb379f..e915d8a 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSubsectionRecord.h
@@ -35,44 +35,38 @@
class DebugSubsectionRecord {
public:
DebugSubsectionRecord();
- DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data,
- CodeViewContainer Container);
+ DebugSubsectionRecord(DebugSubsectionKind Kind, BinaryStreamRef Data);
- static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info,
- CodeViewContainer Container);
+ static Error initialize(BinaryStreamRef Stream, DebugSubsectionRecord &Info);
uint32_t getRecordLength() const;
DebugSubsectionKind kind() const;
BinaryStreamRef getRecordData() const;
private:
- CodeViewContainer Container = CodeViewContainer::ObjectFile;
DebugSubsectionKind Kind = DebugSubsectionKind::None;
BinaryStreamRef Data;
};
class DebugSubsectionRecordBuilder {
public:
- DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection,
- CodeViewContainer Container);
+ DebugSubsectionRecordBuilder(std::shared_ptr<DebugSubsection> Subsection);
/// Use this to copy existing subsections directly from source to destination.
/// For example, line table subsections in an object file only need to be
/// relocated before being copied into the PDB.
- DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents,
- CodeViewContainer Container);
+ DebugSubsectionRecordBuilder(const DebugSubsectionRecord &Contents);
- uint32_t calculateSerializedLength();
- Error commit(BinaryStreamWriter &Writer) const;
+ uint32_t calculateSerializedLength() const;
+ Error commit(BinaryStreamWriter &Writer, CodeViewContainer Container) const;
private:
/// The subsection to build. Will be null if Contents is non-empty.
std::shared_ptr<DebugSubsection> Subsection;
/// The bytes of the subsection. Only non-empty if Subsection is null.
+ /// FIXME: Reduce the size of this.
DebugSubsectionRecord Contents;
-
- CodeViewContainer Container;
};
} // end namespace codeview
@@ -83,8 +77,7 @@
// FIXME: We need to pass the container type through to this function. In
// practice this isn't super important since the subsection header describes
// its length and we can just skip it. It's more important when writing.
- if (auto EC = codeview::DebugSubsectionRecord::initialize(
- Stream, Info, codeview::CodeViewContainer::Pdb))
+ if (auto EC = codeview::DebugSubsectionRecord::initialize(Stream, Info))
return EC;
Length = alignTo(Info.getRecordLength(), 4);
return Error::success();
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h
index 720b1b4..624a623 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h
@@ -10,10 +10,8 @@
#define LLVM_DEBUGINFO_CODEVIEW_MODULEDEBUGFRAGMENTVISITOR_H
#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
#include "llvm/Support/Error.h"
-#include <cstdint>
namespace llvm {
@@ -30,7 +28,6 @@
class DebugSymbolRVASubsectionRef;
class DebugSymbolsSubsectionRef;
class DebugUnknownSubsectionRef;
-class StringsAndChecksumsRef;
class DebugSubsectionVisitor {
public:
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h
index 784fc59..51b8523 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/DebugSymbolsSubsection.h
@@ -9,8 +9,8 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLSSUBSECTION_H
#define LLVM_DEBUGINFO_CODEVIEW_DEBUGSYMBOLSSUBSECTION_H
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/DebugSubsection.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/Support/Error.h"
namespace llvm {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/EnumTables.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/EnumTables.h
index ed126ed..270cd4b 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/EnumTables.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/EnumTables.h
@@ -37,6 +37,17 @@
ArrayRef<EnumEntry<uint16_t>> getTrampolineNames();
ArrayRef<EnumEntry<COFF::SectionCharacteristics>>
getImageSectionCharacteristicNames();
+ArrayRef<EnumEntry<uint16_t>> getClassOptionNames();
+ArrayRef<EnumEntry<uint8_t>> getMemberAccessNames();
+ArrayRef<EnumEntry<uint16_t>> getMethodOptionNames();
+ArrayRef<EnumEntry<uint16_t>> getMemberKindNames();
+ArrayRef<EnumEntry<uint8_t>> getPtrKindNames();
+ArrayRef<EnumEntry<uint8_t>> getPtrModeNames();
+ArrayRef<EnumEntry<uint16_t>> getPtrMemberRepNames();
+ArrayRef<EnumEntry<uint16_t>> getTypeModifierNames();
+ArrayRef<EnumEntry<uint8_t>> getCallingConventions();
+ArrayRef<EnumEntry<uint8_t>> getFunctionOptionEnum();
+ArrayRef<EnumEntry<uint16_t>> getLabelTypeEnum();
} // end namespace codeview
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
index a43ce20..8c22eaf 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
@@ -43,14 +43,14 @@
/// Contains a list of all records indexed by TypeIndex.toArrayIndex().
SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
- /// Contains a list of all hash values inexed by TypeIndex.toArrayIndex().
+ /// Contains a list of all hash values indexed by TypeIndex.toArrayIndex().
SmallVector<GloballyHashedType, 2> SeenHashes;
public:
explicit GlobalTypeTableBuilder(BumpPtrAllocator &Storage);
~GlobalTypeTableBuilder();
- // TypeTableCollection overrides
+ // TypeCollection overrides
Optional<TypeIndex> getFirst() override;
Optional<TypeIndex> getNext(TypeIndex Prev) override;
CVType getType(TypeIndex Index) override;
@@ -58,6 +58,7 @@
bool contains(TypeIndex Index) override;
uint32_t size() override;
uint32_t capacity() override;
+ bool replaceType(TypeIndex &Index, CVType Data, bool Stabilize) override;
// public interface
void reset();
@@ -71,6 +72,11 @@
template <typename CreateFunc>
TypeIndex insertRecordAs(GloballyHashedType Hash, size_t RecordSize,
CreateFunc Create) {
+ assert(RecordSize < UINT32_MAX && "Record too big");
+ assert(RecordSize % 4 == 0 &&
+ "RecordSize is not a multiple of 4 bytes which will cause "
+ "misalignment in the output TPI stream!");
+
auto Result = HashedRecords.try_emplace(Hash, nextTypeIndex());
if (LLVM_UNLIKELY(Result.second /*inserted*/ ||
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
index 4e03627..ddbb4e3 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
@@ -14,7 +14,6 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Error.h"
@@ -79,6 +78,7 @@
uint32_t capacity() override;
Optional<TypeIndex> getFirst() override;
Optional<TypeIndex> getNext(TypeIndex Prev) override;
+ bool replaceType(TypeIndex &Index, CVType Data, bool Stabilize) override;
private:
Error ensureTypeExists(TypeIndex Index);
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h
index 1b2f6d2..2f3d7a9 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h
@@ -47,7 +47,7 @@
explicit MergingTypeTableBuilder(BumpPtrAllocator &Storage);
~MergingTypeTableBuilder();
- // TypeTableCollection overrides
+ // TypeCollection overrides
Optional<TypeIndex> getFirst() override;
Optional<TypeIndex> getNext(TypeIndex Prev) override;
CVType getType(TypeIndex Index) override;
@@ -55,6 +55,7 @@
bool contains(TypeIndex Index) override;
uint32_t size() override;
uint32_t capacity() override;
+ bool replaceType(TypeIndex &Index, CVType Data, bool Stabilize) override;
// public interface
void reset();
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/RecordName.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/RecordName.h
index cc09db8..8e06be9 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/RecordName.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/RecordName.h
@@ -9,7 +9,6 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H
#define LLVM_DEBUGINFO_CODEVIEW_RECORDNAME_H
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeCollection.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h
index 3ca09b4..fcc0452 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h
@@ -10,25 +10,11 @@
#define LLVM_DEBUGINFO_CODEVIEW_SIMPLETYPESERIALIZER_H
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/RecordSerialization.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeRecordMapping.h"
-#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/BinaryByteStream.h"
-#include "llvm/Support/BinaryStreamWriter.h"
-#include "llvm/Support/Error.h"
-#include <cassert>
-#include <cstdint>
-#include <memory>
#include <vector>
namespace llvm {
namespace codeview {
+class FieldListRecord;
class SimpleTypeSerializer {
std::vector<uint8_t> ScratchBuffer;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
index 62761cb..108abb2 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
@@ -62,7 +62,7 @@
Error visitSymbolBegin(CVSymbol &Record) override {
assert(!Mapping && "Already in a symbol mapping!");
- Mapping = llvm::make_unique<MappingInfo>(Record.content(), Container);
+ Mapping = std::make_unique<MappingInfo>(Record.content(), Container);
return Mapping->Mapping.visitSymbolBegin(Record);
}
Error visitSymbolEnd(CVSymbol &Record) override {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolDumper.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolDumper.h
index d832a48..aaeffb2 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolDumper.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolDumper.h
@@ -11,8 +11,8 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/SymbolDumpDelegate.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
namespace llvm {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolRecord.h
index 5e9a743..c37f6b4 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolRecord.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -73,17 +73,17 @@
Thunk32Sym(SymbolRecordKind Kind, uint32_t RecordOffset)
: SymbolRecord(Kind), RecordOffset(RecordOffset) {}
- uint32_t Parent;
- uint32_t End;
- uint32_t Next;
- uint32_t Offset;
- uint16_t Segment;
- uint16_t Length;
- ThunkOrdinal Thunk;
+ uint32_t Parent = 0;
+ uint32_t End = 0;
+ uint32_t Next = 0;
+ uint32_t Offset = 0;
+ uint16_t Segment = 0;
+ uint16_t Length = 0;
+ ThunkOrdinal Thunk = ThunkOrdinal::Standard;
StringRef Name;
ArrayRef<uint8_t> VariantData;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_TRAMPOLINE
@@ -94,13 +94,13 @@
: SymbolRecord(Kind), RecordOffset(RecordOffset) {}
TrampolineType Type;
- uint16_t Size;
- uint32_t ThunkOffset;
- uint32_t TargetOffset;
- uint16_t ThunkSection;
- uint16_t TargetSection;
+ uint16_t Size = 0;
+ uint32_t ThunkOffset = 0;
+ uint32_t TargetOffset = 0;
+ uint16_t ThunkSection = 0;
+ uint16_t TargetSection = 0;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_SECTION
@@ -110,14 +110,14 @@
SectionSym(SymbolRecordKind Kind, uint32_t RecordOffset)
: SymbolRecord(Kind), RecordOffset(RecordOffset) {}
- uint16_t SectionNumber;
- uint8_t Alignment;
- uint32_t Rva;
- uint32_t Length;
- uint32_t Characteristics;
+ uint16_t SectionNumber = 0;
+ uint8_t Alignment = 0;
+ uint32_t Rva = 0;
+ uint32_t Length = 0;
+ uint32_t Characteristics = 0;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_COFFGROUP
@@ -127,13 +127,13 @@
CoffGroupSym(SymbolRecordKind Kind, uint32_t RecordOffset)
: SymbolRecord(Kind), RecordOffset(RecordOffset) {}
- uint32_t Size;
- uint32_t Characteristics;
- uint32_t Offset;
- uint16_t Segment;
+ uint32_t Size = 0;
+ uint32_t Characteristics = 0;
+ uint32_t Offset = 0;
+ uint16_t Segment = 0;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
class ScopeEndSym : public SymbolRecord {
@@ -142,7 +142,7 @@
ScopeEndSym(SymbolRecordKind Kind, uint32_t RecordOffset)
: SymbolRecord(Kind), RecordOffset(RecordOffset) {}
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
class CallerSym : public SymbolRecord {
@@ -153,13 +153,13 @@
std::vector<TypeIndex> Indices;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
struct DecodedAnnotation {
StringRef Name;
ArrayRef<uint8_t> Bytes;
- BinaryAnnotationsOpCode OpCode;
+ BinaryAnnotationsOpCode OpCode = BinaryAnnotationsOpCode::Invalid;
uint32_t U1 = 0;
uint32_t U2 = 0;
int32_t S1 = 0;
@@ -333,7 +333,7 @@
class InlineSiteSym : public SymbolRecord {
public:
explicit InlineSiteSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- InlineSiteSym(uint32_t RecordOffset)
+ explicit InlineSiteSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::InlineSiteSym),
RecordOffset(RecordOffset) {}
@@ -342,12 +342,19 @@
BinaryAnnotationIterator());
}
- uint32_t Parent;
- uint32_t End;
+ uint32_t Parent = 0;
+ uint32_t End = 0;
TypeIndex Inlinee;
std::vector<uint8_t> AnnotationData;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
+};
+
+struct PublicSym32Header {
+ ulittle32_t Flags;
+ ulittle32_t Offset;
+ ulittle16_t Segment;
+ // char Name[];
};
// S_PUB32
@@ -371,7 +378,7 @@
class RegisterSym : public SymbolRecord {
public:
explicit RegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- RegisterSym(uint32_t RecordOffset)
+ explicit RegisterSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::RegisterSym),
RecordOffset(RecordOffset) {}
@@ -379,7 +386,7 @@
RegisterId Register;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_PROCREF, S_LPROCREF
@@ -390,13 +397,13 @@
: SymbolRecord(SymbolRecordKind::ProcRefSym), RecordOffset(RecordOffset) {
}
- uint32_t SumName;
- uint32_t SymOffset;
- uint16_t Module;
+ uint32_t SumName = 0;
+ uint32_t SymOffset = 0;
+ uint16_t Module = 0;
StringRef Name;
uint16_t modi() const { return Module - 1; }
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_LOCAL
@@ -407,21 +414,21 @@
: SymbolRecord(SymbolRecordKind::LocalSym), RecordOffset(RecordOffset) {}
TypeIndex Type;
- LocalSymFlags Flags;
+ LocalSymFlags Flags = LocalSymFlags::None;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
struct LocalVariableAddrRange {
- uint32_t OffsetStart;
- uint16_t ISectStart;
- uint16_t Range;
+ uint32_t OffsetStart = 0;
+ uint16_t ISectStart = 0;
+ uint16_t Range = 0;
};
struct LocalVariableAddrGap {
- uint16_t GapStartOffset;
- uint16_t Range;
+ uint16_t GapStartOffset = 0;
+ uint16_t Range = 0;
};
enum : uint16_t { MaxDefRange = 0xf000 };
@@ -440,11 +447,11 @@
return RecordOffset + RelocationOffset;
}
- uint32_t Program;
+ uint32_t Program = 0;
LocalVariableAddrRange Range;
std::vector<LocalVariableAddrGap> Gaps;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_DEFRANGE_SUBFIELD
@@ -453,7 +460,7 @@
public:
explicit DefRangeSubfieldSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- DefRangeSubfieldSym(uint32_t RecordOffset)
+ explicit DefRangeSubfieldSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeSubfieldSym),
RecordOffset(RecordOffset) {}
@@ -461,58 +468,62 @@
return RecordOffset + RelocationOffset;
}
- uint32_t Program;
- uint16_t OffsetInParent;
+ uint32_t Program = 0;
+ uint16_t OffsetInParent = 0;
LocalVariableAddrRange Range;
std::vector<LocalVariableAddrGap> Gaps;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
+};
+
+struct DefRangeRegisterHeader {
+ ulittle16_t Register;
+ ulittle16_t MayHaveNoName;
};
// S_DEFRANGE_REGISTER
class DefRangeRegisterSym : public SymbolRecord {
public:
- struct Header {
- ulittle16_t Register;
- ulittle16_t MayHaveNoName;
- };
-
explicit DefRangeRegisterSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- DefRangeRegisterSym(uint32_t RecordOffset)
+ explicit DefRangeRegisterSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeRegisterSym),
RecordOffset(RecordOffset) {}
- uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
+ uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterHeader); }
- Header Hdr;
+ DefRangeRegisterHeader Hdr;
LocalVariableAddrRange Range;
std::vector<LocalVariableAddrGap> Gaps;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
+};
+
+struct DefRangeSubfieldRegisterHeader {
+ ulittle16_t Register;
+ ulittle16_t MayHaveNoName;
+ ulittle32_t OffsetInParent;
};
// S_DEFRANGE_SUBFIELD_REGISTER
class DefRangeSubfieldRegisterSym : public SymbolRecord {
public:
- struct Header {
- ulittle16_t Register;
- ulittle16_t MayHaveNoName;
- ulittle32_t OffsetInParent;
- };
-
explicit DefRangeSubfieldRegisterSym(SymbolRecordKind Kind)
: SymbolRecord(Kind) {}
- DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
+ explicit DefRangeSubfieldRegisterSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeSubfieldRegisterSym),
RecordOffset(RecordOffset) {}
- uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
+ uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeSubfieldRegisterHeader); }
- Header Hdr;
+ DefRangeSubfieldRegisterHeader Hdr;
LocalVariableAddrRange Range;
std::vector<LocalVariableAddrGap> Gaps;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
+};
+
+struct DefRangeFramePointerRelHeader {
+ little32_t Offset;
};
// S_DEFRANGE_FRAMEPOINTER_REL
@@ -522,7 +533,7 @@
public:
explicit DefRangeFramePointerRelSym(SymbolRecordKind Kind)
: SymbolRecord(Kind) {}
- DefRangeFramePointerRelSym(uint32_t RecordOffset)
+ explicit DefRangeFramePointerRelSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelSym),
RecordOffset(RecordOffset) {}
@@ -530,22 +541,22 @@
return RecordOffset + RelocationOffset;
}
- int32_t Offset;
+ DefRangeFramePointerRelHeader Hdr;
LocalVariableAddrRange Range;
std::vector<LocalVariableAddrGap> Gaps;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
+};
+
+struct DefRangeRegisterRelHeader {
+ ulittle16_t Register;
+ ulittle16_t Flags;
+ little32_t BasePointerOffset;
};
// S_DEFRANGE_REGISTER_REL
class DefRangeRegisterRelSym : public SymbolRecord {
public:
- struct Header {
- ulittle16_t Register;
- ulittle16_t Flags;
- little32_t BasePointerOffset;
- };
-
explicit DefRangeRegisterRelSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
explicit DefRangeRegisterRelSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DefRangeRegisterRelSym),
@@ -563,13 +574,13 @@
bool hasSpilledUDTMember() const { return Hdr.Flags & IsSubfieldFlag; }
uint16_t offsetInParent() const { return Hdr.Flags >> OffsetInParentShift; }
- uint32_t getRelocationOffset() const { return RecordOffset + sizeof(Header); }
+ uint32_t getRelocationOffset() const { return RecordOffset + sizeof(DefRangeRegisterRelHeader); }
- Header Hdr;
+ DefRangeRegisterRelHeader Hdr;
LocalVariableAddrRange Range;
std::vector<LocalVariableAddrGap> Gaps;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_DEFRANGE_FRAMEPOINTER_REL_FULL_SCOPE
@@ -581,9 +592,9 @@
: SymbolRecord(SymbolRecordKind::DefRangeFramePointerRelFullScopeSym),
RecordOffset(RecordOffset) {}
- int32_t Offset;
+ int32_t Offset = 0;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_BLOCK32
@@ -599,14 +610,14 @@
return RecordOffset + RelocationOffset;
}
- uint32_t Parent;
- uint32_t End;
- uint32_t CodeSize;
- uint32_t CodeOffset;
- uint16_t Segment;
+ uint32_t Parent = 0;
+ uint32_t End = 0;
+ uint32_t CodeSize = 0;
+ uint32_t CodeOffset = 0;
+ uint16_t Segment = 0;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_LABEL32
@@ -622,12 +633,12 @@
return RecordOffset + RelocationOffset;
}
- uint32_t CodeOffset;
- uint16_t Segment;
- ProcSymFlags Flags;
+ uint32_t CodeOffset = 0;
+ uint16_t Segment = 0;
+ ProcSymFlags Flags = ProcSymFlags::None;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_OBJNAME
@@ -635,82 +646,82 @@
public:
explicit ObjNameSym() : SymbolRecord(SymbolRecordKind::ObjNameSym) {}
explicit ObjNameSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- ObjNameSym(uint32_t RecordOffset)
+ explicit ObjNameSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::ObjNameSym), RecordOffset(RecordOffset) {
}
- uint32_t Signature;
+ uint32_t Signature = 0;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_ENVBLOCK
class EnvBlockSym : public SymbolRecord {
public:
explicit EnvBlockSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- EnvBlockSym(uint32_t RecordOffset)
+ explicit EnvBlockSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::EnvBlockSym),
RecordOffset(RecordOffset) {}
std::vector<StringRef> Fields;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_EXPORT
class ExportSym : public SymbolRecord {
public:
explicit ExportSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- ExportSym(uint32_t RecordOffset)
+ explicit ExportSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::ExportSym), RecordOffset(RecordOffset) {}
- uint16_t Ordinal;
- ExportFlags Flags;
+ uint16_t Ordinal = 0;
+ ExportFlags Flags = ExportFlags::None;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_FILESTATIC
class FileStaticSym : public SymbolRecord {
public:
explicit FileStaticSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- FileStaticSym(uint32_t RecordOffset)
+ explicit FileStaticSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::FileStaticSym),
RecordOffset(RecordOffset) {}
TypeIndex Index;
- uint32_t ModFilenameOffset;
- LocalSymFlags Flags;
+ uint32_t ModFilenameOffset = 0;
+ LocalSymFlags Flags = LocalSymFlags::None;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_COMPILE2
class Compile2Sym : public SymbolRecord {
public:
explicit Compile2Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- Compile2Sym(uint32_t RecordOffset)
+ explicit Compile2Sym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::Compile2Sym),
RecordOffset(RecordOffset) {}
- CompileSym2Flags Flags;
+ CompileSym2Flags Flags = CompileSym2Flags::None;
CPUType Machine;
- uint16_t VersionFrontendMajor;
- uint16_t VersionFrontendMinor;
- uint16_t VersionFrontendBuild;
- uint16_t VersionBackendMajor;
- uint16_t VersionBackendMinor;
- uint16_t VersionBackendBuild;
+ uint16_t VersionFrontendMajor = 0;
+ uint16_t VersionFrontendMinor = 0;
+ uint16_t VersionFrontendBuild = 0;
+ uint16_t VersionBackendMajor = 0;
+ uint16_t VersionBackendMinor = 0;
+ uint16_t VersionBackendBuild = 0;
StringRef Version;
std::vector<StringRef> ExtraStrings;
uint8_t getLanguage() const { return static_cast<uint32_t>(Flags) & 0xFF; }
uint32_t getFlags() const { return static_cast<uint32_t>(Flags) & ~0xFF; }
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_COMPILE3
@@ -718,20 +729,20 @@
public:
Compile3Sym() : SymbolRecord(SymbolRecordKind::Compile3Sym) {}
explicit Compile3Sym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- Compile3Sym(uint32_t RecordOffset)
+ explicit Compile3Sym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::Compile3Sym),
RecordOffset(RecordOffset) {}
- CompileSym3Flags Flags;
+ CompileSym3Flags Flags = CompileSym3Flags::None;
CPUType Machine;
- uint16_t VersionFrontendMajor;
- uint16_t VersionFrontendMinor;
- uint16_t VersionFrontendBuild;
- uint16_t VersionFrontendQFE;
- uint16_t VersionBackendMajor;
- uint16_t VersionBackendMinor;
- uint16_t VersionBackendBuild;
- uint16_t VersionBackendQFE;
+ uint16_t VersionFrontendMajor = 0;
+ uint16_t VersionFrontendMinor = 0;
+ uint16_t VersionFrontendBuild = 0;
+ uint16_t VersionFrontendQFE = 0;
+ uint16_t VersionBackendMajor = 0;
+ uint16_t VersionBackendMinor = 0;
+ uint16_t VersionBackendBuild = 0;
+ uint16_t VersionBackendQFE = 0;
StringRef Version;
void setLanguage(SourceLanguage Lang) {
@@ -750,7 +761,7 @@
(getFlags() & (CompileSym3Flags::PGO | CompileSym3Flags::LTCG));
}
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_FRAMEPROC
@@ -761,13 +772,13 @@
: SymbolRecord(SymbolRecordKind::FrameProcSym),
RecordOffset(RecordOffset) {}
- uint32_t TotalFrameBytes;
- uint32_t PaddingFrameBytes;
- uint32_t OffsetToPadding;
- uint32_t BytesOfCalleeSavedRegisters;
- uint32_t OffsetOfExceptionHandler;
- uint16_t SectionIdOfExceptionHandler;
- FrameProcedureOptions Flags;
+ uint32_t TotalFrameBytes = 0;
+ uint32_t PaddingFrameBytes = 0;
+ uint32_t OffsetToPadding = 0;
+ uint32_t BytesOfCalleeSavedRegisters = 0;
+ uint32_t OffsetOfExceptionHandler = 0;
+ uint16_t SectionIdOfExceptionHandler = 0;
+ FrameProcedureOptions Flags = FrameProcedureOptions::None;
/// Extract the register this frame uses to refer to local variables.
RegisterId getLocalFramePtrReg(CPUType CPU) const {
@@ -781,7 +792,7 @@
EncodedFramePtrReg((uint32_t(Flags) >> 16U) & 0x3U), CPU);
}
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
private:
};
@@ -799,11 +810,11 @@
return RecordOffset + RelocationOffset;
}
- uint32_t CodeOffset;
- uint16_t Segment;
+ uint32_t CodeOffset = 0;
+ uint16_t Segment = 0;
TypeIndex Type;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_HEAPALLOCSITE
@@ -820,12 +831,12 @@
return RecordOffset + RelocationOffset;
}
- uint32_t CodeOffset;
- uint16_t Segment;
- uint16_t CallInstructionSize;
+ uint32_t CodeOffset = 0;
+ uint16_t Segment = 0;
+ uint16_t CallInstructionSize = 0;
TypeIndex Type;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_FRAMECOOKIE
@@ -841,12 +852,12 @@
return RecordOffset + RelocationOffset;
}
- uint32_t CodeOffset;
- uint16_t Register;
+ uint32_t CodeOffset = 0;
+ uint16_t Register = 0;
FrameCookieKind CookieKind;
- uint8_t Flags;
+ uint8_t Flags = 0;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_UDT, S_COBOLUDT
@@ -859,20 +870,20 @@
TypeIndex Type;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_BUILDINFO
class BuildInfoSym : public SymbolRecord {
public:
explicit BuildInfoSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- BuildInfoSym(uint32_t RecordOffset)
+ explicit BuildInfoSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::BuildInfoSym),
RecordOffset(RecordOffset) {}
TypeIndex BuildId;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_BPREL32
@@ -883,11 +894,11 @@
: SymbolRecord(SymbolRecordKind::BPRelativeSym),
RecordOffset(RecordOffset) {}
- int32_t Offset;
+ int32_t Offset = 0;
TypeIndex Type;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_REGREL32
@@ -898,19 +909,19 @@
: SymbolRecord(SymbolRecordKind::RegRelativeSym),
RecordOffset(RecordOffset) {}
- uint32_t Offset;
+ uint32_t Offset = 0;
TypeIndex Type;
RegisterId Register;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_CONSTANT, S_MANCONSTANT
class ConstantSym : public SymbolRecord {
public:
explicit ConstantSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- ConstantSym(uint32_t RecordOffset)
+ explicit ConstantSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::ConstantSym),
RecordOffset(RecordOffset) {}
@@ -918,7 +929,7 @@
APSInt Value;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_LDATA32, S_GDATA32, S_LMANDATA, S_GMANDATA
@@ -927,7 +938,7 @@
public:
explicit DataSym(SymbolRecordKind Kind) : SymbolRecord(Kind) {}
- DataSym(uint32_t RecordOffset)
+ explicit DataSym(uint32_t RecordOffset)
: SymbolRecord(SymbolRecordKind::DataSym), RecordOffset(RecordOffset) {}
uint32_t getRelocationOffset() const {
@@ -935,11 +946,11 @@
}
TypeIndex Type;
- uint32_t DataOffset;
- uint16_t Segment;
+ uint32_t DataOffset = 0;
+ uint16_t Segment = 0;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_LTHREAD32, S_GTHREAD32
@@ -957,11 +968,11 @@
}
TypeIndex Type;
- uint32_t DataOffset;
- uint16_t Segment;
+ uint32_t DataOffset = 0;
+ uint16_t Segment = 0;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_UNAMESPACE
@@ -974,7 +985,7 @@
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_ANNOTATION
@@ -989,12 +1000,9 @@
uint16_t Segment = 0;
std::vector<StringRef> Strings;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
-using CVSymbol = CVRecord<SymbolKind>;
-using CVSymbolArray = VarStreamArray<CVSymbol>;
-
Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
uint32_t Offset);
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h
index 57dbc56..71bc70d 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/SymbolRecordHelpers.h
@@ -9,7 +9,8 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORDHELPERS_H
#define LLVM_DEBUGINFO_CODEVIEW_SYMBOLRECORDHELPERS_H
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
namespace llvm {
namespace codeview {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeCollection.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeCollection.h
index 58b1dd0..bde5a8b 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeCollection.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeCollection.h
@@ -10,9 +10,8 @@
#define LLVM_DEBUGINFO_CODEVIEW_TYPECOLLECTION_H
#include "llvm/ADT/StringRef.h"
-
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
namespace llvm {
namespace codeview {
@@ -30,6 +29,7 @@
virtual bool contains(TypeIndex Index) = 0;
virtual uint32_t size() = 0;
virtual uint32_t capacity() = 0;
+ virtual bool replaceType(TypeIndex &Index, CVType Data, bool Stabilize) = 0;
template <typename TFunc> void ForEachRecord(TFunc Func) {
Optional<TypeIndex> Next = getFirst();
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
index 081de32..2b17f5c 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
@@ -66,7 +66,7 @@
Error visitTypeBegin(CVType &Record) override {
assert(!Mapping && "Already in a type mapping!");
- Mapping = llvm::make_unique<MappingInfo>(Record.content());
+ Mapping = std::make_unique<MappingInfo>(Record.content());
return Mapping->Mapping.visitTypeBegin(Record);
}
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeHashing.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeHashing.h
index b0a16cc..9f34d02 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeHashing.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeHashing.h
@@ -86,6 +86,16 @@
bool empty() const { return *(const uint64_t*)Hash.data() == 0; }
+ friend inline bool operator==(const GloballyHashedType &L,
+ const GloballyHashedType &R) {
+ return L.Hash == R.Hash;
+ }
+
+ friend inline bool operator!=(const GloballyHashedType &L,
+ const GloballyHashedType &R) {
+ return !(L.Hash == R.Hash);
+ }
+
/// Given a sequence of bytes representing a record, compute a global hash for
/// this record. Due to the nature of global hashes incorporating the hashes
/// of referenced records, this function requires a list of types and ids
@@ -161,15 +171,10 @@
return Hashes;
}
};
-#if defined(_MSC_VER)
-// is_trivially_copyable is not available in older versions of libc++, but it is
-// available in all supported versions of MSVC, so at least this gives us some
-// coverage.
static_assert(std::is_trivially_copyable<GloballyHashedType>::value,
"GloballyHashedType must be trivially copyable so that we can "
"reinterpret_cast arrays of hash data to arrays of "
"GloballyHashedType");
-#endif
} // namespace codeview
template <> struct DenseMapInfo<codeview::LocallyHashedType> {
@@ -206,7 +211,7 @@
static bool isEqual(codeview::GloballyHashedType LHS,
codeview::GloballyHashedType RHS) {
- return LHS.Hash == RHS.Hash;
+ return LHS == RHS;
}
};
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeIndex.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeIndex.h
index b9e2562..bdc6cf4 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeIndex.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeIndex.h
@@ -116,13 +116,22 @@
uint32_t toArrayIndex() const {
assert(!isSimple());
- return getIndex() - FirstNonSimpleIndex;
+ return (getIndex() & ~DecoratedItemIdMask) - FirstNonSimpleIndex;
}
static TypeIndex fromArrayIndex(uint32_t Index) {
return TypeIndex(Index + FirstNonSimpleIndex);
}
+ static TypeIndex fromDecoratedArrayIndex(bool IsItem, uint32_t Index) {
+ return TypeIndex((Index + FirstNonSimpleIndex) |
+ (IsItem ? DecoratedItemIdMask : 0));
+ }
+
+ TypeIndex removeDecoration() {
+ return TypeIndex(Index & ~DecoratedItemIdMask);
+ }
+
SimpleTypeKind getSimpleKind() const {
assert(isSimple());
return static_cast<SimpleTypeKind>(Index & SimpleKindMask);
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
index 4697687..f4f5835 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
@@ -10,8 +10,8 @@
#define LLVM_DEBUGINFO_CODEVIEW_TYPEINDEXDISCOVERY_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/Support/Error.h"
namespace llvm {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecord.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecord.h
index b147dd6..3b6d1b0 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecord.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecord.h
@@ -14,7 +14,6 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/CodeView/GUID.h"
@@ -32,15 +31,10 @@
using support::ulittle16_t;
using support::ulittle32_t;
-using CVType = CVRecord<TypeLeafKind>;
-using RemappedType = RemappedRecord<TypeLeafKind>;
-
struct CVMemberRecord {
TypeLeafKind Kind;
ArrayRef<uint8_t> Data;
};
-using CVTypeArray = VarStreamArray<CVType>;
-using CVTypeRange = iterator_range<CVTypeArray::Iterator>;
/// Equvalent to CV_fldattr_t in cvinfo.h.
struct MemberAttributes {
@@ -144,7 +138,7 @@
ModifierOptions getModifiers() const { return Modifiers; }
TypeIndex ModifiedType;
- ModifierOptions Modifiers;
+ ModifierOptions Modifiers = ModifierOptions::None;
};
// LF_PROCEDURE
@@ -168,7 +162,7 @@
TypeIndex ReturnType;
CallingConvention CallConv;
FunctionOptions Options;
- uint16_t ParameterCount;
+ uint16_t ParameterCount = 0;
TypeIndex ArgumentList;
};
@@ -202,9 +196,9 @@
TypeIndex ThisType;
CallingConvention CallConv;
FunctionOptions Options;
- uint16_t ParameterCount;
+ uint16_t ParameterCount = 0;
TypeIndex ArgumentList;
- int32_t ThisPointerAdjustment;
+ int32_t ThisPointerAdjustment = 0;
};
// LF_LABEL
@@ -351,7 +345,7 @@
}
TypeIndex ReferentType;
- uint32_t Attrs;
+ uint32_t Attrs = 0;
Optional<MemberPointerInfo> MemberInfo;
void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
@@ -414,7 +408,7 @@
TypeIndex ElementType;
TypeIndex IndexType;
- uint64_t Size;
+ uint64_t Size = 0;
StringRef Name;
};
@@ -459,7 +453,7 @@
StringRef getName() const { return Name; }
StringRef getUniqueName() const { return UniqueName; }
- uint16_t MemberCount;
+ uint16_t MemberCount = 0;
ClassOptions Options;
TypeIndex FieldList;
StringRef Name;
@@ -496,7 +490,7 @@
TypeIndex DerivationList;
TypeIndex VTableShape;
- uint64_t Size;
+ uint64_t Size = 0;
};
// LF_UNION
@@ -517,7 +511,7 @@
uint64_t getSize() const { return Size; }
- uint64_t Size;
+ uint64_t Size = 0;
};
// LF_ENUM
@@ -550,8 +544,8 @@
uint8_t getBitSize() const { return BitSize; }
TypeIndex Type;
- uint8_t BitSize;
- uint8_t BitOffset;
+ uint8_t BitSize = 0;
+ uint8_t BitOffset = 0;
};
// LF_VTSHAPE
@@ -592,7 +586,7 @@
StringRef getName() const { return Name; }
GUID Guid;
- uint32_t Age;
+ uint32_t Age = 0;
StringRef Name;
};
@@ -644,7 +638,7 @@
TypeIndex UDT;
TypeIndex SourceFile;
- uint32_t LineNumber;
+ uint32_t LineNumber = 0;
};
// LF_UDT_MOD_SRC_LINE
@@ -664,8 +658,8 @@
TypeIndex UDT;
TypeIndex SourceFile;
- uint32_t LineNumber;
- uint16_t Module;
+ uint32_t LineNumber = 0;
+ uint16_t Module = 0;
};
// LF_BUILDINFO
@@ -703,7 +697,7 @@
: TypeRecord(TypeRecordKind::VFTable), CompleteClass(CompleteClass),
OverriddenVFTable(OverriddenVFTable), VFPtrOffset(VFPtrOffset) {
MethodNames.push_back(Name);
- MethodNames.insert(MethodNames.end(), Methods.begin(), Methods.end());
+ llvm::append_range(MethodNames, Methods);
}
TypeIndex getCompleteClass() const { return CompleteClass; }
@@ -717,7 +711,7 @@
TypeIndex CompleteClass;
TypeIndex OverriddenVFTable;
- uint32_t VFPtrOffset;
+ uint32_t VFPtrOffset = 0;
std::vector<StringRef> MethodNames;
};
@@ -749,7 +743,7 @@
TypeIndex Type;
MemberAttributes Attrs;
- int32_t VFTableOffset;
+ int32_t VFTableOffset = 0;
StringRef Name;
};
@@ -780,7 +774,7 @@
TypeIndex getMethodList() const { return MethodList; }
StringRef getName() const { return Name; }
- uint16_t NumOverloads;
+ uint16_t NumOverloads = 0;
TypeIndex MethodList;
StringRef Name;
};
@@ -806,7 +800,7 @@
MemberAttributes Attrs;
TypeIndex Type;
- uint64_t FieldOffset;
+ uint64_t FieldOffset = 0;
StringRef Name;
};
@@ -883,7 +877,7 @@
MemberAttributes Attrs;
TypeIndex Type;
- uint64_t Offset;
+ uint64_t Offset = 0;
};
// LF_VBCLASS, LF_IVBCLASS
@@ -911,8 +905,8 @@
MemberAttributes Attrs;
TypeIndex BaseType;
TypeIndex VBPtrType;
- uint64_t VBPtrOffset;
- uint64_t VTableIndex;
+ uint64_t VBPtrOffset = 0;
+ uint64_t VTableIndex = 0;
};
/// LF_INDEX - Used to chain two large LF_FIELDLIST or LF_METHODLIST records
@@ -941,9 +935,9 @@
uint32_t getSignature() const { return Signature; }
StringRef getPrecompFilePath() const { return PrecompFilePath; }
- uint32_t StartTypeIndex;
- uint32_t TypesCount;
- uint32_t Signature;
+ uint32_t StartTypeIndex = 0;
+ uint32_t TypesCount = 0;
+ uint32_t Signature = 0;
StringRef PrecompFilePath;
};
@@ -955,7 +949,7 @@
uint32_t getSignature() const { return Signature; }
- uint32_t Signature;
+ uint32_t Signature = 0;
};
} // end namespace codeview
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h
index e84704d..041f521 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecordHelpers.h
@@ -9,19 +9,39 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDHELPERS_H
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
namespace llvm {
- namespace codeview {
- /// Given an arbitrary codeview type, determine if it is an LF_STRUCTURE,
- /// LF_CLASS, LF_INTERFACE, LF_UNION, or LF_ENUM with the forward ref class
- /// option.
- bool isUdtForwardRef(CVType CVT);
+namespace codeview {
- /// Given a CVType which is assumed to be an LF_MODIFIER, return the
- /// TypeIndex of the type that the LF_MODIFIER modifies.
- TypeIndex getModifiedType(const CVType &CVT);
+/// Given an arbitrary codeview type, determine if it is an LF_STRUCTURE,
+/// LF_CLASS, LF_INTERFACE, LF_UNION, or LF_ENUM with the forward ref class
+/// option.
+bool isUdtForwardRef(CVType CVT);
+
+/// Given a CVType which is assumed to be an LF_MODIFIER, return the
+/// TypeIndex of the type that the LF_MODIFIER modifies.
+TypeIndex getModifiedType(const CVType &CVT);
+
+/// Return true if this record should be in the IPI stream of a PDB. In an
+/// object file, these record kinds will appear mixed into the .debug$T section.
+inline bool isIdRecord(TypeLeafKind K) {
+ switch (K) {
+ case TypeLeafKind::LF_FUNC_ID:
+ case TypeLeafKind::LF_MFUNC_ID:
+ case TypeLeafKind::LF_STRING_ID:
+ case TypeLeafKind::LF_SUBSTR_LIST:
+ case TypeLeafKind::LF_BUILDINFO:
+ case TypeLeafKind::LF_UDT_SRC_LINE:
+ case TypeLeafKind::LF_UDT_MOD_SRC_LINE:
+ return true;
+ default:
+ return false;
}
}
+} // namespace codeview
+} // namespace llvm
+
#endif
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
index 4c309c1..c6044d5 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeRecordMapping.h
@@ -10,6 +10,7 @@
#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDMAPPING_H
#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/CodeViewRecordIO.h"
#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
#include "llvm/Support/Error.h"
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
index d0506cc..04d7c7b 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -11,7 +11,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/Support/Error.h"
namespace llvm {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h
index 4f2e5de..01525d0 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeSymbolEmitter.h
@@ -9,13 +9,11 @@
#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESYMBOLEMITTER_H
#define LLVM_DEBUGINFO_CODEVIEW_TYPESYMBOLEMITTER_H
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-
namespace llvm {
class StringRef;
namespace codeview {
+class TypeIndex;
class TypeSymbolEmitter {
private:
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeTableCollection.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
index 5cbe340..c300874 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeTableCollection.h
@@ -29,6 +29,7 @@
bool contains(TypeIndex Index) override;
uint32_t size() override;
uint32_t capacity() override;
+ bool replaceType(TypeIndex &Index, CVType Data, bool Stabilize) override;
private:
BumpPtrAllocator Allocator;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h
index 169715b..fb0b579 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/CodeView/TypeVisitorCallbackPipeline.h
@@ -82,11 +82,6 @@
Pipeline.push_back(&Callbacks);
}
- void addCallbackToPipelineFront(TypeVisitorCallbacks &Callbacks) {
- auto CallBackItr = Pipeline.begin();
- Pipeline.insert(CallBackItr, &Callbacks);
- }
-
#define TYPE_RECORD(EnumName, EnumVal, Name) \
Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
return visitKnownRecordImpl(CVR, Record); \
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DIContext.h b/linux-x64/clang/include/llvm/DebugInfo/DIContext.h
index d2a5318..ae78fe9 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DIContext.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DIContext.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
@@ -28,8 +29,13 @@
/// A format-neutral container for source line information.
struct DILineInfo {
+ // DILineInfo contains "<invalid>" for function/filename it cannot fetch.
+ static constexpr const char *const BadString = "<invalid>";
+ // Use "??" instead of "<invalid>" to make our output closer to addr2line.
+ static constexpr const char *const Addr2LineBadString = "??";
std::string FileName;
std::string FunctionName;
+ std::string StartFileName;
Optional<StringRef> Source;
uint32_t Line = 0;
uint32_t Column = 0;
@@ -38,12 +44,15 @@
// DWARF-specific.
uint32_t Discriminator = 0;
- DILineInfo() : FileName("<invalid>"), FunctionName("<invalid>") {}
+ DILineInfo()
+ : FileName(BadString), FunctionName(BadString), StartFileName(BadString) {
+ }
bool operator==(const DILineInfo &RHS) const {
return Line == RHS.Line && Column == RHS.Column &&
FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
- StartLine == RHS.StartLine && Discriminator == RHS.Discriminator;
+ StartFileName == RHS.StartFileName && StartLine == RHS.StartLine &&
+ Discriminator == RHS.Discriminator;
}
bool operator!=(const DILineInfo &RHS) const {
@@ -51,22 +60,24 @@
}
bool operator<(const DILineInfo &RHS) const {
- return std::tie(FileName, FunctionName, Line, Column, StartLine,
- Discriminator) <
- std::tie(RHS.FileName, RHS.FunctionName, RHS.Line, RHS.Column,
- RHS.StartLine, RHS.Discriminator);
+ return std::tie(FileName, FunctionName, StartFileName, Line, Column,
+ StartLine, Discriminator) <
+ std::tie(RHS.FileName, RHS.FunctionName, RHS.StartFileName, RHS.Line,
+ RHS.Column, RHS.StartLine, RHS.Discriminator);
}
explicit operator bool() const { return *this != DILineInfo(); }
void dump(raw_ostream &OS) {
OS << "Line info: ";
- if (FileName != "<invalid>")
+ if (FileName != BadString)
OS << "file '" << FileName << "', ";
- if (FunctionName != "<invalid>")
+ if (FunctionName != BadString)
OS << "function '" << FunctionName << "', ";
OS << "line " << Line << ", ";
OS << "column " << Column << ", ";
+ if (StartFileName != BadString)
+ OS << "start file '" << StartFileName << "', ";
OS << "start line " << StartLine << '\n';
}
};
@@ -109,7 +120,7 @@
uint64_t Start = 0;
uint64_t Size = 0;
- DIGlobal() : Name("<invalid>") {}
+ DIGlobal() : Name(DILineInfo::BadString) {}
};
struct DILocal {
@@ -129,20 +140,29 @@
/// Controls which fields of DILineInfo container should be filled
/// with data.
struct DILineInfoSpecifier {
- enum class FileLineInfoKind { None, Default, AbsoluteFilePath };
+ enum class FileLineInfoKind {
+ None,
+ // RawValue is whatever the compiler stored in the filename table. Could be
+ // a full path, could be something else.
+ RawValue,
+ BaseNameOnly,
+ // Relative to the compilation directory.
+ RelativeFilePath,
+ AbsoluteFilePath
+ };
using FunctionNameKind = DINameKind;
FileLineInfoKind FLIKind;
FunctionNameKind FNKind;
- DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::Default,
+ DILineInfoSpecifier(FileLineInfoKind FLIKind = FileLineInfoKind::RawValue,
FunctionNameKind FNKind = FunctionNameKind::None)
: FLIKind(FLIKind), FNKind(FNKind) {}
};
/// This is just a helper to programmatically construct DIDumpType.
enum DIDumpTypeCounter {
-#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
+#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
DIDT_ID_##ENUM_NAME,
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
@@ -155,7 +175,7 @@
enum DIDumpType : unsigned {
DIDT_Null,
DIDT_All = ~0U,
-#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
+#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME, OPTION) \
DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
#include "llvm/BinaryFormat/Dwarf.def"
#undef HANDLE_DWARF_SECTION
@@ -195,6 +215,10 @@
Opts.ParentRecurseDepth = 0;
return Opts;
}
+
+ std::function<void(Error)> RecoverableErrorHandler =
+ WithColor::defaultErrorHandler;
+ std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
};
class DIContext {
@@ -289,7 +313,7 @@
LoadedObjectInfoHelper(Ts &&... Args) : Base(std::forward<Ts>(Args)...) {}
std::unique_ptr<llvm::LoadedObjectInfo> clone() const override {
- return llvm::make_unique<Derived>(static_cast<const Derived &>(*this));
+ return std::make_unique<Derived>(static_cast<const Derived &>(*this));
}
};
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
index ccf2891..39ae53c 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
@@ -130,11 +130,11 @@
/// \param Attr DWARF attribute to search for.
/// \param U the DWARFUnit the contains the DIE.
/// \returns Optional DWARF form value if the attribute was extracted.
- Optional<DWARFFormValue> getAttributeValue(const uint32_t DIEOffset,
+ Optional<DWARFFormValue> getAttributeValue(const uint64_t DIEOffset,
const dwarf::Attribute Attr,
const DWARFUnit &U) const;
- bool extract(DataExtractor Data, uint32_t* OffsetPtr);
+ bool extract(DataExtractor Data, uint64_t* OffsetPtr);
void dump(raw_ostream &OS) const;
// Return an optional byte size of all attribute data in this abbreviation
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index 3033757..961a8d8 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -96,7 +96,7 @@
using AtomType = uint16_t;
using Form = dwarf::Form;
- uint32_t DIEOffsetBase;
+ uint64_t DIEOffsetBase;
SmallVector<std::pair<AtomType, Form>, 3> Atoms;
Optional<uint64_t> extractOffset(Optional<DWARFFormValue> Value) const;
@@ -109,7 +109,7 @@
/// Returns true if we should continue scanning for entries or false if we've
/// reached the last (sentinel) entry of encountered a parsing error.
bool dumpName(ScopedPrinter &W, SmallVectorImpl<DWARFFormValue> &AtomForms,
- uint32_t *DataOffset) const;
+ uint64_t *DataOffset) const;
public:
/// Apple-specific implementation of an Accelerator Entry.
@@ -119,7 +119,7 @@
Entry(const HeaderData &Data);
Entry() = default;
- void extract(const AppleAcceleratorTable &AccelTable, uint32_t *Offset);
+ void extract(const AppleAcceleratorTable &AccelTable, uint64_t *Offset);
public:
Optional<uint64_t> getCUOffset() const override;
@@ -143,7 +143,7 @@
class ValueIterator : public std::iterator<std::input_iterator_tag, Entry> {
const AppleAcceleratorTable *AccelTable = nullptr;
Entry Current; ///< The current entry.
- unsigned DataOffset = 0; ///< Offset into the section.
+ uint64_t DataOffset = 0; ///< Offset into the section.
unsigned Data = 0; ///< Current data entry.
unsigned NumData = 0; ///< Number of data entries.
@@ -151,7 +151,7 @@
void Next();
public:
/// Construct a new iterator for the entries at \p DataOffset.
- ValueIterator(const AppleAcceleratorTable &AccelTable, unsigned DataOffset);
+ ValueIterator(const AppleAcceleratorTable &AccelTable, uint64_t DataOffset);
/// End marker.
ValueIterator() = default;
@@ -193,7 +193,7 @@
/// DieOffset is the offset into the .debug_info section for the DIE
/// related to the input hash data offset.
/// DieTag is the tag of the DIE
- std::pair<uint32_t, dwarf::Tag> readAtoms(uint32_t &HashDataOffset);
+ std::pair<uint64_t, dwarf::Tag> readAtoms(uint64_t *HashDataOffset);
void dump(raw_ostream &OS) const override;
/// Look up all entries in the accelerator table matching \c Key.
@@ -222,11 +222,16 @@
/// referenced by the name table and interpreted with the help of the
/// abbreviation table.
class DWARFDebugNames : public DWARFAcceleratorTable {
- /// The fixed-size part of a DWARF v5 Name Index header
- struct HeaderPOD {
- uint32_t UnitLength;
+public:
+ class NameIndex;
+ class NameIterator;
+ class ValueIterator;
+
+ /// DWARF v5 Name Index header.
+ struct Header {
+ uint64_t UnitLength;
+ dwarf::DwarfFormat Format;
uint16_t Version;
- uint16_t Padding;
uint32_t CompUnitCount;
uint32_t LocalTypeUnitCount;
uint32_t ForeignTypeUnitCount;
@@ -234,18 +239,9 @@
uint32_t NameCount;
uint32_t AbbrevTableSize;
uint32_t AugmentationStringSize;
- };
-
-public:
- class NameIndex;
- class NameIterator;
- class ValueIterator;
-
- /// DWARF v5 Name Index header.
- struct Header : public HeaderPOD {
SmallString<8> AugmentationString;
- Error extract(const DWARFDataExtractor &AS, uint32_t *Offset);
+ Error extract(const DWARFDataExtractor &AS, uint64_t *Offset);
void dump(ScopedPrinter &W) const;
};
@@ -354,12 +350,12 @@
DataExtractor StrData;
uint32_t Index;
- uint32_t StringOffset;
- uint32_t EntryOffset;
+ uint64_t StringOffset;
+ uint64_t EntryOffset;
public:
NameTableEntry(const DataExtractor &StrData, uint32_t Index,
- uint32_t StringOffset, uint32_t EntryOffset)
+ uint64_t StringOffset, uint64_t EntryOffset)
: StrData(StrData), Index(Index), StringOffset(StringOffset),
EntryOffset(EntryOffset) {}
@@ -367,17 +363,17 @@
uint32_t getIndex() const { return Index; }
/// Returns the offset of the name of the described entities.
- uint32_t getStringOffset() const { return StringOffset; }
+ uint64_t getStringOffset() const { return StringOffset; }
/// Return the string referenced by this name table entry or nullptr if the
/// string offset is not valid.
const char *getString() const {
- uint32_t Off = StringOffset;
+ uint64_t Off = StringOffset;
return StrData.getCStr(&Off);
}
/// Returns the offset of the first Entry in the list.
- uint32_t getEntryOffset() const { return EntryOffset; }
+ uint64_t getEntryOffset() const { return EntryOffset; }
};
/// Represents a single accelerator table within the DWARF v5 .debug_names
@@ -389,40 +385,40 @@
// Base of the whole unit and of various important tables, as offsets from
// the start of the section.
- uint32_t Base;
- uint32_t CUsBase;
- uint32_t BucketsBase;
- uint32_t HashesBase;
- uint32_t StringOffsetsBase;
- uint32_t EntryOffsetsBase;
- uint32_t EntriesBase;
+ uint64_t Base;
+ uint64_t CUsBase;
+ uint64_t BucketsBase;
+ uint64_t HashesBase;
+ uint64_t StringOffsetsBase;
+ uint64_t EntryOffsetsBase;
+ uint64_t EntriesBase;
void dumpCUs(ScopedPrinter &W) const;
void dumpLocalTUs(ScopedPrinter &W) const;
void dumpForeignTUs(ScopedPrinter &W) const;
void dumpAbbreviations(ScopedPrinter &W) const;
- bool dumpEntry(ScopedPrinter &W, uint32_t *Offset) const;
+ bool dumpEntry(ScopedPrinter &W, uint64_t *Offset) const;
void dumpName(ScopedPrinter &W, const NameTableEntry &NTE,
Optional<uint32_t> Hash) const;
void dumpBucket(ScopedPrinter &W, uint32_t Bucket) const;
- Expected<AttributeEncoding> extractAttributeEncoding(uint32_t *Offset);
+ Expected<AttributeEncoding> extractAttributeEncoding(uint64_t *Offset);
Expected<std::vector<AttributeEncoding>>
- extractAttributeEncodings(uint32_t *Offset);
+ extractAttributeEncodings(uint64_t *Offset);
- Expected<Abbrev> extractAbbrev(uint32_t *Offset);
+ Expected<Abbrev> extractAbbrev(uint64_t *Offset);
public:
- NameIndex(const DWARFDebugNames &Section, uint32_t Base)
+ NameIndex(const DWARFDebugNames &Section, uint64_t Base)
: Section(Section), Base(Base) {}
/// Reads offset of compilation unit CU. CU is 0-based.
- uint32_t getCUOffset(uint32_t CU) const;
+ uint64_t getCUOffset(uint32_t CU) const;
uint32_t getCUCount() const { return Hdr.CompUnitCount; }
/// Reads offset of local type unit TU, TU is 0-based.
- uint32_t getLocalTUOffset(uint32_t TU) const;
+ uint64_t getLocalTUOffset(uint32_t TU) const;
uint32_t getLocalTUCount() const { return Hdr.LocalTypeUnitCount; }
/// Reads signature of foreign type unit TU. TU is 0-based.
@@ -451,7 +447,7 @@
return Abbrevs;
}
- Expected<Entry> getEntry(uint32_t *Offset) const;
+ Expected<Entry> getEntry(uint64_t *Offset) const;
/// Look up all entries in this Name Index matching \c Key.
iterator_range<ValueIterator> equal_range(StringRef Key) const;
@@ -460,8 +456,11 @@
NameIterator end() const { return NameIterator(this, getNameCount() + 1); }
Error extract();
- uint32_t getUnitOffset() const { return Base; }
- uint32_t getNextUnitOffset() const { return Base + 4 + Hdr.UnitLength; }
+ uint64_t getUnitOffset() const { return Base; }
+ uint64_t getNextUnitOffset() const {
+ return Base + dwarf::getUnitLengthFieldByteSize(Hdr.Format) +
+ Hdr.UnitLength;
+ }
void dump(ScopedPrinter &W) const;
friend class DWARFDebugNames;
@@ -479,12 +478,12 @@
bool IsLocal;
Optional<Entry> CurrentEntry;
- unsigned DataOffset = 0; ///< Offset into the section.
+ uint64_t DataOffset = 0; ///< Offset into the section.
std::string Key; ///< The Key we are searching for.
Optional<uint32_t> Hash; ///< Hash of Key, if it has been computed.
bool getEntryAtCurrentOffset();
- Optional<uint32_t> findEntryOffsetInCurrentIndex();
+ Optional<uint64_t> findEntryOffsetInCurrentIndex();
bool findInCurrentIndex();
void searchFromStartOfCurrentIndex();
void next();
@@ -572,7 +571,7 @@
private:
SmallVector<NameIndex, 0> NameIndices;
- DenseMap<uint32_t, const NameIndex *> CUToNameIndex;
+ DenseMap<uint64_t, const NameIndex *> CUToNameIndex;
public:
DWARFDebugNames(const DWARFDataExtractor &AccelSection,
@@ -591,7 +590,7 @@
/// Return the Name Index covering the compile unit at CUOffset, or nullptr if
/// there is no Name Index covering that unit.
- const NameIndex *getCUNameIndex(uint32_t CUOffset);
+ const NameIndex *getCUNameIndex(uint64_t CUOffset);
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
index 2d5f9f3..154f789 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAddressRange.h
@@ -17,6 +17,7 @@
namespace llvm {
class raw_ostream;
+class DWARFObject;
struct DWARFAddressRange {
uint64_t LowPC;
@@ -26,7 +27,9 @@
DWARFAddressRange() = default;
/// Used for unit testing.
- DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0)
+ DWARFAddressRange(
+ uint64_t LowPC, uint64_t HighPC,
+ uint64_t SectionIndex = object::SectionedAddress::UndefSection)
: LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {}
/// Returns true if LowPC is smaller or equal to HighPC. This accounts for
@@ -42,15 +45,38 @@
return LowPC < RHS.HighPC && RHS.LowPC < HighPC;
}
- void dump(raw_ostream &OS, uint32_t AddressSize,
- DIDumpOptions DumpOpts = {}) const;
+ /// Union two address ranges if they intersect.
+ ///
+ /// This function will union two address ranges if they intersect by
+ /// modifying this range to be the union of both ranges. If the two ranges
+ /// don't intersect this range will be left alone.
+ ///
+ /// \param RHS Another address range to combine with.
+ ///
+ /// \returns false if the ranges don't intersect, true if they do and the
+ /// ranges were combined.
+ bool merge(const DWARFAddressRange &RHS) {
+ if (!intersects(RHS))
+ return false;
+ LowPC = std::min<uint64_t>(LowPC, RHS.LowPC);
+ HighPC = std::max<uint64_t>(HighPC, RHS.HighPC);
+ return true;
+ }
+
+ void dump(raw_ostream &OS, uint32_t AddressSize, DIDumpOptions DumpOpts = {},
+ const DWARFObject *Obj = nullptr) const;
};
-static inline bool operator<(const DWARFAddressRange &LHS,
- const DWARFAddressRange &RHS) {
+inline bool operator<(const DWARFAddressRange &LHS,
+ const DWARFAddressRange &RHS) {
return std::tie(LHS.LowPC, LHS.HighPC) < std::tie(RHS.LowPC, RHS.HighPC);
}
+inline bool operator==(const DWARFAddressRange &LHS,
+ const DWARFAddressRange &RHS) {
+ return std::tie(LHS.LowPC, LHS.HighPC) == std::tie(RHS.LowPC, RHS.HighPC);
+}
+
raw_ostream &operator<<(raw_ostream &OS, const DWARFAddressRange &R);
/// DWARFAddressRangesVector - represents a set of absolute address ranges.
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAttribute.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
index 96e622c..dfc7783 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFAttribute.h
@@ -23,17 +23,14 @@
/// attributes in a DWARFDie.
struct DWARFAttribute {
/// The debug info/types offset for this attribute.
- uint32_t Offset = 0;
+ uint64_t Offset = 0;
/// The debug info/types section byte size of the data for this attribute.
uint32_t ByteSize = 0;
/// The attribute enumeration of this attribute.
- dwarf::Attribute Attr;
+ dwarf::Attribute Attr = dwarf::Attribute(0);
/// The form and value for this attribute.
DWARFFormValue Value;
- DWARFAttribute(uint32_t O, dwarf::Attribute A = dwarf::Attribute(0),
- dwarf::Form F = dwarf::Form(0)) : Attr(A), Value(F) {}
-
bool isValid() const {
return Offset != 0 && Attr != dwarf::Attribute(0);
}
@@ -45,13 +42,6 @@
/// Identifies DWARF attributes that may contain a reference to a
/// DWARF expression.
static bool mayHaveLocationDescription(dwarf::Attribute Attr);
-
- void clear() {
- Offset = 0;
- ByteSize = 0;
- Attr = dwarf::Attribute(0);
- Value = DWARFFormValue();
- }
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFContext.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFContext.h
index 23cf21c..7d88e14 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -47,11 +47,6 @@
class MemoryBuffer;
class raw_ostream;
-/// Used as a return value for a error callback passed to DWARF context.
-/// Callback should return Halt if client application wants to stop
-/// object parsing, or should return Continue otherwise.
-enum class ErrorPolicy { Halt, Continue };
-
/// DWARFContext
/// This data structure is the top level entity that deals with dwarf debug
/// information parsing. The actual data is supplied through DWARFObj.
@@ -67,6 +62,7 @@
std::unique_ptr<DWARFDebugFrame> DebugFrame;
std::unique_ptr<DWARFDebugFrame> EHFrame;
std::unique_ptr<DWARFDebugMacro> Macro;
+ std::unique_ptr<DWARFDebugMacro> Macinfo;
std::unique_ptr<DWARFDebugNames> Names;
std::unique_ptr<AppleAcceleratorTable> AppleNames;
std::unique_ptr<AppleAcceleratorTable> AppleTypes;
@@ -75,7 +71,8 @@
DWARFUnitVector DWOUnits;
std::unique_ptr<DWARFDebugAbbrev> AbbrevDWO;
- std::unique_ptr<DWARFDebugLoclists> LocDWO;
+ std::unique_ptr<DWARFDebugMacro> MacinfoDWO;
+ std::unique_ptr<DWARFDebugMacro> MacroDWO;
/// The maximum DWARF version of all units.
unsigned MaxVersion = 0;
@@ -91,6 +88,10 @@
std::unique_ptr<MCRegisterInfo> RegInfo;
+ std::function<void(Error)> RecoverableErrorHandler =
+ WithColor::defaultErrorHandler;
+ std::function<void(Error)> WarningHandler = WithColor::defaultWarningHandler;
+
/// Read compile units from the debug_info section (if necessary)
/// and type units from the debug_types sections (if necessary)
/// and store them in NormalUnits.
@@ -105,9 +106,22 @@
std::unique_ptr<const DWARFObject> DObj;
+ /// Helper enum to distinguish between macro[.dwo] and macinfo[.dwo]
+ /// section.
+ enum MacroSecType {
+ MacinfoSection,
+ MacinfoDwoSection,
+ MacroSection,
+ MacroDwoSection
+ };
+
public:
DWARFContext(std::unique_ptr<const DWARFObject> DObj,
- std::string DWPName = "");
+ std::string DWPName = "",
+ std::function<void(Error)> RecoverableErrorHandler =
+ WithColor::defaultErrorHandler,
+ std::function<void(Error)> WarningHandler =
+ WithColor::defaultWarningHandler);
~DWARFContext();
DWARFContext(DWARFContext &) = delete;
@@ -132,6 +146,7 @@
bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
using unit_iterator_range = DWARFUnitVector::iterator_range;
+ using compile_unit_range = DWARFUnitVector::compile_unit_range;
/// Get units from .debug_info in this context.
unit_iterator_range info_section_units() {
@@ -149,10 +164,12 @@
}
/// Get compile units in this context.
- unit_iterator_range compile_units() { return info_section_units(); }
+ compile_unit_range compile_units() {
+ return make_filter_range(info_section_units(), isCompileUnit);
+ }
- /// Get type units in this context.
- unit_iterator_range type_units() { return types_section_units(); }
+ // If you want type_units(), it'll need to be a concat iterator of a filter of
+ // TUs in info_section + all the (all type) units in types_section
/// Get all normal compile/type units in this context.
unit_iterator_range normal_units() {
@@ -175,10 +192,13 @@
}
/// Get compile units in the DWO context.
- unit_iterator_range dwo_compile_units() { return dwo_info_section_units(); }
+ compile_unit_range dwo_compile_units() {
+ return make_filter_range(dwo_info_section_units(), isCompileUnit);
+ }
- /// Get type units in the DWO context.
- unit_iterator_range dwo_type_units() { return dwo_types_section_units(); }
+ // If you want dwo_type_units(), it'll need to be a concat iterator of a
+ // filter of TUs in dwo_info_section + all the (all type) units in
+ // dwo_types_section.
/// Get all units in the DWO context.
unit_iterator_range dwo_units() {
@@ -225,10 +245,10 @@
DWARFCompileUnit *getDWOCompileUnitForHash(uint64_t Hash);
/// Return the compile unit that includes an offset (relative to .debug_info).
- DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
+ DWARFCompileUnit *getCompileUnitForOffset(uint64_t Offset);
/// Get a DIE given an exact offset.
- DWARFDie getDIEForOffset(uint32_t Offset);
+ DWARFDie getDIEForOffset(uint64_t Offset);
unsigned getMaxVersion() {
// Ensure info units have been parsed to discover MaxVersion
@@ -260,21 +280,27 @@
/// Get a pointer to the parsed dwo abbreviations object.
const DWARFDebugAbbrev *getDebugAbbrevDWO();
- /// Get a pointer to the parsed DebugLoc object.
- const DWARFDebugLoclists *getDebugLocDWO();
-
/// Get a pointer to the parsed DebugAranges object.
const DWARFDebugAranges *getDebugAranges();
/// Get a pointer to the parsed frame information object.
- const DWARFDebugFrame *getDebugFrame();
+ Expected<const DWARFDebugFrame *> getDebugFrame();
/// Get a pointer to the parsed eh frame information object.
- const DWARFDebugFrame *getEHFrame();
+ Expected<const DWARFDebugFrame *> getEHFrame();
- /// Get a pointer to the parsed DebugMacro object.
+ /// Get a pointer to the parsed DebugMacinfo information object.
+ const DWARFDebugMacro *getDebugMacinfo();
+
+ /// Get a pointer to the parsed DebugMacinfoDWO information object.
+ const DWARFDebugMacro *getDebugMacinfoDWO();
+
+ /// Get a pointer to the parsed DebugMacro information object.
const DWARFDebugMacro *getDebugMacro();
+ /// Get a pointer to the parsed DebugMacroDWO information object.
+ const DWARFDebugMacro *getDebugMacroDWO();
+
/// Get a reference to the parsed accelerator table object.
const DWARFDebugNames &getDebugNames();
@@ -295,16 +321,19 @@
const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *U);
/// Get a pointer to a parsed line table corresponding to a compile unit.
- /// Report any recoverable parsing problems using the callback.
+ /// Report any recoverable parsing problems using the handler.
Expected<const DWARFDebugLine::LineTable *>
getLineTableForUnit(DWARFUnit *U,
- std::function<void(Error)> RecoverableErrorCallback);
+ function_ref<void(Error)> RecoverableErrorHandler);
DataExtractor getStringExtractor() const {
- return DataExtractor(DObj->getStringSection(), false, 0);
+ return DataExtractor(DObj->getStrSection(), false, 0);
+ }
+ DataExtractor getStringDWOExtractor() const {
+ return DataExtractor(DObj->getStrDWOSection(), false, 0);
}
DataExtractor getLineStringExtractor() const {
- return DataExtractor(DObj->getLineStringSection(), false, 0);
+ return DataExtractor(DObj->getLineStrSection(), false, 0);
}
/// Wraps the returned DIEs for a given address.
@@ -339,21 +368,35 @@
return version == 2 || version == 3 || version == 4 || version == 5;
}
+ static bool isAddressSizeSupported(unsigned AddressSize) {
+ return AddressSize == 2 || AddressSize == 4 || AddressSize == 8;
+ }
+
std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
const MCRegisterInfo *getRegisterInfo() const { return RegInfo.get(); }
- /// Function used to handle default error reporting policy. Prints a error
- /// message and returns Continue, so DWARF context ignores the error.
- static ErrorPolicy defaultErrorHandler(Error E);
+ function_ref<void(Error)> getRecoverableErrorHandler() {
+ return RecoverableErrorHandler;
+ }
+
+ function_ref<void(Error)> getWarningHandler() { return WarningHandler; }
+
static std::unique_ptr<DWARFContext>
create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
- function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler,
- std::string DWPName = "");
+ std::string DWPName = "",
+ std::function<void(Error)> RecoverableErrorHandler =
+ WithColor::defaultErrorHandler,
+ std::function<void(Error)> WarningHandler =
+ WithColor::defaultWarningHandler);
static std::unique_ptr<DWARFContext>
create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
- uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost);
+ uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost,
+ std::function<void(Error)> RecoverableErrorHandler =
+ WithColor::defaultErrorHandler,
+ std::function<void(Error)> WarningHandler =
+ WithColor::defaultWarningHandler);
/// Loads register info for the architecture of the provided object file.
/// Improves readability of dumped DWARF expressions. Requires the caller to
@@ -364,19 +407,21 @@
/// TODO: refactor compile_units() to make this const.
uint8_t getCUAddrSize();
- /// Dump Error as warning message to stderr.
- static void dumpWarning(Error Warning);
-
Triple::ArchType getArch() const {
return getDWARFObj().getFile()->getArch();
}
-private:
/// Return the compile unit which contains instruction with provided
/// address.
/// TODO: change input parameter from "uint64_t Address"
/// into "SectionedAddress Address"
DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
+
+private:
+ /// Parse a macro[.dwo] or macinfo[.dwo] section.
+ std::unique_ptr<DWARFDebugMacro>
+ parseMacroOrMacinfo(MacroSecType SectionType);
+
void addLocalsForDie(DWARFCompileUnit *CU, DWARFDie Subprogram, DWARFDie Die,
std::vector<DILocal> &Result);
};
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
index 7c2a159..34329ec 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
@@ -9,6 +9,7 @@
#ifndef LLVM_DEBUGINFO_DWARFDATAEXTRACTOR_H
#define LLVM_DEBUGINFO_DWARFDATAEXTRACTOR_H
+#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/Support/DataExtractor.h"
@@ -32,26 +33,56 @@
/// Constructor for cases when there are no relocations.
DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
: DataExtractor(Data, IsLittleEndian, AddressSize) {}
+ DWARFDataExtractor(ArrayRef<uint8_t> Data, bool IsLittleEndian,
+ uint8_t AddressSize)
+ : DataExtractor(
+ StringRef(reinterpret_cast<const char *>(Data.data()), Data.size()),
+ IsLittleEndian, AddressSize) {}
+
+ /// Truncating constructor
+ DWARFDataExtractor(const DWARFDataExtractor &Other, size_t Length)
+ : DataExtractor(Other.getData().substr(0, Length), Other.isLittleEndian(),
+ Other.getAddressSize()),
+ Obj(Other.Obj), Section(Other.Section) {}
+
+ /// Extracts the DWARF "initial length" field, which can either be a 32-bit
+ /// value smaller than 0xfffffff0, or the value 0xffffffff followed by a
+ /// 64-bit length. Returns the actual length, and the DWARF format which is
+ /// encoded in the field. In case of errors, it returns {0, DWARF32} and
+ /// leaves the offset unchanged.
+ std::pair<uint64_t, dwarf::DwarfFormat>
+ getInitialLength(uint64_t *Off, Error *Err = nullptr) const;
+
+ std::pair<uint64_t, dwarf::DwarfFormat> getInitialLength(Cursor &C) const {
+ return getInitialLength(&getOffset(C), &getError(C));
+ }
/// Extracts a value and applies a relocation to the result if
/// one exists for the given offset.
- uint64_t getRelocatedValue(uint32_t Size, uint32_t *Off,
- uint64_t *SectionIndex = nullptr) const;
+ uint64_t getRelocatedValue(uint32_t Size, uint64_t *Off,
+ uint64_t *SectionIndex = nullptr,
+ Error *Err = nullptr) const;
+ uint64_t getRelocatedValue(Cursor &C, uint32_t Size,
+ uint64_t *SectionIndex = nullptr) const {
+ return getRelocatedValue(Size, &getOffset(C), SectionIndex, &getError(C));
+ }
/// Extracts an address-sized value and applies a relocation to the result if
/// one exists for the given offset.
- uint64_t getRelocatedAddress(uint32_t *Off, uint64_t *SecIx = nullptr) const {
+ uint64_t getRelocatedAddress(uint64_t *Off, uint64_t *SecIx = nullptr) const {
return getRelocatedValue(getAddressSize(), Off, SecIx);
}
+ uint64_t getRelocatedAddress(Cursor &C, uint64_t *SecIx = nullptr) const {
+ return getRelocatedValue(getAddressSize(), &getOffset(C), SecIx,
+ &getError(C));
+ }
/// Extracts a DWARF-encoded pointer in \p Offset using \p Encoding.
/// There is a DWARF encoding that uses a PC-relative adjustment.
/// For these values, \p AbsPosOffset is used to fix them, which should
/// reflect the absolute address of this pointer.
- Optional<uint64_t> getEncodedPointer(uint32_t *Offset, uint8_t Encoding,
+ Optional<uint64_t> getEncodedPointer(uint64_t *Offset, uint8_t Encoding,
uint64_t AbsPosOffset = 0) const;
-
- size_t size() const { return Section == nullptr ? 0 : Section->Data.size(); }
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
index 28fd848..1398e16 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
@@ -20,7 +20,7 @@
class raw_ostream;
class DWARFAbbreviationDeclarationSet {
- uint32_t Offset;
+ uint64_t Offset;
/// Code of the first abbreviation, if all abbreviations in the set have
/// consecutive codes. UINT32_MAX otherwise.
uint32_t FirstAbbrCode;
@@ -32,9 +32,9 @@
public:
DWARFAbbreviationDeclarationSet();
- uint32_t getOffset() const { return Offset; }
+ uint64_t getOffset() const { return Offset; }
void dump(raw_ostream &OS) const;
- bool extract(DataExtractor Data, uint32_t *OffsetPtr);
+ bool extract(DataExtractor Data, uint64_t *OffsetPtr);
const DWARFAbbreviationDeclaration *
getAbbreviationDeclaration(uint32_t AbbrCode) const;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h
index a98bf28..69e6786 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAddr.h
@@ -27,69 +27,71 @@
/// The table consists of a header followed by an array of address values from
/// .debug_addr section.
class DWARFDebugAddrTable {
-public:
- struct Header {
- /// The total length of the entries for this table, not including the length
- /// field itself.
- uint32_t Length = 0;
- /// The DWARF version number.
- uint16_t Version = 5;
- /// The size in bytes of an address on the target architecture. For
- /// segmented addressing, this is the size of the offset portion of the
- /// address.
- uint8_t AddrSize;
- /// The size in bytes of a segment selector on the target architecture.
- /// If the target system uses a flat address space, this value is 0.
- uint8_t SegSize = 0;
- };
-
-private:
dwarf::DwarfFormat Format;
- uint32_t HeaderOffset;
- Header HeaderData;
- uint32_t DataSize = 0;
+ uint64_t Offset;
+ /// The total length of the entries for this table, not including the length
+ /// field itself.
+ uint64_t Length = 0;
+ /// The DWARF version number.
+ uint16_t Version;
+ /// The size in bytes of an address on the target architecture. For
+ /// segmented addressing, this is the size of the offset portion of the
+ /// address.
+ uint8_t AddrSize;
+ /// The size in bytes of a segment selector on the target architecture.
+ /// If the target system uses a flat address space, this value is 0.
+ uint8_t SegSize;
std::vector<uint64_t> Addrs;
-public:
- void clear();
+ /// Invalidate Length field to stop further processing.
+ void invalidateLength() { Length = 0; }
- /// Extract an entire table, including all addresses.
- Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr,
- uint16_t Version, uint8_t AddrSize,
+ Error extractAddresses(const DWARFDataExtractor &Data, uint64_t *OffsetPtr,
+ uint64_t EndOffset);
+
+public:
+
+ /// Extract the entire table, including all addresses.
+ Error extract(const DWARFDataExtractor &Data, uint64_t *OffsetPtr,
+ uint16_t CUVersion, uint8_t CUAddrSize,
std::function<void(Error)> WarnCallback);
- uint32_t getHeaderOffset() const { return HeaderOffset; }
- uint8_t getAddrSize() const { return HeaderData.AddrSize; }
+ /// Extract a DWARFv5 address table.
+ Error extractV5(const DWARFDataExtractor &Data, uint64_t *OffsetPtr,
+ uint8_t CUAddrSize, std::function<void(Error)> WarnCallback);
+
+ /// Extract a pre-DWARFv5 address table. Such tables do not have a header
+ /// and consist only of a series of addresses.
+ /// See https://gcc.gnu.org/wiki/DebugFission for details.
+ Error extractPreStandard(const DWARFDataExtractor &Data, uint64_t *OffsetPtr,
+ uint16_t CUVersion, uint8_t CUAddrSize);
+
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
/// Return the address based on a given index.
Expected<uint64_t> getAddrEntry(uint32_t Index) const;
- /// Return the size of the table header including the length
- /// but not including the addresses.
- uint8_t getHeaderSize() const {
- switch (Format) {
- case dwarf::DwarfFormat::DWARF32:
- return 8; // 4 + 2 + 1 + 1
- case dwarf::DwarfFormat::DWARF64:
- return 16; // 12 + 2 + 1 + 1
- }
- llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64)");
- }
+ /// Return the full length of this table, including the length field.
+ /// Return None if the length cannot be identified reliably.
+ Optional<uint64_t> getFullLength() const;
- /// Returns the length of this table, including the length field, or 0 if the
- /// length has not been determined (e.g. because the table has not yet been
- /// parsed, or there was a problem in parsing).
- uint32_t getLength() const;
+ /// Return the DWARF format of this table.
+ dwarf::DwarfFormat getFormat() const { return Format; }
- /// Verify that the given length is valid for this table.
- bool hasValidLength() const { return getLength() != 0; }
+ /// Return the length of this table.
+ uint64_t getLength() const { return Length; }
- /// Invalidate Length field to stop further processing.
- void invalidateLength() { HeaderData.Length = 0; }
+ /// Return the version of this table.
+ uint16_t getVersion() const { return Version; }
- /// Returns the length of the array of addresses.
- uint32_t getDataSize() const;
+ /// Return the address size of this table.
+ uint8_t getAddressSize() const { return AddrSize; }
+
+ /// Return the segment selector size of this table.
+ uint8_t getSegmentSelectorSize() const { return SegSize; }
+
+ /// Return the parsed addresses of this table.
+ ArrayRef<uint64_t> getAddressEntries() const { return Addrs; }
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
index 5b6c578..3d5852e 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h
@@ -10,7 +10,8 @@
#define LLVM_DEBUGINFO_DWARFDEBUGARANGESET_H
#include "llvm/ADT/iterator_range.h"
-#include "llvm/Support/DataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/Support/Error.h"
#include <cstdint>
#include <vector>
@@ -23,10 +24,12 @@
struct Header {
/// The total length of the entries for that set, not including the length
/// field itself.
- uint32_t Length;
+ uint64_t Length;
+ /// The DWARF format of the set.
+ dwarf::DwarfFormat Format;
/// The offset from the beginning of the .debug_info section of the
/// compilation unit entry referenced by the table.
- uint32_t CuOffset;
+ uint64_t CuOffset;
/// The DWARF version number.
uint16_t Version;
/// The size in bytes of an address on the target architecture. For segmented
@@ -49,7 +52,7 @@
using DescriptorColl = std::vector<Descriptor>;
using desc_iterator_range = iterator_range<DescriptorColl::const_iterator>;
- uint32_t Offset;
+ uint64_t Offset;
Header HeaderData;
DescriptorColl ArangeDescriptors;
@@ -57,10 +60,11 @@
DWARFDebugArangeSet() { clear(); }
void clear();
- bool extract(DataExtractor data, uint32_t *offset_ptr);
+ Error extract(DWARFDataExtractor data, uint64_t *offset_ptr,
+ function_ref<void(Error)> WarningHandler);
void dump(raw_ostream &OS) const;
- uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; }
+ uint64_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; }
const Header &getHeader() const { return HeaderData; }
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
index 03223fb..31a8b46 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugAranges.h
@@ -10,7 +10,7 @@
#define LLVM_DEBUGINFO_DWARFDEBUGARANGES_H
#include "llvm/ADT/DenseSet.h"
-#include "llvm/Support/DataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include <cstdint>
#include <vector>
@@ -21,19 +21,19 @@
class DWARFDebugAranges {
public:
void generate(DWARFContext *CTX);
- uint32_t findAddress(uint64_t Address) const;
+ uint64_t findAddress(uint64_t Address) const;
private:
void clear();
- void extract(DataExtractor DebugArangesData);
+ void extract(DWARFDataExtractor DebugArangesData,
+ function_ref<void(Error)> RecoverableErrorHandler);
/// Call appendRange multiple times and then call construct.
- void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC);
+ void appendRange(uint64_t CUOffset, uint64_t LowPC, uint64_t HighPC);
void construct();
struct Range {
- explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL,
- uint32_t CUOffset = -1U)
+ explicit Range(uint64_t LowPC, uint64_t HighPC, uint64_t CUOffset)
: LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {}
void setHighPC(uint64_t HighPC) {
@@ -54,16 +54,16 @@
}
uint64_t LowPC; /// Start of address range.
- uint32_t Length; /// End of address range (not including this address).
- uint32_t CUOffset; /// Offset of the compile unit or die.
+ uint64_t Length; /// End of address range (not including this address).
+ uint64_t CUOffset; /// Offset of the compile unit or die.
};
struct RangeEndpoint {
uint64_t Address;
- uint32_t CUOffset;
+ uint64_t CUOffset;
bool IsRangeStart;
- RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart)
+ RangeEndpoint(uint64_t Address, uint64_t CUOffset, bool IsRangeStart)
: Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {}
bool operator<(const RangeEndpoint &Other) const {
@@ -76,7 +76,7 @@
std::vector<RangeEndpoint> Endpoints;
RangeColl Aranges;
- DenseSet<uint32_t> ParsedCUOffsets;
+ DenseSet<uint64_t> ParsedCUOffsets;
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index d960f4b..af87811 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -69,10 +69,10 @@
/// starting at *Offset and ending at EndOffset. *Offset is updated
/// to EndOffset upon successful parsing, or indicates the offset
/// where a problem occurred in case an error is returned.
- Error parse(DataExtractor Data, uint32_t *Offset, uint32_t EndOffset);
+ Error parse(DWARFDataExtractor Data, uint64_t *Offset, uint64_t EndOffset);
- void dump(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
- unsigned IndentLevel = 1) const;
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
+ bool IsEH, unsigned IndentLevel = 1) const;
private:
std::vector<Instruction> Instructions;
@@ -121,7 +121,8 @@
static ArrayRef<OperandType[2]> getOperandTypes();
/// Print \p Opcode's operand number \p OperandIdx which has value \p Operand.
- void printOperand(raw_ostream &OS, const MCRegisterInfo *MRI, bool IsEH,
+ void printOperand(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *MRI, bool IsEH,
const Instruction &Instr, unsigned OperandIdx,
uint64_t Operand) const;
};
@@ -132,9 +133,9 @@
public:
enum FrameKind { FK_CIE, FK_FDE };
- FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length, uint64_t CodeAlign,
- int64_t DataAlign, Triple::ArchType Arch)
- : Kind(K), Offset(Offset), Length(Length),
+ FrameEntry(FrameKind K, bool IsDWARF64, uint64_t Offset, uint64_t Length,
+ uint64_t CodeAlign, int64_t DataAlign, Triple::ArchType Arch)
+ : Kind(K), IsDWARF64(IsDWARF64), Offset(Offset), Length(Length),
CFIs(CodeAlign, DataAlign, Arch) {}
virtual ~FrameEntry() {}
@@ -146,12 +147,14 @@
CFIProgram &cfis() { return CFIs; }
/// Dump the instructions in this CFI fragment
- virtual void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
- bool IsEH) const = 0;
+ virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *MRI, bool IsEH) const = 0;
protected:
const FrameKind Kind;
+ const bool IsDWARF64;
+
/// Offset of this entry in the section.
const uint64_t Offset;
@@ -166,14 +169,14 @@
public:
// CIEs (and FDEs) are simply container classes, so the only sensible way to
// create them is by providing the full parsed contents in the constructor.
- CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
+ CIE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint8_t Version,
SmallString<8> Augmentation, uint8_t AddressSize,
uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister,
SmallString<8> AugmentationData, uint32_t FDEPointerEncoding,
uint32_t LSDAPointerEncoding, Optional<uint64_t> Personality,
Optional<uint32_t> PersonalityEnc, Triple::ArchType Arch)
- : FrameEntry(FK_CIE, Offset, Length, CodeAlignmentFactor,
+ : FrameEntry(FK_CIE, IsDWARF64, Offset, Length, CodeAlignmentFactor,
DataAlignmentFactor, Arch),
Version(Version), Augmentation(std::move(Augmentation)),
AddressSize(AddressSize), SegmentDescriptorSize(SegmentDescriptorSize),
@@ -199,7 +202,7 @@
uint32_t getLSDAPointerEncoding() const { return LSDAPointerEncoding; }
- void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
bool IsEH) const override;
private:
@@ -223,17 +226,14 @@
/// DWARF Frame Description Entry (FDE)
class FDE : public FrameEntry {
public:
- // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
- // an offset to the CIE (provided by parsing the FDE header). The CIE itself
- // is obtained lazily once it's actually required.
- FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
+ FDE(bool IsDWARF64, uint64_t Offset, uint64_t Length, uint64_t CIEPointer,
uint64_t InitialLocation, uint64_t AddressRange, CIE *Cie,
Optional<uint64_t> LSDAAddress, Triple::ArchType Arch)
- : FrameEntry(FK_FDE, Offset, Length,
+ : FrameEntry(FK_FDE, IsDWARF64, Offset, Length,
Cie ? Cie->getCodeAlignmentFactor() : 0,
Cie ? Cie->getDataAlignmentFactor() : 0,
Arch),
- LinkedCIEOffset(LinkedCIEOffset), InitialLocation(InitialLocation),
+ CIEPointer(CIEPointer), InitialLocation(InitialLocation),
AddressRange(AddressRange), LinkedCIE(Cie), LSDAAddress(LSDAAddress) {}
~FDE() override = default;
@@ -243,14 +243,17 @@
uint64_t getAddressRange() const { return AddressRange; }
Optional<uint64_t> getLSDAAddress() const { return LSDAAddress; }
- void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
bool IsEH) const override;
static bool classof(const FrameEntry *FE) { return FE->getKind() == FK_FDE; }
private:
- /// The following fields are defined in section 6.4.1 of the DWARF standard v3
- const uint64_t LinkedCIEOffset;
+ /// The following fields are defined in section 6.4.1 of the DWARFv3 standard.
+ /// Note that CIE pointers in EH FDEs, unlike DWARF FDEs, contain relative
+ /// offsets to the linked CIEs. See the following link for more info:
+ /// https://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/LSB-Core-generic/ehframechpt.html
+ const uint64_t CIEPointer;
const uint64_t InitialLocation;
const uint64_t AddressRange;
const CIE *LinkedCIE;
@@ -283,12 +286,12 @@
~DWARFDebugFrame();
/// Dump the section data into the given stream.
- void dump(raw_ostream &OS, const MCRegisterInfo *MRI,
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts, const MCRegisterInfo *MRI,
Optional<uint64_t> Offset) const;
/// Parse the section from raw data. \p Data is assumed to contain the whole
/// frame section contents to be parsed.
- void parse(DWARFDataExtractor Data);
+ Error parse(DWARFDataExtractor Data);
/// Return whether the section has any entries.
bool empty() const { return Entries.empty(); }
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
index f50063b..ded9603 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h
@@ -22,7 +22,7 @@
/// DWARFDebugInfoEntry - A DIE with only the minimum required data.
class DWARFDebugInfoEntry {
/// Offset within the .debug_info of the start of this entry.
- uint32_t Offset = 0;
+ uint64_t Offset = 0;
/// The integer depth of this DIE within the compile unit DIEs where the
/// compile/type unit DIE has a depth of zero.
@@ -36,14 +36,14 @@
/// Extracts a debug info entry, which is a child of a given unit,
/// starting at a given offset. If DIE can't be extracted, returns false and
/// doesn't change OffsetPtr.
- bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr);
+ bool extractFast(const DWARFUnit &U, uint64_t *OffsetPtr);
/// High performance extraction should use this call.
- bool extractFast(const DWARFUnit &U, uint32_t *OffsetPtr,
- const DWARFDataExtractor &DebugInfoData, uint32_t UEndOffset,
+ bool extractFast(const DWARFUnit &U, uint64_t *OffsetPtr,
+ const DWARFDataExtractor &DebugInfoData, uint64_t UEndOffset,
uint32_t Depth);
- uint32_t getOffset() const { return Offset; }
+ uint64_t getOffset() const { return Offset; }
uint32_t getDepth() const { return Depth; }
dwarf::Tag getTag() const {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
index 9a3ad2b..bc6c67a 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -18,6 +18,7 @@
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/Support/MD5.h"
+#include "llvm/Support/Path.h"
#include <cstdint>
#include <map>
#include <string>
@@ -107,23 +108,31 @@
bool totalLengthIsValid() const;
/// Length of the prologue in bytes.
- uint32_t getLength() const {
- return PrologueLength + sizeofTotalLength() + sizeof(getVersion()) +
- sizeofPrologueLength();
- }
-
- /// Length of the line table data in bytes (not including the prologue).
- uint32_t getStatementTableLength() const {
- return TotalLength + sizeofTotalLength() - getLength();
- }
+ uint64_t getLength() const;
int32_t getMaxLineIncrementForSpecialOpcode() const {
return LineBase + (int8_t)LineRange - 1;
}
+ /// Get DWARF-version aware access to the file name entry at the provided
+ /// index.
+ const llvm::DWARFDebugLine::FileNameEntry &
+ getFileNameEntry(uint64_t Index) const;
+
+ bool hasFileAtIndex(uint64_t FileIndex) const;
+
+ Optional<uint64_t> getLastValidFileIndex() const;
+
+ bool
+ getFileNameByIndex(uint64_t FileIndex, StringRef CompDir,
+ DILineInfoSpecifier::FileLineInfoKind Kind,
+ std::string &Result,
+ sys::path::Style Style = sys::path::Style::native) const;
+
void clear();
void dump(raw_ostream &OS, DIDumpOptions DumpOptions) const;
- Error parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
+ Error parse(DWARFDataExtractor Data, uint64_t *OffsetPtr,
+ function_ref<void(Error)> RecoverableErrorHandler,
const DWARFContext &Ctx, const DWARFUnit *U = nullptr);
};
@@ -136,7 +145,7 @@
void reset(bool DefaultIsStmt);
void dump(raw_ostream &OS) const;
- static void dumpTableHeader(raw_ostream &OS);
+ static void dumpTableHeader(raw_ostream &OS, unsigned Indent);
static bool orderByAddress(const Row &LHS, const Row &RHS) {
return std::tie(LHS.Address.SectionIndex, LHS.Address.Address) <
@@ -240,16 +249,24 @@
bool lookupAddressRange(object::SectionedAddress Address, uint64_t Size,
std::vector<uint32_t> &Result) const;
- bool hasFileAtIndex(uint64_t FileIndex) const;
+ bool hasFileAtIndex(uint64_t FileIndex) const {
+ return Prologue.hasFileAtIndex(FileIndex);
+ }
+
+ Optional<uint64_t> getLastValidFileIndex() const {
+ return Prologue.getLastValidFileIndex();
+ }
/// Extracts filename by its index in filename table in prologue.
/// In Dwarf 4, the files are 1-indexed and the current compilation file
/// name is not represented in the list. In DWARF v5, the files are
/// 0-indexed and the primary source file has the index 0.
/// Returns true on success.
- bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir,
+ bool getFileNameByIndex(uint64_t FileIndex, StringRef CompDir,
DILineInfoSpecifier::FileLineInfoKind Kind,
- std::string &Result) const;
+ std::string &Result) const {
+ return Prologue.getFileNameByIndex(FileIndex, CompDir, Kind, Result);
+ }
/// Fills the Result argument with the file and line information
/// corresponding to Address. Returns true on success.
@@ -262,16 +279,10 @@
void clear();
/// Parse prologue and all rows.
- Error parse(
- DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
- const DWARFContext &Ctx, const DWARFUnit *U,
- std::function<void(Error)> RecoverableErrorCallback,
- raw_ostream *OS = nullptr);
-
- /// Get DWARF-version aware access to the file name entry at the provided
- /// index.
- const llvm::DWARFDebugLine::FileNameEntry &
- getFileNameEntry(uint64_t Index) const;
+ Error parse(DWARFDataExtractor &DebugLineData, uint64_t *OffsetPtr,
+ const DWARFContext &Ctx, const DWARFUnit *U,
+ function_ref<void(Error)> RecoverableErrorHandler,
+ raw_ostream *OS = nullptr, bool Verbose = false);
using RowVector = std::vector<Row>;
using RowIter = RowVector::const_iterator;
@@ -295,43 +306,44 @@
std::vector<uint32_t> &Result) const;
};
- const LineTable *getLineTable(uint32_t Offset) const;
- Expected<const LineTable *> getOrParseLineTable(
- DWARFDataExtractor &DebugLineData, uint32_t Offset,
- const DWARFContext &Ctx, const DWARFUnit *U,
- std::function<void(Error)> RecoverableErrorCallback);
+ const LineTable *getLineTable(uint64_t Offset) const;
+ Expected<const LineTable *>
+ getOrParseLineTable(DWARFDataExtractor &DebugLineData, uint64_t Offset,
+ const DWARFContext &Ctx, const DWARFUnit *U,
+ function_ref<void(Error)> RecoverableErrorHandler);
/// Helper to allow for parsing of an entire .debug_line section in sequence.
class SectionParser {
public:
- using cu_range = DWARFUnitVector::iterator_range;
- using tu_range = DWARFUnitVector::iterator_range;
using LineToUnitMap = std::map<uint64_t, DWARFUnit *>;
- SectionParser(DWARFDataExtractor &Data, const DWARFContext &C, cu_range CUs,
- tu_range TUs);
+ SectionParser(DWARFDataExtractor &Data, const DWARFContext &C,
+ DWARFUnitVector::iterator_range Units);
/// Get the next line table from the section. Report any issues via the
- /// callbacks.
+ /// handlers.
///
- /// \param RecoverableErrorCallback - any issues that don't prevent further
- /// parsing of the table will be reported through this callback.
- /// \param UnrecoverableErrorCallback - any issues that prevent further
- /// parsing of the table will be reported through this callback.
+ /// \param RecoverableErrorHandler - any issues that don't prevent further
+ /// parsing of the table will be reported through this handler.
+ /// \param UnrecoverableErrorHandler - any issues that prevent further
+ /// parsing of the table will be reported through this handler.
/// \param OS - if not null, the parser will print information about the
/// table as it parses it.
- LineTable
- parseNext(
- function_ref<void(Error)> RecoverableErrorCallback,
- function_ref<void(Error)> UnrecoverableErrorCallback,
- raw_ostream *OS = nullptr);
+ /// \param Verbose - if true, the parser will print verbose information when
+ /// printing to the output.
+ LineTable parseNext(function_ref<void(Error)> RecoverableErrorHandler,
+ function_ref<void(Error)> UnrecoverableErrorHandler,
+ raw_ostream *OS = nullptr, bool Verbose = false);
/// Skip the current line table and go to the following line table (if
/// present) immediately.
///
- /// \param ErrorCallback - report any prologue parsing issues via this
- /// callback.
- void skip(function_ref<void(Error)> ErrorCallback);
+ /// \param RecoverableErrorHandler - report any recoverable prologue
+ /// parsing issues via this handler.
+ /// \param UnrecoverableErrorHandler - report any unrecoverable prologue
+ /// parsing issues via this handler.
+ void skip(function_ref<void(Error)> RecoverableErrorHandler,
+ function_ref<void(Error)> UnrecoverableErrorHandler);
/// Indicates if the parser has parsed as much as possible.
///
@@ -340,34 +352,66 @@
bool done() const { return Done; }
/// Get the offset the parser has reached.
- uint32_t getOffset() const { return Offset; }
+ uint64_t getOffset() const { return Offset; }
private:
- DWARFUnit *prepareToParse(uint32_t Offset);
- void moveToNextTable(uint32_t OldOffset, const Prologue &P);
+ DWARFUnit *prepareToParse(uint64_t Offset);
+ void moveToNextTable(uint64_t OldOffset, const Prologue &P);
LineToUnitMap LineToUnit;
DWARFDataExtractor &DebugLineData;
const DWARFContext &Context;
- uint32_t Offset = 0;
+ uint64_t Offset = 0;
bool Done = false;
};
private:
struct ParsingState {
- ParsingState(struct LineTable *LT);
+ ParsingState(struct LineTable *LT, uint64_t TableOffset,
+ function_ref<void(Error)> ErrorHandler);
void resetRowAndSequence();
void appendRowToMatrix();
+ /// Advance the address by the \p OperationAdvance value. \returns the
+ /// amount advanced by.
+ uint64_t advanceAddr(uint64_t OperationAdvance, uint8_t Opcode,
+ uint64_t OpcodeOffset);
+
+ struct AddrAndAdjustedOpcode {
+ uint64_t AddrDelta;
+ uint8_t AdjustedOpcode;
+ };
+
+ /// Advance the address as required by the specified \p Opcode.
+ /// \returns the amount advanced by and the calculated adjusted opcode.
+ AddrAndAdjustedOpcode advanceAddrForOpcode(uint8_t Opcode,
+ uint64_t OpcodeOffset);
+
+ struct AddrAndLineDelta {
+ uint64_t Address;
+ int32_t Line;
+ };
+
+ /// Advance the line and address as required by the specified special \p
+ /// Opcode. \returns the address and line delta.
+ AddrAndLineDelta handleSpecialOpcode(uint8_t Opcode, uint64_t OpcodeOffset);
+
/// Line table we're currently parsing.
struct LineTable *LineTable;
struct Row Row;
struct Sequence Sequence;
+
+ private:
+ uint64_t LineTableOffset;
+
+ bool ReportAdvanceAddrProblem = true;
+ bool ReportBadLineRange = true;
+ function_ref<void(Error)> ErrorHandler;
};
- using LineTableMapTy = std::map<uint32_t, LineTable>;
+ using LineTableMapTy = std::map<uint64_t, LineTable>;
using LineTableIter = LineTableMapTy::iterator;
using LineTableConstIter = LineTableMapTy::const_iterator;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
index cced604..dbc11c5 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -11,7 +11,9 @@
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include <cstdint>
@@ -20,29 +22,75 @@
class MCRegisterInfo;
class raw_ostream;
-class DWARFDebugLoc {
-public:
- /// A single location within a location list.
- struct Entry {
- /// The beginning address of the instruction range.
- uint64_t Begin;
- /// The ending address of the instruction range.
- uint64_t End;
- /// The location of the variable within the specified range.
- SmallVector<char, 4> Loc;
- };
+/// A single location within a location list. Entries are stored in the DWARF5
+/// form even if they originally come from a DWARF<=4 location list.
+struct DWARFLocationEntry {
+ /// The entry kind (DW_LLE_***).
+ uint8_t Kind;
+ /// The first value of the location entry (if applicable).
+ uint64_t Value0;
+
+ /// The second value of the location entry (if applicable).
+ uint64_t Value1;
+
+ /// The index of the section this entry is relative to (if applicable).
+ uint64_t SectionIndex;
+
+ /// The location expression itself (if applicable).
+ SmallVector<uint8_t, 4> Loc;
+};
+
+/// An abstract base class for various kinds of location tables (.debug_loc,
+/// .debug_loclists, and their dwo variants).
+class DWARFLocationTable {
+public:
+ DWARFLocationTable(DWARFDataExtractor Data) : Data(std::move(Data)) {}
+ virtual ~DWARFLocationTable() = default;
+
+ /// Call the user-provided callback for each entry (including the end-of-list
+ /// entry) in the location list starting at \p Offset. The callback can return
+ /// false to terminate the iteration early. Returns an error if it was unable
+ /// to parse the entire location list correctly. Upon successful termination
+ /// \p Offset will be updated point past the end of the list.
+ virtual Error visitLocationList(
+ uint64_t *Offset,
+ function_ref<bool(const DWARFLocationEntry &)> Callback) const = 0;
+
+ /// Dump the location list at the given \p Offset. The function returns true
+ /// iff it has successfully reched the end of the list. This means that one
+ /// can attempt to parse another list after the current one (\p Offset will be
+ /// updated to point past the end of the current list).
+ bool dumpLocationList(uint64_t *Offset, raw_ostream &OS,
+ Optional<object::SectionedAddress> BaseAddr,
+ const MCRegisterInfo *MRI, const DWARFObject &Obj,
+ DWARFUnit *U, DIDumpOptions DumpOpts,
+ unsigned Indent) const;
+
+ Error visitAbsoluteLocationList(
+ uint64_t Offset, Optional<object::SectionedAddress> BaseAddr,
+ std::function<Optional<object::SectionedAddress>(uint32_t)> LookupAddr,
+ function_ref<bool(Expected<DWARFLocationExpression>)> Callback) const;
+
+ const DWARFDataExtractor &getData() { return Data; }
+
+protected:
+ DWARFDataExtractor Data;
+
+ virtual void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
+ unsigned Indent, DIDumpOptions DumpOpts,
+ const DWARFObject &Obj) const = 0;
+};
+
+class DWARFDebugLoc final : public DWARFLocationTable {
+public:
/// A list of locations that contain one variable.
struct LocationList {
/// The beginning offset where this location list is stored in the debug_loc
/// section.
- unsigned Offset;
+ uint64_t Offset;
/// All the locations in which the variable is stored.
- SmallVector<Entry, 2> Entries;
- /// Dump this list on OS.
- void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize,
- const MCRegisterInfo *MRI, DWARFUnit *U, uint64_t BaseAddress,
- unsigned Indent) const;
+ SmallVector<DWARFLocationEntry, 2> Entries;
};
private:
@@ -52,62 +100,46 @@
/// the locations in which the variable is stored.
LocationLists Locations;
- unsigned AddressSize;
-
- bool IsLittleEndian;
-
public:
+ DWARFDebugLoc(DWARFDataExtractor Data)
+ : DWARFLocationTable(std::move(Data)) {}
+
/// Print the location lists found within the debug_loc section.
void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo,
+ const DWARFObject &Obj, DIDumpOptions DumpOpts,
Optional<uint64_t> Offset) const;
- /// Parse the debug_loc section accessible via the 'data' parameter using the
- /// address size also given in 'data' to interpret the address ranges.
- void parse(const DWARFDataExtractor &data);
+ Error visitLocationList(
+ uint64_t *Offset,
+ function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
- /// Return the location list at the given offset or nullptr.
- LocationList const *getLocationListAtOffset(uint64_t Offset) const;
-
- Optional<LocationList> parseOneLocationList(DWARFDataExtractor Data,
- uint32_t *Offset);
+protected:
+ void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
+ unsigned Indent, DIDumpOptions DumpOpts,
+ const DWARFObject &Obj) const override;
};
-class DWARFDebugLoclists {
+class DWARFDebugLoclists final : public DWARFLocationTable {
public:
- struct Entry {
- uint8_t Kind;
- uint64_t Value0;
- uint64_t Value1;
- SmallVector<char, 4> Loc;
- };
+ DWARFDebugLoclists(DWARFDataExtractor Data, uint16_t Version)
+ : DWARFLocationTable(std::move(Data)), Version(Version) {}
- struct LocationList {
- unsigned Offset;
- SmallVector<Entry, 2> Entries;
- void dump(raw_ostream &OS, uint64_t BaseAddr, bool IsLittleEndian,
- unsigned AddressSize, const MCRegisterInfo *RegInfo,
- DWARFUnit *U, unsigned Indent) const;
- };
+ Error visitLocationList(
+ uint64_t *Offset,
+ function_ref<bool(const DWARFLocationEntry &)> Callback) const override;
+
+ /// Dump all location lists within the given range.
+ void dumpRange(uint64_t StartOffset, uint64_t Size, raw_ostream &OS,
+ const MCRegisterInfo *MRI, const DWARFObject &Obj,
+ DIDumpOptions DumpOpts);
+
+protected:
+ void dumpRawEntry(const DWARFLocationEntry &Entry, raw_ostream &OS,
+ unsigned Indent, DIDumpOptions DumpOpts,
+ const DWARFObject &Obj) const override;
private:
- using LocationLists = SmallVector<LocationList, 4>;
-
- LocationLists Locations;
-
- unsigned AddressSize;
-
- bool IsLittleEndian;
-
-public:
- void parse(DataExtractor data, unsigned Version);
- void dump(raw_ostream &OS, uint64_t BaseAddr, const MCRegisterInfo *RegInfo,
- Optional<uint64_t> Offset) const;
-
- /// Return the location list at the given offset or nullptr.
- LocationList const *getLocationListAtOffset(uint64_t Offset) const;
-
- static Optional<LocationList>
- parseOneLocationList(DataExtractor Data, unsigned *Offset, unsigned Version);
+ uint16_t Version;
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
index a6c1259..f1768a1 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
@@ -10,7 +10,10 @@
#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGMACRO_H
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Support/DataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/Error.h"
#include <cstdint>
namespace llvm {
@@ -18,6 +21,51 @@
class raw_ostream;
class DWARFDebugMacro {
+ /// DWARFv5 section 6.3.1 Macro Information Header.
+ enum HeaderFlagMask {
+#define HANDLE_MACRO_FLAG(ID, NAME) MACRO_##NAME = ID,
+#include "llvm/BinaryFormat/Dwarf.def"
+ };
+ struct MacroHeader {
+ /// Macro version information number.
+ uint16_t Version = 0;
+
+ /// The bits of the flags field are interpreted as a set of flags, some of
+ /// which may indicate that additional fields follow. The following flags,
+ /// beginning with the least significant bit, are defined:
+ /// offset_size_flag:
+ /// If the offset_size_flag is zero, the header is for a 32-bit DWARF
+ /// format macro section and all offsets are 4 bytes long; if it is one,
+ /// the header is for a 64-bit DWARF format macro section and all offsets
+ /// are 8 bytes long.
+ /// debug_line_offset_flag:
+ /// If the debug_line_offset_flag is one, the debug_line_offset field (see
+ /// below) is present. If zero, that field is omitted.
+ /// opcode_operands_table_flag:
+ /// If the opcode_operands_table_flag is one, the opcode_operands_table
+ /// field (see below) is present. If zero, that field is omitted.
+ uint8_t Flags = 0;
+
+ /// debug_line_offset
+ /// An offset in the .debug_line section of the beginning of the line
+ /// number information in the containing compilation unit, encoded as a
+ /// 4-byte offset for a 32-bit DWARF format macro section and an 8-byte
+ /// offset for a 64-bit DWARF format macro section.
+ uint64_t DebugLineOffset;
+
+ /// Print the macro header from the debug_macro section.
+ void dumpMacroHeader(raw_ostream &OS) const;
+
+ /// Parse the debug_macro header.
+ Error parseMacroHeader(DWARFDataExtractor Data, uint64_t *Offset);
+
+ /// Get the DWARF format according to the flags.
+ dwarf::DwarfFormat getDwarfFormat() const;
+
+ /// Get the size of a reference according to the DWARF format.
+ uint8_t getOffsetByteSize() const;
+ };
+
/// A single macro entry within a macro list.
struct Entry {
/// The type of the macro entry.
@@ -27,6 +75,8 @@
uint64_t Line;
/// Vendor extension constant value.
uint64_t ExtConstant;
+ /// Macro unit import offset.
+ uint64_t ImportOffset;
};
union {
@@ -39,22 +89,46 @@
};
};
- using MacroList = SmallVector<Entry, 4>;
+ struct MacroList {
+ // A value 0 in the `Header.Version` field indicates that we're parsing
+ // a macinfo[.dwo] section which doesn't have header itself, hence
+ // for that case other fields in the `Header` are uninitialized.
+ MacroHeader Header;
+ SmallVector<Entry, 4> Macros;
+ uint64_t Offset;
+
+ /// Whether or not this is a .debug_macro section.
+ bool IsDebugMacro;
+ };
/// A list of all the macro entries in the debug_macinfo section.
- MacroList Macros;
+ std::vector<MacroList> MacroLists;
public:
DWARFDebugMacro() = default;
- /// Print the macro list found within the debug_macinfo section.
+ /// Print the macro list found within the debug_macinfo/debug_macro section.
void dump(raw_ostream &OS) const;
- /// Parse the debug_macinfo section accessible via the 'data' parameter.
- void parse(DataExtractor data);
+ Error parseMacro(DWARFUnitVector::compile_unit_range Units,
+ DataExtractor StringExtractor,
+ DWARFDataExtractor MacroData) {
+ return parseImpl(Units, StringExtractor, MacroData, /*IsMacro=*/true);
+ }
+
+ Error parseMacinfo(DWARFDataExtractor MacroData) {
+ return parseImpl(None, None, MacroData, /*IsMacro=*/false);
+ }
/// Return whether the section has any entries.
- bool empty() const { return Macros.empty(); }
+ bool empty() const { return MacroLists.empty(); }
+
+private:
+ /// Parse the debug_macinfo/debug_macro section accessible via the 'MacroData'
+ /// parameter.
+ Error parseImpl(Optional<DWARFUnitVector::compile_unit_range> Units,
+ Optional<DataExtractor> StringExtractor,
+ DWARFDataExtractor Data, bool IsMacro);
};
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
index 99e91ca..cb34761 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
@@ -12,6 +12,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFObject.h"
#include <cstdint>
#include <vector>
@@ -25,7 +26,7 @@
public:
struct Entry {
/// Section offset from the beginning of the compilation unit.
- uint32_t SecOffset;
+ uint64_t SecOffset;
/// An entry of the various gnu_pub* debug sections.
dwarf::PubIndexEntryDescriptor Descriptor;
@@ -42,7 +43,10 @@
struct Set {
/// The total length of the entries for that set, not including the length
/// field itself.
- uint32_t Length;
+ uint64_t Length;
+
+ /// The DWARF format of the set.
+ dwarf::DwarfFormat Format;
/// This number is specific to the name lookup table and is independent of
/// the DWARF version number.
@@ -50,11 +54,11 @@
/// The offset from the beginning of the .debug_info section of the
/// compilation unit header referenced by the set.
- uint32_t Offset;
+ uint64_t Offset;
/// The size in bytes of the contents of the .debug_info section generated
/// to represent that compilation unit.
- uint32_t Size;
+ uint64_t Size;
std::vector<Entry> Entries;
};
@@ -64,11 +68,13 @@
/// gnu styled tables contains additional information.
/// This flag determines whether or not section we parse is debug_gnu* table.
- bool GnuStyle;
+ bool GnuStyle = false;
public:
- DWARFDebugPubTable(const DWARFObject &Obj, const DWARFSection &Sec,
- bool LittleEndian, bool GnuStyle);
+ DWARFDebugPubTable() = default;
+
+ void extract(DWARFDataExtractor Data, bool GnuStyle,
+ function_ref<void(Error)> RecoverableErrorHandler);
void dump(raw_ostream &OS) const;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
index a66f602..2f72c64 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -53,14 +53,13 @@
assert(AddressSize == 4 || AddressSize == 8);
if (AddressSize == 4)
return StartAddress == -1U;
- else
- return StartAddress == -1ULL;
+ return StartAddress == -1ULL;
}
};
private:
/// Offset in .debug_ranges section.
- uint32_t Offset;
+ uint64_t Offset;
uint8_t AddressSize;
std::vector<RangeListEntry> Entries;
@@ -69,7 +68,7 @@
void clear();
void dump(raw_ostream &OS) const;
- Error extract(const DWARFDataExtractor &data, uint32_t *offset_ptr);
+ Error extract(const DWARFDataExtractor &data, uint64_t *offset_ptr);
const std::vector<RangeListEntry> &getEntries() { return Entries; }
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
index 167ddde..4d28bdc 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDebugRnglists.h
@@ -34,7 +34,7 @@
uint64_t Value0;
uint64_t Value1;
- Error extract(DWARFDataExtractor Data, uint32_t End, uint32_t *OffsetPtr);
+ Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr);
void dump(raw_ostream &OS, uint8_t AddrSize, uint8_t MaxEncodingStringLength,
uint64_t &CurrentBase, DIDumpOptions DumpOpts,
llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
@@ -47,6 +47,13 @@
public:
/// Build a DWARFAddressRangesVector from a rangelist.
DWARFAddressRangesVector
+ getAbsoluteRanges(Optional<object::SectionedAddress> BaseAddr,
+ uint8_t AddressByteSize,
+ function_ref<Optional<object::SectionedAddress>(uint32_t)>
+ LookupPooledAddress) const;
+
+ /// Build a DWARFAddressRangesVector from a rangelist.
+ DWARFAddressRangesVector
getAbsoluteRanges(llvm::Optional<object::SectionedAddress> BaseAddr,
DWARFUnit &U) const;
};
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDie.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDie.h
index 21e68f9..0f76d7f 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -18,6 +18,7 @@
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFAttribute.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include <cassert>
#include <cstdint>
#include <iterator>
@@ -63,7 +64,7 @@
/// Get the absolute offset into the debug info or types section.
///
/// \returns the DIE offset or -1U if invalid.
- uint32_t getOffset() const {
+ uint64_t getOffset() const {
assert(isValid() && "must check validity prior to calling");
return Die->getOffset();
}
@@ -188,6 +189,7 @@
///
/// \returns anm optional absolute section offset value for the attribute.
Optional<uint64_t> getRangesBaseAttribute() const;
+ Optional<uint64_t> getLocBaseAttribute() const;
/// Get the DW_AT_high_pc attribute value as an address.
///
@@ -230,21 +232,37 @@
bool addressRangeContainsAddress(const uint64_t Address) const;
+ Expected<DWARFLocationExpressionsVector>
+ getLocations(dwarf::Attribute Attr) const;
+
/// If a DIE represents a subprogram (or inlined subroutine), returns its
/// mangled name (or short name, if mangled is missing). This name may be
/// fetched from specification or abstract origin for this subprogram.
/// Returns null if no name is found.
const char *getSubroutineName(DINameKind Kind) const;
- /// Return the DIE name resolving DW_AT_sepcification or DW_AT_abstract_origin
- /// references if necessary. Returns null if no name is found.
+ /// Return the DIE name resolving DW_AT_specification or DW_AT_abstract_origin
+ /// references if necessary. For the LinkageName case it additionaly searches
+ /// for ShortName if LinkageName is not found.
+ /// Returns null if no name is found.
const char *getName(DINameKind Kind) const;
+ /// Return the DIE short name resolving DW_AT_specification or
+ /// DW_AT_abstract_origin references if necessary. Returns null if no name
+ /// is found.
+ const char *getShortName() const;
+
+ /// Return the DIE linkage name resolving DW_AT_specification or
+ /// DW_AT_abstract_origin references if necessary. Returns null if no name
+ /// is found.
+ const char *getLinkageName() const;
+
/// Returns the declaration line (start line) for a DIE, assuming it specifies
/// a subprogram. This may be fetched from specification or abstract origin
/// for this subprogram by resolving DW_AT_sepcification or
/// DW_AT_abstract_origin references if necessary.
uint64_t getDeclLine() const;
+ std::string getDeclFile(DILineInfoSpecifier::FileLineInfoKind Kind) const;
/// Retrieves values of DW_AT_call_file, DW_AT_call_line and DW_AT_call_column
/// from DIE (or zeroes if they are missing). This function looks for
@@ -364,11 +382,6 @@
return LHS.Die == RHS.Die;
}
-inline bool operator!=(const DWARFDie::iterator &LHS,
- const DWARFDie::iterator &RHS) {
- return !(LHS == RHS);
-}
-
// These inline functions must follow the DWARFDie::iterator definition above
// as they use functions from that class.
inline DWARFDie::iterator DWARFDie::begin() const {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFExpression.h
index f066dd5..447ad66 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFExpression.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFExpression.h
@@ -10,8 +10,11 @@
#define LLVM_DEBUGINFO_DWARFEXPRESSION_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/iterator.h"
#include "llvm/ADT/iterator_range.h"
+#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/Support/DataExtractor.h"
namespace llvm {
@@ -42,6 +45,7 @@
SizeRefAddr = 6,
SizeBlock = 7, ///< Preceding operand contains block size
BaseTypeRef = 8,
+ WasmLocationArg = 30,
SignBit = 0x80,
SignedSize1 = SignBit | Size1,
SignedSize2 = SignBit | Size2,
@@ -77,21 +81,22 @@
uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
Description Desc;
bool Error;
- uint32_t EndOffset;
+ uint64_t EndOffset;
uint64_t Operands[2];
- uint32_t OperandEndOffsets[2];
+ uint64_t OperandEndOffsets[2];
public:
Description &getDescription() { return Desc; }
uint8_t getCode() { return Opcode; }
uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; }
- uint32_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; }
- uint32_t getEndOffset() { return EndOffset; }
- bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize,
- uint32_t Offset);
+ uint64_t getOperandEndOffset(unsigned Idx) { return OperandEndOffsets[Idx]; }
+ uint64_t getEndOffset() { return EndOffset; }
+ bool extract(DataExtractor Data, uint8_t AddressSize, uint64_t Offset,
+ Optional<dwarf::DwarfFormat> Format);
bool isError() { return Error; }
- bool print(raw_ostream &OS, const DWARFExpression *Expr,
- const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH);
+ bool print(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const DWARFExpression *Expr, const MCRegisterInfo *RegInfo,
+ DWARFUnit *U, bool isEH);
bool verify(DWARFUnit *U);
};
@@ -101,13 +106,13 @@
Operation> {
friend class DWARFExpression;
const DWARFExpression *Expr;
- uint32_t Offset;
+ uint64_t Offset;
Operation Op;
- iterator(const DWARFExpression *Expr, uint32_t Offset)
+ iterator(const DWARFExpression *Expr, uint64_t Offset)
: Expr(Expr), Offset(Offset) {
Op.Error =
Offset >= Expr->Data.getData().size() ||
- !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset);
+ !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
}
public:
@@ -115,7 +120,7 @@
Offset = Op.isError() ? Expr->Data.getData().size() : Op.EndOffset;
Op.Error =
Offset >= Expr->Data.getData().size() ||
- !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset);
+ !Op.extract(Expr->Data, Expr->AddressSize, Offset, Expr->Format);
return Op;
}
@@ -123,37 +128,44 @@
return Op;
}
+ iterator skipBytes(uint64_t Add) {
+ return iterator(Expr, Op.EndOffset + Add);
+ }
+
// Comparison operators are provided out of line.
friend bool operator==(const iterator &, const iterator &);
};
- DWARFExpression(DataExtractor Data, uint16_t Version, uint8_t AddressSize)
- : Data(Data), Version(Version), AddressSize(AddressSize) {
+ DWARFExpression(DataExtractor Data, uint8_t AddressSize,
+ Optional<dwarf::DwarfFormat> Format = None)
+ : Data(Data), AddressSize(AddressSize), Format(Format) {
assert(AddressSize == 8 || AddressSize == 4 || AddressSize == 2);
}
iterator begin() const { return iterator(this, 0); }
iterator end() const { return iterator(this, Data.getData().size()); }
- void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U,
+ void print(raw_ostream &OS, DIDumpOptions DumpOpts,
+ const MCRegisterInfo *RegInfo, DWARFUnit *U,
bool IsEH = false) const;
+ /// Print the expression in a format intended to be compact and useful to a
+ /// user, but not perfectly unambiguous, or capable of representing every
+ /// valid DWARF expression. Returns true if the expression was sucessfully
+ /// printed.
+ bool printCompact(raw_ostream &OS, const MCRegisterInfo &RegInfo);
+
bool verify(DWARFUnit *U);
private:
DataExtractor Data;
- uint16_t Version;
uint8_t AddressSize;
+ Optional<dwarf::DwarfFormat> Format;
};
inline bool operator==(const DWARFExpression::iterator &LHS,
const DWARFExpression::iterator &RHS) {
return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset;
}
-
-inline bool operator!=(const DWARFExpression::iterator &LHS,
- const DWARFExpression::iterator &RHS) {
- return !(LHS == RHS);
-}
}
#endif
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index 731e71e..1342e64 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -55,6 +55,8 @@
};
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.
const DWARFUnit *U = nullptr; /// Remember the DWARFUnit at extract time.
const DWARFContext *C = nullptr; /// Context for extract time.
@@ -70,7 +72,7 @@
static DWARFFormValue createFromBlockValue(dwarf::Form F,
ArrayRef<uint8_t> D);
static DWARFFormValue createFromUnit(dwarf::Form F, const DWARFUnit *Unit,
- uint32_t *OffsetPtr);
+ uint64_t *OffsetPtr);
dwarf::Form getForm() const { return Form; }
uint64_t getRawUValue() const { return Value.uval; }
@@ -80,6 +82,9 @@
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const;
void dumpSectionedAddress(raw_ostream &OS, DIDumpOptions DumpOpts,
object::SectionedAddress SA) const;
+ void dumpAddress(raw_ostream &OS, uint64_t Address) const;
+ static void dumpAddress(raw_ostream &OS, uint8_t AddressSize,
+ uint64_t Address);
static void dumpAddressSection(const DWARFObject &Obj, raw_ostream &OS,
DIDumpOptions DumpOpts, uint64_t SectionIndex);
@@ -87,12 +92,12 @@
/// in \p FormParams is needed to interpret some forms. The optional
/// \p Context and \p Unit allows extracting information if the form refers
/// to other sections (e.g., .debug_str).
- bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
+ bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr,
dwarf::FormParams FormParams,
const DWARFContext *Context = nullptr,
const DWARFUnit *Unit = nullptr);
- bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
+ bool extractValue(const DWARFDataExtractor &Data, uint64_t *OffsetPtr,
dwarf::FormParams FormParams, const DWARFUnit *U) {
return extractValue(Data, OffsetPtr, FormParams, nullptr, U);
}
@@ -128,7 +133,7 @@
/// \param OffsetPtr A reference to the offset that will be updated.
/// \param Params DWARF parameters to help interpret forms.
/// \returns true on success, false if the form was not skipped.
- bool skipValue(DataExtractor DebugInfoData, uint32_t *OffsetPtr,
+ bool skipValue(DataExtractor DebugInfoData, uint64_t *OffsetPtr,
const dwarf::FormParams Params) const {
return DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, Params);
}
@@ -144,7 +149,7 @@
/// \param FormParams DWARF parameters to help interpret forms.
/// \returns true on success, false if the form was not skipped.
static bool skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
- uint32_t *OffsetPtr,
+ uint64_t *OffsetPtr,
const dwarf::FormParams FormParams);
private:
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFListTable.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFListTable.h
index a1ea69b..8f58b4e 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFListTable.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFListTable.h
@@ -26,7 +26,7 @@
/// entries.
struct DWARFListEntryBase {
/// The offset at which the entry is located in the section.
- uint32_t Offset;
+ uint64_t Offset;
/// The DWARF encoding (DW_RLE_* or DW_LLE_*).
uint8_t EntryKind;
/// The index of the section this entry belongs to.
@@ -46,8 +46,8 @@
const ListEntries &getEntries() const { return Entries; }
bool empty() const { return Entries.empty(); }
void clear() { Entries.clear(); }
- Error extract(DWARFDataExtractor Data, uint32_t HeaderOffset, uint32_t End,
- uint32_t *OffsetPtr, StringRef SectionName,
+ Error extract(DWARFDataExtractor Data, uint64_t HeaderOffset,
+ uint64_t *OffsetPtr, StringRef SectionName,
StringRef ListStringName);
};
@@ -57,7 +57,7 @@
struct Header {
/// The total length of the entries for this table, not including the length
/// field itself.
- uint32_t Length = 0;
+ uint64_t Length = 0;
/// The DWARF version number.
uint16_t Version;
/// The size in bytes of an address on the target architecture. For
@@ -72,15 +72,11 @@
};
Header HeaderData;
- /// The offset table, which contains offsets to the individual list entries.
- /// It is used by forms such as DW_FORM_rnglistx.
- /// FIXME: Generate the table and use the appropriate forms.
- std::vector<uint32_t> Offsets;
/// The table's format, either DWARF32 or DWARF64.
dwarf::DwarfFormat Format;
/// The offset at which the header (and hence the table) is located within
/// its section.
- uint32_t HeaderOffset;
+ uint64_t HeaderOffset;
/// The name of the section the list is located in.
StringRef SectionName;
/// A characterization of the list for dumping purposes, e.g. "range" or
@@ -93,30 +89,53 @@
void clear() {
HeaderData = {};
- Offsets.clear();
}
- uint32_t getHeaderOffset() const { return HeaderOffset; }
+ uint64_t getHeaderOffset() const { return HeaderOffset; }
uint8_t getAddrSize() const { return HeaderData.AddrSize; }
- uint32_t getLength() const { return HeaderData.Length; }
+ uint64_t getLength() const { return HeaderData.Length; }
uint16_t getVersion() const { return HeaderData.Version; }
StringRef getSectionName() const { return SectionName; }
StringRef getListTypeString() const { return ListTypeString; }
dwarf::DwarfFormat getFormat() const { return Format; }
- void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) const;
- Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
- if (Index < Offsets.size())
- return Offsets[Index];
- return None;
+ /// Return the size of the table header including the length but not including
+ /// the offsets.
+ static uint8_t getHeaderSize(dwarf::DwarfFormat Format) {
+ switch (Format) {
+ case dwarf::DwarfFormat::DWARF32:
+ return 12;
+ case dwarf::DwarfFormat::DWARF64:
+ return 20;
+ }
+ llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
+ }
+
+ void dump(DataExtractor Data, raw_ostream &OS,
+ DIDumpOptions DumpOpts = {}) const;
+ Optional<uint64_t> getOffsetEntry(DataExtractor Data, uint32_t Index) const {
+ if (Index > HeaderData.OffsetEntryCount)
+ return None;
+
+ return getOffsetEntry(Data, getHeaderOffset() + getHeaderSize(Format), Format, Index);
+ }
+
+ static Optional<uint64_t> getOffsetEntry(DataExtractor Data,
+ uint64_t OffsetTableOffset,
+ dwarf::DwarfFormat Format,
+ uint32_t Index) {
+ uint8_t OffsetByteSize = Format == dwarf::DWARF64 ? 8 : 4;
+ uint64_t Offset = OffsetTableOffset + OffsetByteSize * Index;
+ auto R = Data.getUnsigned(&Offset, OffsetByteSize);
+ return R;
}
/// Extract the table header and the array of offsets.
- Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
+ Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr);
/// Returns the length of the table, including the length field, or 0 if the
/// length has not been determined (e.g. because the table has not yet been
/// parsed, or there was a problem in parsing).
- uint32_t length() const;
+ uint64_t length() const;
};
/// A class representing a table of lists as specified in the DWARF v5
@@ -128,7 +147,7 @@
DWARFListTableHeader Header;
/// A mapping between file offsets and lists. It is used to find a particular
/// list based on an offset (obtained from DW_AT_ranges, for example).
- std::map<uint32_t, DWARFListType> ListMap;
+ std::map<uint64_t, DWARFListType> ListMap;
/// This string is displayed as a heading before the list is dumped
/// (e.g. "ranges:").
StringRef HeaderString;
@@ -144,63 +163,58 @@
ListMap.clear();
}
/// Extract the table header and the array of offsets.
- Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint32_t *OffsetPtr) {
+ Error extractHeaderAndOffsets(DWARFDataExtractor Data, uint64_t *OffsetPtr) {
return Header.extract(Data, OffsetPtr);
}
/// Extract an entire table, including all list entries.
- Error extract(DWARFDataExtractor Data, uint32_t *OffsetPtr);
+ Error extract(DWARFDataExtractor Data, uint64_t *OffsetPtr);
/// Look up a list based on a given offset. Extract it and enter it into the
/// list map if necessary.
- Expected<DWARFListType> findList(DWARFDataExtractor Data, uint32_t Offset);
+ Expected<DWARFListType> findList(DWARFDataExtractor Data, uint64_t Offset);
- uint32_t getHeaderOffset() const { return Header.getHeaderOffset(); }
+ uint64_t getHeaderOffset() const { return Header.getHeaderOffset(); }
uint8_t getAddrSize() const { return Header.getAddrSize(); }
+ dwarf::DwarfFormat getFormat() const { return Header.getFormat(); }
- void dump(raw_ostream &OS,
+ void dump(DWARFDataExtractor Data, raw_ostream &OS,
llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress,
DIDumpOptions DumpOpts = {}) const;
/// Return the contents of the offset entry designated by a given index.
- Optional<uint32_t> getOffsetEntry(uint32_t Index) const {
- return Header.getOffsetEntry(Index);
+ Optional<uint64_t> getOffsetEntry(DataExtractor Data, uint32_t Index) const {
+ return Header.getOffsetEntry(Data, Index);
}
/// Return the size of the table header including the length but not including
/// the offsets. This is dependent on the table format, which is unambiguously
/// derived from parsing the table.
uint8_t getHeaderSize() const {
- switch (Header.getFormat()) {
- case dwarf::DwarfFormat::DWARF32:
- return 12;
- case dwarf::DwarfFormat::DWARF64:
- return 20;
- }
- llvm_unreachable("Invalid DWARF format (expected DWARF32 or DWARF64");
+ return DWARFListTableHeader::getHeaderSize(getFormat());
}
- uint32_t length() { return Header.length(); }
+ uint64_t length() { return Header.length(); }
};
template <typename DWARFListType>
Error DWARFListTableBase<DWARFListType>::extract(DWARFDataExtractor Data,
- uint32_t *OffsetPtr) {
+ uint64_t *OffsetPtr) {
clear();
if (Error E = extractHeaderAndOffsets(Data, OffsetPtr))
return E;
Data.setAddressSize(Header.getAddrSize());
- uint32_t End = getHeaderOffset() + Header.length();
- while (*OffsetPtr < End) {
+ Data = DWARFDataExtractor(Data, getHeaderOffset() + Header.length());
+ while (Data.isValidOffset(*OffsetPtr)) {
DWARFListType CurrentList;
- uint32_t Off = *OffsetPtr;
- if (Error E = CurrentList.extract(Data, getHeaderOffset(), End, OffsetPtr,
+ uint64_t Off = *OffsetPtr;
+ if (Error E = CurrentList.extract(Data, getHeaderOffset(), OffsetPtr,
Header.getSectionName(),
Header.getListTypeString()))
return E;
ListMap[Off] = CurrentList;
}
- assert(*OffsetPtr == End &&
+ assert(*OffsetPtr == Data.size() &&
"mismatch between expected length of table and length "
"of extracted data");
return Error::success();
@@ -208,18 +222,18 @@
template <typename ListEntryType>
Error DWARFListType<ListEntryType>::extract(DWARFDataExtractor Data,
- uint32_t HeaderOffset, uint32_t End,
- uint32_t *OffsetPtr,
+ uint64_t HeaderOffset,
+ uint64_t *OffsetPtr,
StringRef SectionName,
StringRef ListTypeString) {
- if (*OffsetPtr < HeaderOffset || *OffsetPtr >= End)
+ if (*OffsetPtr < HeaderOffset || *OffsetPtr >= Data.size())
return createStringError(errc::invalid_argument,
- "invalid %s list offset 0x%" PRIx32,
+ "invalid %s list offset 0x%" PRIx64,
ListTypeString.data(), *OffsetPtr);
Entries.clear();
- while (*OffsetPtr < End) {
+ while (Data.isValidOffset(*OffsetPtr)) {
ListEntryType Entry;
- if (Error E = Entry.extract(Data, End, OffsetPtr))
+ if (Error E = Entry.extract(Data, OffsetPtr))
return E;
Entries.push_back(Entry);
if (Entry.isSentinel())
@@ -227,17 +241,17 @@
}
return createStringError(errc::illegal_byte_sequence,
"no end of list marker detected at end of %s table "
- "starting at offset 0x%" PRIx32,
+ "starting at offset 0x%" PRIx64,
SectionName.data(), HeaderOffset);
}
template <typename DWARFListType>
void DWARFListTableBase<DWARFListType>::dump(
- raw_ostream &OS,
+ DWARFDataExtractor Data, raw_ostream &OS,
llvm::function_ref<Optional<object::SectionedAddress>(uint32_t)>
LookupPooledAddress,
DIDumpOptions DumpOpts) const {
- Header.dump(OS, DumpOpts);
+ Header.dump(Data, OS, DumpOpts);
OS << HeaderString << "\n";
// Determine the length of the longest encoding string we have in the table,
@@ -261,20 +275,15 @@
template <typename DWARFListType>
Expected<DWARFListType>
DWARFListTableBase<DWARFListType>::findList(DWARFDataExtractor Data,
- uint32_t Offset) {
- auto Entry = ListMap.find(Offset);
- if (Entry != ListMap.end())
- return Entry->second;
-
+ uint64_t Offset) {
// Extract the list from the section and enter it into the list map.
DWARFListType List;
- uint32_t End = getHeaderOffset() + Header.length();
- uint32_t StartingOffset = Offset;
+ if (Header.length())
+ Data = DWARFDataExtractor(Data, getHeaderOffset() + Header.length());
if (Error E =
- List.extract(Data, getHeaderOffset(), End, &Offset,
+ List.extract(Data, Header.length() ? getHeaderOffset() : 0, &Offset,
Header.getSectionName(), Header.getListTypeString()))
return std::move(E);
- ListMap[StartingOffset] = List;
return List;
}
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFLocationExpression.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFLocationExpression.h
new file mode 100644
index 0000000..35aa1a7
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFLocationExpression.h
@@ -0,0 +1,49 @@
+//===- DWARFLocationExpression.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H
+#define LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+/// Represents a single DWARF expression, whose value is location-dependent.
+/// Typically used in DW_AT_location attributes to describe the location of
+/// objects.
+struct DWARFLocationExpression {
+ /// The address range in which this expression is valid. None denotes a
+ /// default entry which is valid in addresses not covered by other location
+ /// expressions, or everywhere if there are no other expressions.
+ Optional<DWARFAddressRange> Range;
+
+ /// The expression itself.
+ SmallVector<uint8_t, 4> Expr;
+};
+
+inline bool operator==(const DWARFLocationExpression &L,
+ const DWARFLocationExpression &R) {
+ return L.Range == R.Range && L.Expr == R.Expr;
+}
+
+inline bool operator!=(const DWARFLocationExpression &L,
+ const DWARFLocationExpression &R) {
+ return !(L == R);
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const DWARFLocationExpression &Loc);
+
+/// Represents a set of absolute location expressions.
+using DWARFLocationExpressionsVector = std::vector<DWARFLocationExpression>;
+
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_DWARF_DWARFLOCATIONEXPRESSION_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFObject.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFObject.h
index 1bba74a..60fcd3d 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFObject.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFObject.h
@@ -39,20 +39,23 @@
virtual StringRef getAbbrevSection() const { return ""; }
virtual const DWARFSection &getLocSection() const { return Dummy; }
virtual const DWARFSection &getLoclistsSection() const { return Dummy; }
- virtual StringRef getARangeSection() const { return ""; }
- virtual StringRef getDebugFrameSection() const { return ""; }
- virtual StringRef getEHFrameSection() const { return ""; }
+ virtual StringRef getArangesSection() const { return ""; }
+ virtual const DWARFSection &getFrameSection() const { return Dummy; }
+ virtual const DWARFSection &getEHFrameSection() const { return Dummy; }
virtual const DWARFSection &getLineSection() const { return Dummy; }
- virtual StringRef getLineStringSection() const { return ""; }
- virtual StringRef getStringSection() const { return ""; }
- virtual const DWARFSection &getRangeSection() const { return Dummy; }
+ virtual StringRef getLineStrSection() const { return ""; }
+ virtual StringRef getStrSection() const { return ""; }
+ virtual const DWARFSection &getRangesSection() const { return Dummy; }
virtual const DWARFSection &getRnglistsSection() const { return Dummy; }
+ virtual const DWARFSection &getMacroSection() const { return Dummy; }
+ virtual StringRef getMacroDWOSection() const { return ""; }
virtual StringRef getMacinfoSection() const { return ""; }
- virtual const DWARFSection &getPubNamesSection() const { return Dummy; }
- virtual const DWARFSection &getPubTypesSection() const { return Dummy; }
- virtual const DWARFSection &getGnuPubNamesSection() const { return Dummy; }
- virtual const DWARFSection &getGnuPubTypesSection() const { return Dummy; }
- virtual const DWARFSection &getStringOffsetSection() const { return Dummy; }
+ virtual StringRef getMacinfoDWOSection() const { return ""; }
+ virtual const DWARFSection &getPubnamesSection() const { return Dummy; }
+ virtual const DWARFSection &getPubtypesSection() const { return Dummy; }
+ virtual const DWARFSection &getGnuPubnamesSection() const { return Dummy; }
+ virtual const DWARFSection &getGnuPubtypesSection() const { return Dummy; }
+ virtual const DWARFSection &getStrOffsetsSection() const { return Dummy; }
virtual void
forEachInfoDWOSections(function_ref<void(const DWARFSection &)> F) const {}
virtual void
@@ -60,11 +63,12 @@
virtual StringRef getAbbrevDWOSection() const { return ""; }
virtual const DWARFSection &getLineDWOSection() const { return Dummy; }
virtual const DWARFSection &getLocDWOSection() const { return Dummy; }
- virtual StringRef getStringDWOSection() const { return ""; }
- virtual const DWARFSection &getStringOffsetDWOSection() const {
+ virtual const DWARFSection &getLoclistsDWOSection() const { return Dummy; }
+ virtual StringRef getStrDWOSection() const { return ""; }
+ virtual const DWARFSection &getStrOffsetsDWOSection() const {
return Dummy;
}
- virtual const DWARFSection &getRangeDWOSection() const { return Dummy; }
+ virtual const DWARFSection &getRangesDWOSection() const { return Dummy; }
virtual const DWARFSection &getRnglistsDWOSection() const { return Dummy; }
virtual const DWARFSection &getAddrSection() const { return Dummy; }
virtual const DWARFSection &getAppleNamesSection() const { return Dummy; }
@@ -72,7 +76,7 @@
virtual const DWARFSection &getAppleNamespacesSection() const {
return Dummy;
}
- virtual const DWARFSection &getDebugNamesSection() const { return Dummy; }
+ virtual const DWARFSection &getNamesSection() const { return Dummy; }
virtual const DWARFSection &getAppleObjCSection() const { return Dummy; }
virtual StringRef getCUIndexSection() const { return ""; }
virtual StringRef getGdbIndexSection() const { return ""; }
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
index cd022e7..3add711 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFRelocMap.h
@@ -20,8 +20,10 @@
struct RelocAddrEntry {
uint64_t SectionIndex;
object::RelocationRef Reloc;
- object::RelocationResolver Resolver;
uint64_t SymbolValue;
+ Optional<object::RelocationRef> Reloc2;
+ uint64_t SymbolValue2;
+ object::RelocationResolver Resolver;
};
/// In place of applying the relocations to the data we've read from disk we use
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
index 90d8937..c95bdcb 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
@@ -34,7 +34,7 @@
LS, LE, IsDWO, UnitVector) {}
uint64_t getTypeHash() const { return getHeader().getTypeHash(); }
- uint32_t getTypeOffset() const { return getHeader().getTypeOffset(); }
+ uint64_t getTypeOffset() const { return getHeader().getTypeOffset(); }
void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
// Enable LLVM-style RTTI.
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index f9f90db..369cbdc 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
@@ -45,7 +46,7 @@
/// parse the header before deciding what specific kind of unit to construct.
class DWARFUnitHeader {
// Offset within section.
- uint32_t Offset = 0;
+ uint64_t Offset = 0;
// Version, address size, and DWARF format.
dwarf::FormParams FormParams;
uint64_t Length = 0;
@@ -56,7 +57,7 @@
// For type units only.
uint64_t TypeHash = 0;
- uint32_t TypeOffset = 0;
+ uint64_t TypeOffset = 0;
// For v5 split or skeleton compile units only.
Optional<uint64_t> DWOId;
@@ -69,11 +70,15 @@
public:
/// Parse a unit header from \p debug_info starting at \p offset_ptr.
+ /// Note that \p SectionKind is used as a hint to guess the unit type
+ /// for DWARF formats prior to DWARFv5. In DWARFv5 the unit type is
+ /// explicitly defined in the header and the hint is ignored.
bool extract(DWARFContext &Context, const DWARFDataExtractor &debug_info,
- uint32_t *offset_ptr, DWARFSectionKind Kind = DW_SECT_INFO,
- const DWARFUnitIndex *Index = nullptr,
- const DWARFUnitIndex::Entry *Entry = nullptr);
- uint32_t getOffset() const { return Offset; }
+ uint64_t *offset_ptr, DWARFSectionKind SectionKind);
+ // For units in DWARF Package File, remember the index entry and update
+ // the abbreviation offset read by extract().
+ bool applyIndexEntry(const DWARFUnitIndex::Entry *Entry);
+ uint64_t getOffset() const { return Offset; }
const dwarf::FormParams &getFormParams() const { return FormParams; }
uint16_t getVersion() const { return FormParams.Version; }
dwarf::DwarfFormat getFormat() const { return FormParams.Format; }
@@ -91,26 +96,29 @@
}
const DWARFUnitIndex::Entry *getIndexEntry() const { return IndexEntry; }
uint64_t getTypeHash() const { return TypeHash; }
- uint32_t getTypeOffset() const { return TypeOffset; }
+ uint64_t getTypeOffset() const { return TypeOffset; }
uint8_t getUnitType() const { return UnitType; }
bool isTypeUnit() const {
return UnitType == dwarf::DW_UT_type || UnitType == dwarf::DW_UT_split_type;
}
uint8_t getSize() const { return Size; }
- uint32_t getNextUnitOffset() const {
- return Offset + Length +
- (FormParams.Format == llvm::dwarf::DwarfFormat::DWARF64 ? 4 : 0) +
- FormParams.getDwarfOffsetByteSize();
+ uint8_t getUnitLengthFieldByteSize() const {
+ return dwarf::getUnitLengthFieldByteSize(FormParams.Format);
+ }
+ uint64_t getNextUnitOffset() const {
+ return Offset + Length + getUnitLengthFieldByteSize();
}
};
const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
DWARFSectionKind Kind);
+bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U);
+
/// Describe a collection of units. Intended to hold all units either from
/// .debug_info and .debug_types, or from .debug_info.dwo and .debug_types.dwo.
class DWARFUnitVector final : public SmallVector<std::unique_ptr<DWARFUnit>, 1> {
- std::function<std::unique_ptr<DWARFUnit>(uint32_t, DWARFSectionKind,
+ std::function<std::unique_ptr<DWARFUnit>(uint64_t, DWARFSectionKind,
const DWARFSection *,
const DWARFUnitIndex::Entry *)>
Parser;
@@ -121,7 +129,10 @@
using iterator = typename UnitVector::iterator;
using iterator_range = llvm::iterator_range<typename UnitVector::iterator>;
- DWARFUnit *getUnitForOffset(uint32_t Offset) const;
+ using compile_unit_range =
+ decltype(make_filter_range(std::declval<iterator_range>(), isCompileUnit));
+
+ DWARFUnit *getUnitForOffset(uint64_t Offset) const;
DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E);
/// Read units from a .debug_info or .debug_types section. Calls made
@@ -197,18 +208,17 @@
DWARFUnitHeader Header;
const DWARFDebugAbbrev *Abbrev;
const DWARFSection *RangeSection;
- uint32_t RangeSectionBase;
- /// We either keep track of the location list section or its data, depending
- /// on whether we are handling a split DWARF section or not.
- union {
- const DWARFSection *LocSection;
- StringRef LocSectionData;
- };
+ uint64_t RangeSectionBase;
+ uint64_t LocSectionBase;
+
+ /// Location table of this unit.
+ std::unique_ptr<DWARFLocationTable> LocTable;
+
const DWARFSection &LineSection;
StringRef StringSection;
const DWARFSection &StringOffsetSection;
const DWARFSection *AddrOffsetSection;
- uint32_t AddrOffsetSectionBase = 0;
+ Optional<uint64_t> AddrOffsetSectionBase;
bool isLittleEndian;
bool IsDWO;
const DWARFUnitVector &UnitVector;
@@ -217,9 +227,6 @@
/// offsets table (DWARF v5).
Optional<StrOffsetsContributionDescriptor> StringOffsetsTableContribution;
- /// A table of range lists (DWARF v5 and later).
- Optional<DWARFDebugRnglistTable> RngListTable;
-
mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
llvm::Optional<object::SectionedAddress> BaseAddr;
/// The compile unit debug information entry items.
@@ -273,9 +280,7 @@
bool isDWOUnit() const { return IsDWO; }
DWARFContext& getContext() const { return Context; }
const DWARFSection &getInfoSection() const { return InfoSection; }
- const DWARFSection *getLocSection() const { return LocSection; }
- StringRef getLocSectionData() const { return LocSectionData; }
- uint32_t getOffset() const { return Header.getOffset(); }
+ uint64_t getOffset() const { return Header.getOffset(); }
const dwarf::FormParams &getFormParams() const {
return Header.getFormParams();
}
@@ -285,17 +290,19 @@
uint8_t getDwarfOffsetByteSize() const {
return Header.getDwarfOffsetByteSize();
}
- uint32_t getLength() const { return Header.getLength(); }
+ uint64_t getLength() const { return Header.getLength(); }
+ dwarf::DwarfFormat getFormat() const { return Header.getFormat(); }
uint8_t getUnitType() const { return Header.getUnitType(); }
bool isTypeUnit() const { return Header.isTypeUnit(); }
- uint32_t getNextUnitOffset() const { return Header.getNextUnitOffset(); }
+ uint64_t getAbbrOffset() const { return Header.getAbbrOffset(); }
+ uint64_t getNextUnitOffset() const { return Header.getNextUnitOffset(); }
const DWARFSection &getLineSection() const { return LineSection; }
StringRef getStringSection() const { return StringSection; }
const DWARFSection &getStringOffsetSection() const {
return StringOffsetSection;
}
- void setAddrOffsetSection(const DWARFSection *AOS, uint32_t Base) {
+ void setAddrOffsetSection(const DWARFSection *AOS, uint64_t Base) {
AddrOffsetSection = AOS;
AddrOffsetSectionBase = Base;
}
@@ -303,11 +310,15 @@
/// Recursively update address to Die map.
void updateAddressDieMap(DWARFDie Die);
- void setRangesSection(const DWARFSection *RS, uint32_t Base) {
+ void setRangesSection(const DWARFSection *RS, uint64_t Base) {
RangeSection = RS;
RangeSectionBase = Base;
}
+ uint64_t getLocSectionBase() const {
+ return LocSectionBase;
+ }
+
Optional<object::SectionedAddress>
getAddrOffsetSectionItem(uint32_t Index) const;
Optional<uint64_t> getStringOffsetSectionItem(uint32_t Index) const;
@@ -318,11 +329,13 @@
return DataExtractor(StringSection, false, 0);
}
+ const DWARFLocationTable &getLocationTable() { return *LocTable; }
+
/// Extract the range list referenced by this compile unit from the
/// .debug_ranges section. If the extraction is unsuccessful, an error
/// is returned. Successful extraction requires that the compile unit
/// has already been extracted.
- Error extractRangeList(uint32_t RangeListOffset,
+ Error extractRangeList(uint64_t RangeListOffset,
DWARFDebugRangeList &RangeList) const;
void clear();
@@ -360,26 +373,6 @@
return false;
}
- /// Return the number of bytes for the header of a unit of
- /// UnitType type.
- ///
- /// This function must be called with a valid unit type which in
- /// DWARF5 is defined as one of the following six types.
- static uint32_t getDWARF5HeaderSize(uint8_t UnitType) {
- switch (UnitType) {
- case dwarf::DW_UT_compile:
- case dwarf::DW_UT_partial:
- return 12;
- case dwarf::DW_UT_skeleton:
- case dwarf::DW_UT_split_compile:
- return 20;
- case dwarf::DW_UT_type:
- case dwarf::DW_UT_split_type:
- return 24;
- }
- llvm_unreachable("Invalid UnitType.");
- }
-
llvm::Optional<object::SectionedAddress> getBaseAddress();
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
@@ -405,7 +398,7 @@
/// Return a vector of address ranges resulting from a (possibly encoded)
/// range list starting at a given offset in the appropriate ranges section.
- Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint32_t Offset);
+ Expected<DWARFAddressRangesVector> findRnglistFromOffset(uint64_t Offset);
/// Return a vector of address ranges retrieved from an encoded range
/// list whose offset is found via a table lookup given an index (DWARF v5
@@ -415,14 +408,15 @@
/// Return a rangelist's offset based on an index. The index designates
/// an entry in the rangelist table's offset array and is supplied by
/// DW_FORM_rnglistx.
- Optional<uint32_t> getRnglistOffset(uint32_t Index) {
- if (RngListTable)
- return RngListTable->getOffsetEntry(Index);
- return None;
- }
+ Optional<uint64_t> getRnglistOffset(uint32_t Index);
+
+ Optional<uint64_t> getLoclistOffset(uint32_t Index);
Expected<DWARFAddressRangesVector> collectAddressRanges();
+ Expected<DWARFLocationExpressionsVector>
+ findLoclistFromOffset(uint64_t Offset);
+
/// Returns subprogram DIE with address range encompassing the provided
/// address. The pointer is alive as long as parsed compile unit DIEs are not
/// cleared.
@@ -470,9 +464,8 @@
/// unit's DIE vector.
///
/// The unit needs to have its DIEs extracted for this method to work.
- DWARFDie getDIEForOffset(uint32_t Offset) {
+ DWARFDie getDIEForOffset(uint64_t Offset) {
extractDIEsIfNeeded(false);
- assert(!DieArray.empty());
auto It =
llvm::partition_point(DieArray, [=](const DWARFDebugInfoEntry &DIE) {
return DIE.getOffset() < Offset;
@@ -484,7 +477,7 @@
uint32_t getLineTableOffset() const {
if (auto IndexEntry = Header.getIndexEntry())
- if (const auto *Contrib = IndexEntry->getOffset(DW_SECT_LINE))
+ if (const auto *Contrib = IndexEntry->getContribution(DW_SECT_LINE))
return Contrib->Offset;
return 0;
}
@@ -495,15 +488,19 @@
}
virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
+
+ Error tryExtractDIEsIfNeeded(bool CUDieOnly);
+
private:
/// Size in bytes of the .debug_info data associated with this compile unit.
size_t getDebugInfoSize() const {
- return Header.getLength() + 4 - getHeaderSize();
+ return Header.getLength() + Header.getUnitLengthFieldByteSize() -
+ getHeaderSize();
}
/// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it
- /// hasn't already been done. Returns the number of DIEs parsed at this call.
- size_t extractDIEsIfNeeded(bool CUDieOnly);
+ /// hasn't already been done
+ void extractDIEsIfNeeded(bool CUDieOnly);
/// extractDIEsToVector - Appends all parsed DIEs to a vector.
void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs,
@@ -517,6 +514,10 @@
bool parseDWO();
};
+inline bool isCompileUnit(const std::unique_ptr<DWARFUnit> &U) {
+ return !U->isTypeUnit();
+}
+
} // end namespace llvm
#endif // LLVM_DEBUGINFO_DWARF_DWARFUNIT_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
index fc8c707..edea59e 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
@@ -19,17 +19,64 @@
class raw_ostream;
+/// The enum of section identifiers to be used in internal interfaces.
+///
+/// Pre-standard implementation of package files defined a number of section
+/// identifiers with values that clash definitions in the DWARFv5 standard.
+/// See https://gcc.gnu.org/wiki/DebugFissionDWP and Section 7.3.5.3 in DWARFv5.
+///
+/// The following identifiers are the same in the proposal and in DWARFv5:
+/// - DW_SECT_INFO = 1 (.debug_info.dwo)
+/// - DW_SECT_ABBREV = 3 (.debug_abbrev.dwo)
+/// - DW_SECT_LINE = 4 (.debug_line.dwo)
+/// - DW_SECT_STR_OFFSETS = 6 (.debug_str_offsets.dwo)
+///
+/// The following identifiers are defined only in DWARFv5:
+/// - DW_SECT_LOCLISTS = 5 (.debug_loclists.dwo)
+/// - DW_SECT_RNGLISTS = 8 (.debug_rnglists.dwo)
+///
+/// The following identifiers are defined only in the GNU proposal:
+/// - DW_SECT_TYPES = 2 (.debug_types.dwo)
+/// - DW_SECT_LOC = 5 (.debug_loc.dwo)
+/// - DW_SECT_MACINFO = 7 (.debug_macinfo.dwo)
+///
+/// DW_SECT_MACRO for the .debug_macro.dwo section is defined in both standards,
+/// but with different values, 8 in GNU and 7 in DWARFv5.
+///
+/// This enum defines constants to represent the identifiers of both sets.
+/// For DWARFv5 ones, the values are the same as defined in the standard.
+/// For pre-standard ones that correspond to sections being deprecated in
+/// DWARFv5, the values are chosen arbitrary and a tag "_EXT_" is added to
+/// the names.
+///
+/// The enum is for internal use only. The user should not expect the values
+/// to correspond to any input/output constants. Special conversion functions,
+/// serializeSectionKind() and deserializeSectionKind(), should be used for
+/// the translation.
enum DWARFSectionKind {
- DW_SECT_INFO = 1,
- DW_SECT_TYPES,
- DW_SECT_ABBREV,
- DW_SECT_LINE,
- DW_SECT_LOC,
- DW_SECT_STR_OFFSETS,
- DW_SECT_MACINFO,
- DW_SECT_MACRO,
+ /// Denotes a value read from an index section that does not correspond
+ /// to any of the supported standards.
+ DW_SECT_EXT_unknown = 0,
+#define HANDLE_DW_SECT(ID, NAME) DW_SECT_##NAME = ID,
+#include "llvm/BinaryFormat/Dwarf.def"
+ DW_SECT_EXT_TYPES = 2,
+ DW_SECT_EXT_LOC = 9,
+ DW_SECT_EXT_MACINFO = 10,
};
+/// Convert the internal value for a section kind to an on-disk value.
+///
+/// The conversion depends on the version of the index section.
+/// IndexVersion is expected to be either 2 for pre-standard GNU proposal
+/// or 5 for DWARFv5 package file.
+uint32_t serializeSectionKind(DWARFSectionKind Kind, unsigned IndexVersion);
+
+/// Convert a value read from an index section to the internal representation.
+///
+/// The conversion depends on the index section version, which is expected
+/// to be either 2 for pre-standard GNU proposal or 5 for DWARFv5 package file.
+DWARFSectionKind deserializeSectionKind(uint32_t Value, unsigned IndexVersion);
+
class DWARFUnitIndex {
struct Header {
uint32_t Version;
@@ -37,7 +84,7 @@
uint32_t NumUnits;
uint32_t NumBuckets = 0;
- bool parse(DataExtractor IndexData, uint32_t *OffsetPtr);
+ bool parse(DataExtractor IndexData, uint64_t *OffsetPtr);
void dump(raw_ostream &OS) const;
};
@@ -56,10 +103,10 @@
friend class DWARFUnitIndex;
public:
- const SectionContribution *getOffset(DWARFSectionKind Sec) const;
- const SectionContribution *getOffset() const;
+ const SectionContribution *getContribution(DWARFSectionKind Sec) const;
+ const SectionContribution *getContribution() const;
- const SectionContribution *getOffsets() const {
+ const SectionContribution *getContributions() const {
return Contributions.get();
}
@@ -72,6 +119,10 @@
DWARFSectionKind InfoColumnKind;
int InfoColumn = -1;
std::unique_ptr<DWARFSectionKind[]> ColumnKinds;
+ // This is a parallel array of section identifiers as they read from the input
+ // file. The mapping from raw values to DWARFSectionKind is not revertable in
+ // case of unknown identifiers, so we keep them here.
+ std::unique_ptr<uint32_t[]> RawSectionIds;
std::unique_ptr<Entry[]> Rows;
mutable std::vector<Entry *> OffsetLookup;
@@ -88,6 +139,8 @@
bool parse(DataExtractor IndexData);
void dump(raw_ostream &OS) const;
+ uint32_t getVersion() const { return Header.Version; }
+
const Entry *getFromOffset(uint32_t Offset) const;
const Entry *getFromHash(uint64_t Offset) const;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
index f1268f2..18d889f 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
@@ -9,27 +9,25 @@
#ifndef LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
+#include "llvm/ADT/Optional.h"
#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
-#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
-
#include <cstdint>
#include <map>
#include <set>
namespace llvm {
class raw_ostream;
+struct DWARFAddressRange;
struct DWARFAttribute;
class DWARFContext;
-class DWARFDie;
-class DWARFUnit;
-class DWARFCompileUnit;
class DWARFDataExtractor;
class DWARFDebugAbbrev;
class DataExtractor;
struct DWARFSection;
+class DWARFUnit;
/// A class that verifies DWARF debug information given a DWARF Context.
class DWARFVerifier {
@@ -56,11 +54,13 @@
typedef std::set<DieRangeInfo>::const_iterator die_range_info_iterator;
/// Inserts the address range. If the range overlaps with an existing
- /// range, the range is *not* added and an iterator to the overlapping
- /// range is returned.
+ /// range, the range that it overlaps with will be returned and the two
+ /// address ranges will be unioned together in "Ranges".
///
- /// This is used for finding overlapping ranges within the same DIE.
- address_range_iterator insert(const DWARFAddressRange &R);
+ /// This is used for finding overlapping ranges in the DW_AT_ranges
+ /// attribute of a DIE. It is also used as a set of address ranges that
+ /// children address ranges must all be contained in.
+ Optional<DWARFAddressRange> insert(const DWARFAddressRange &R);
/// Finds an address range in the sorted vector of ranges.
address_range_iterator findRange(const DWARFAddressRange &R) const {
@@ -94,7 +94,7 @@
/// A map that tracks all references (converted absolute references) so we
/// can verify each reference points to a valid DIE and not an offset that
/// lies between to valid DIEs.
- std::map<uint64_t, std::set<uint32_t>> ReferenceToDIEOffsets;
+ std::map<uint64_t, std::set<uint64_t>> ReferenceToDIEOffsets;
uint32_t NumDebugLineErrors = 0;
// Used to relax some checks that do not currently work portably
bool IsObjectFile;
@@ -138,7 +138,7 @@
///
/// \returns true if the header is verified successfully, false otherwise.
bool verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
- uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType,
+ uint64_t *Offset, unsigned UnitIndex, uint8_t &UnitType,
bool &isUnitDWARF64);
/// Verifies the header of a unit in a .debug_info or .debug_types section.
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/DwarfTransformer.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/DwarfTransformer.h
new file mode 100644
index 0000000..a5d07fb
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/DwarfTransformer.h
@@ -0,0 +1,91 @@
+//===- DwarfTransformer.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_GSYM_DWARFTRANSFORMER_H
+#define LLVM_DEBUGINFO_GSYM_DWARFTRANSFORMER_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/GSYM/Range.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace gsym {
+
+struct CUInfo;
+struct FunctionInfo;
+class GsymCreator;
+
+/// A class that transforms the DWARF in a DWARFContext into GSYM information
+/// by populating the GsymCreator object that it is constructed with. This
+/// class supports converting all DW_TAG_subprogram DIEs into
+/// gsym::FunctionInfo objects that includes line table information and inline
+/// function information. Creating a separate class to transform this data
+/// allows this class to be unit tested.
+class DwarfTransformer {
+public:
+
+ /// Create a DWARF transformer.
+ ///
+ /// \param D The DWARF to use when converting to GSYM.
+ ///
+ /// \param OS The stream to log warnings and non fatal issues to.
+ ///
+ /// \param G The GSYM creator to populate with the function information
+ /// from the debug info.
+ DwarfTransformer(DWARFContext &D, raw_ostream &OS, GsymCreator &G) :
+ DICtx(D), Log(OS), Gsym(G) {}
+
+ /// Extract the DWARF from the supplied object file and convert it into the
+ /// Gsym format in the GsymCreator object that is passed in. Returns an
+ /// error if something fatal is encountered.
+ ///
+ /// \returns An error indicating any fatal issues that happen when parsing
+ /// the DWARF, or Error::success() if all goes well.
+ llvm::Error convert(uint32_t NumThreads);
+
+ llvm::Error verify(StringRef GsymPath);
+
+
+private:
+
+ /// Parse the DWARF in the object file and convert it into the GsymCreator.
+ Error parse();
+
+ /// Handle any DIE (debug info entry) from the DWARF.
+ ///
+ /// This function will find all DW_TAG_subprogram DIEs that convert them into
+ /// GSYM FuntionInfo objects and add them to the GsymCreator supplied during
+ /// construction. The DIE and all its children will be recursively parsed
+ /// with calls to this function.
+ ///
+ /// \param Strm The thread specific log stream for any non fatal errors and
+ /// warnings. Once a thread has finished parsing an entire compile unit, all
+ /// information in this temporary stream will be forwarded to the member
+ /// variable log. This keeps logging thread safe.
+ ///
+ /// \param CUI The compile unit specific information that contains the DWARF
+ /// line table, cached file list, and other compile unit specific
+ /// information.
+ ///
+ /// \param Die The DWARF debug info entry to parse.
+ void handleDie(raw_ostream &Strm, CUInfo &CUI, DWARFDie Die);
+
+ DWARFContext &DICtx;
+ raw_ostream &Log;
+ GsymCreator &Gsym;
+
+ friend class DwarfTransformerTest;
+};
+
+} // namespace gsym
+} // namespace llvm
+
+#endif // #ifndef LLVM_DEBUGINFO_GSYM_DWARFTRANSFORMER_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/FileEntry.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/FileEntry.h
index 228b4ef..49e7fc9 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/GSYM/FileEntry.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/FileEntry.h
@@ -1,9 +1,8 @@
//===- FileEntry.h ----------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/FileWriter.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/FileWriter.h
new file mode 100644
index 0000000..cd56876
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/FileWriter.h
@@ -0,0 +1,124 @@
+//===- FileWriter.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_GSYM_FILEWRITER_H
+#define LLVM_DEBUGINFO_GSYM_FILEWRITER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Support/Endian.h"
+
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+namespace llvm {
+class raw_pwrite_stream;
+
+namespace gsym {
+
+/// A simplified binary data writer class that doesn't require targets, target
+/// definitions, architectures, or require any other optional compile time
+/// libraries to be enabled via the build process. This class needs the ability
+/// to seek to different spots in the binary stream that is produces to fixup
+/// offsets and sizes.
+class FileWriter {
+ llvm::raw_pwrite_stream &OS;
+ llvm::support::endianness ByteOrder;
+public:
+ FileWriter(llvm::raw_pwrite_stream &S, llvm::support::endianness B)
+ : OS(S), ByteOrder(B) {}
+ ~FileWriter();
+ /// Write a single uint8_t value into the stream at the current file
+ /// position.
+ ///
+ /// \param Value The value to write into the stream.
+ void writeU8(uint8_t Value);
+
+ /// Write a single uint16_t value into the stream at the current file
+ /// position. The value will be byte swapped if needed to match the byte
+ /// order specified during construction.
+ ///
+ /// \param Value The value to write into the stream.
+ void writeU16(uint16_t Value);
+
+ /// Write a single uint32_t value into the stream at the current file
+ /// position. The value will be byte swapped if needed to match the byte
+ /// order specified during construction.
+ ///
+ /// \param Value The value to write into the stream.
+ void writeU32(uint32_t Value);
+
+ /// Write a single uint64_t value into the stream at the current file
+ /// position. The value will be byte swapped if needed to match the byte
+ /// order specified during construction.
+ ///
+ /// \param Value The value to write into the stream.
+ void writeU64(uint64_t Value);
+
+ /// Write the value into the stream encoded using signed LEB128 at the
+ /// current file position.
+ ///
+ /// \param Value The value to write into the stream.
+ void writeSLEB(int64_t Value);
+
+ /// Write the value into the stream encoded using unsigned LEB128 at the
+ /// current file position.
+ ///
+ /// \param Value The value to write into the stream.
+ void writeULEB(uint64_t Value);
+
+ /// Write an array of uint8_t values into the stream at the current file
+ /// position.
+ ///
+ /// \param Data An array of values to write into the stream.
+ void writeData(llvm::ArrayRef<uint8_t> Data);
+
+ /// Write a NULL terminated C string into the stream at the current file
+ /// position. The entire contents of Str will be written into the steam at
+ /// the current file position and then an extra NULL termation byte will be
+ /// written. It is up to the user to ensure that Str doesn't contain any NULL
+ /// characters unless the additional NULL characters are desired.
+ ///
+ /// \param Str The value to write into the stream.
+ void writeNullTerminated(llvm::StringRef Str);
+
+ /// Fixup a uint32_t value at the specified offset in the stream. This
+ /// function will save the current file position, seek to the specified
+ /// offset, overwrite the data using Value, and then restore the file
+ /// position to the previous file position.
+ ///
+ /// \param Value The value to write into the stream.
+ /// \param Offset The offset at which to write the Value within the stream.
+ void fixup32(uint32_t Value, uint64_t Offset);
+
+ /// Pad with zeroes at the current file position until the current file
+ /// position matches the specified alignment.
+ ///
+ /// \param Align An integer speciying the desired alignment. This does not
+ /// need to be a power of two.
+ void alignTo(size_t Align);
+
+ /// Return the current offset within the file.
+ ///
+ /// \return The unsigned offset from the start of the file of the current
+ /// file position.
+ uint64_t tell();
+
+ llvm::raw_pwrite_stream &get_stream() {
+ return OS;
+ }
+
+private:
+ FileWriter(const FileWriter &rhs) = delete;
+ void operator=(const FileWriter &rhs) = delete;
+};
+
+} // namespace gsym
+} // namespace llvm
+
+#endif // #ifndef LLVM_DEBUGINFO_GSYM_FILEWRITER_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/FunctionInfo.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/FunctionInfo.h
index eedb1e6..893cfc1 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/GSYM/FunctionInfo.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/FunctionInfo.h
@@ -1,17 +1,18 @@
//===- FunctionInfo.h -------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_GSYM_FUNCTIONINFO_H
#define LLVM_DEBUGINFO_GSYM_FUNCTIONINFO_H
+#include "llvm/ADT/Optional.h"
#include "llvm/DebugInfo/GSYM/InlineInfo.h"
-#include "llvm/DebugInfo/GSYM/LineEntry.h"
+#include "llvm/DebugInfo/GSYM/LineTable.h"
+#include "llvm/DebugInfo/GSYM/LookupResult.h"
#include "llvm/DebugInfo/GSYM/Range.h"
#include "llvm/DebugInfo/GSYM/StringTable.h"
#include <tuple>
@@ -21,41 +22,153 @@
class raw_ostream;
namespace gsym {
-/// Function information in GSYM files encodes information for one
-/// contiguous address range. The name of the function is encoded as
-/// a string table offset and allows multiple functions with the same
-/// name to share the name string in the string table. Line tables are
-/// stored in a sorted vector of gsym::LineEntry objects and are split
-/// into line tables for each function. If a function has a discontiguous
-/// range, it will be split into two gsym::FunctionInfo objects. If the
-/// function has inline functions, the information will be encoded in
-/// the "Inline" member, see gsym::InlineInfo for more information.
+class GsymReader;
+/// Function information in GSYM files encodes information for one contiguous
+/// address range. If a function has discontiguous address ranges, they will
+/// need to be encoded using multiple FunctionInfo objects.
+///
+/// ENCODING
+///
+/// The function information gets the function start address as an argument
+/// to the FunctionInfo::decode(...) function. This information is calculated
+/// from the GSYM header and an address offset from the GSYM address offsets
+/// table. The encoded FunctionInfo information must be aligned to a 4 byte
+/// boundary.
+///
+/// The encoded data for a FunctionInfo starts with fixed data that all
+/// function info objects have:
+///
+/// ENCODING NAME DESCRIPTION
+/// ========= =========== ====================================================
+/// uint32_t Size The size in bytes of this function.
+/// uint32_t Name The string table offset of the function name.
+///
+/// The optional data in a FunctionInfo object follows this fixed information
+/// and consists of a stream of tuples that consist of:
+///
+/// ENCODING NAME DESCRIPTION
+/// ========= =========== ====================================================
+/// uint32_t InfoType An "InfoType" enumeration that describes the type
+/// of optional data that is encoded.
+/// uint32_t InfoLength The size in bytes of the encoded data that
+/// immediately follows this length if this value is
+/// greater than zero.
+/// uint8_t[] InfoData Encoded bytes that represent the data for the
+/// "InfoType". These bytes are only present if
+/// "InfoLength" is greater than zero.
+///
+/// The "InfoType" is an enumeration:
+///
+/// enum InfoType {
+/// EndOfList = 0u,
+/// LineTableInfo = 1u,
+/// InlineInfo = 2u
+/// };
+///
+/// This stream of tuples is terminated by a "InfoType" whose value is
+/// InfoType::EndOfList and a zero for "InfoLength". This signifies the end of
+/// the optional information list. This format allows us to add new optional
+/// information data to a FunctionInfo object over time and allows older
+/// clients to still parse the format and skip over any data that they don't
+/// understand or want to parse.
+///
+/// So the function information encoding essientially looks like:
+///
+/// struct {
+/// uint32_t Size;
+/// uint32_t Name;
+/// struct {
+/// uint32_t InfoType;
+/// uint32_t InfoLength;
+/// uint8_t InfoData[InfoLength];
+/// }[N];
+/// }
+///
+/// Where "N" is the number of tuples.
struct FunctionInfo {
AddressRange Range;
uint32_t Name; ///< String table offset in the string table.
- std::vector<gsym::LineEntry> Lines;
- InlineInfo Inline;
+ llvm::Optional<LineTable> OptLineTable;
+ llvm::Optional<InlineInfo> Inline;
FunctionInfo(uint64_t Addr = 0, uint64_t Size = 0, uint32_t N = 0)
: Range(Addr, Addr + Size), Name(N) {}
+ /// Query if a FunctionInfo has rich debug info.
+ ///
+ /// \returns A bool that indicates if this object has something else than
+ /// range and name. When converting information from a symbol table and from
+ /// debug info, we might end up with multiple FunctionInfo objects for the
+ /// same range and we need to be able to tell which one is the better object
+ /// to use.
bool hasRichInfo() const {
- /// Returns whether we have something else than range and name. When
- /// converting information from a symbol table and from debug info, we
- /// might end up with multiple FunctionInfo objects for the same range
- /// and we need to be able to tell which one is the better object to use.
- return !Lines.empty() || Inline.isValid();
+ return OptLineTable.hasValue() || Inline.hasValue();
}
+ /// Query if a FunctionInfo object is valid.
+ ///
+ /// Address and size can be zero and there can be no line entries for a
+ /// symbol so the only indication this entry is valid is if the name is
+ /// not zero. This can happen when extracting information from symbol
+ /// tables that do not encode symbol sizes. In that case only the
+ /// address and name will be filled in.
+ ///
+ /// \returns A boolean indicating if this FunctionInfo is valid.
bool isValid() const {
- /// Address and size can be zero and there can be no line entries for a
- /// symbol so the only indication this entry is valid is if the name is
- /// not zero. This can happen when extracting information from symbol
- /// tables that do not encode symbol sizes. In that case only the
- /// address and name will be filled in.
return Name != 0;
}
+ /// Decode an object from a binary data stream.
+ ///
+ /// \param Data The binary stream to read the data from. This object must
+ /// have the data for the object starting at offset zero. The data
+ /// can contain more data than needed.
+ ///
+ /// \param BaseAddr The FunctionInfo's start address and will be used as the
+ /// base address when decoding any contained information like the line table
+ /// and the inline info.
+ ///
+ /// \returns An FunctionInfo or an error describing the issue that was
+ /// encountered during decoding.
+ static llvm::Expected<FunctionInfo> decode(DataExtractor &Data,
+ uint64_t BaseAddr);
+
+ /// Encode this object into FileWriter stream.
+ ///
+ /// \param O The binary stream to write the data to at the current file
+ /// position.
+ ///
+ /// \returns An error object that indicates failure or the offset of the
+ /// function info that was successfully written into the stream.
+ llvm::Expected<uint64_t> encode(FileWriter &O) const;
+
+
+ /// Lookup an address within a FunctionInfo object's data stream.
+ ///
+ /// Instead of decoding an entire FunctionInfo object when doing lookups,
+ /// we can decode only the information we need from the FunctionInfo's data
+ /// for the specific address. The lookup result information is returned as
+ /// a LookupResult.
+ ///
+ /// \param Data The binary stream to read the data from. This object must
+ /// have the data for the object starting at offset zero. The data
+ /// can contain more data than needed.
+ ///
+ /// \param GR The GSYM reader that contains the string and file table that
+ /// will be used to fill in information in the returned result.
+ ///
+ /// \param FuncAddr The function start address decoded from the GsymReader.
+ ///
+ /// \param Addr The address to lookup.
+ ///
+ /// \returns An LookupResult or an error describing the issue that was
+ /// encountered during decoding. An error should only be returned if the
+ /// address is not contained in the FunctionInfo or if the data is corrupted.
+ static llvm::Expected<LookupResult> lookup(DataExtractor &Data,
+ const GsymReader &GR,
+ uint64_t FuncAddr,
+ uint64_t Addr);
+
uint64_t startAddress() const { return Range.Start; }
uint64_t endAddress() const { return Range.End; }
uint64_t size() const { return Range.size(); }
@@ -66,14 +179,14 @@
void clear() {
Range = {0, 0};
Name = 0;
- Lines.clear();
- Inline.clear();
+ OptLineTable = None;
+ Inline = None;
}
};
inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) {
return LHS.Range == RHS.Range && LHS.Name == RHS.Name &&
- LHS.Lines == RHS.Lines && LHS.Inline == RHS.Inline;
+ LHS.OptLineTable == RHS.OptLineTable && LHS.Inline == RHS.Inline;
}
inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) {
return !(LHS == RHS);
@@ -89,14 +202,10 @@
return LHS.Range < RHS.Range;
// Then sort by inline
- if (LHS.Inline.isValid() != RHS.Inline.isValid())
- return RHS.Inline.isValid();
+ if (LHS.Inline.hasValue() != RHS.Inline.hasValue())
+ return RHS.Inline.hasValue();
- // If the number of lines is the same, then compare line table entries
- if (LHS.Lines.size() == RHS.Lines.size())
- return LHS.Lines < RHS.Lines;
- // Then sort by number of line table entries (more is better)
- return LHS.Lines.size() < RHS.Lines.size();
+ return LHS.OptLineTable < RHS.OptLineTable;
}
raw_ostream &operator<<(raw_ostream &OS, const FunctionInfo &R);
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/GsymCreator.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/GsymCreator.h
new file mode 100644
index 0000000..f29a147
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/GsymCreator.h
@@ -0,0 +1,297 @@
+//===- GsymCreator.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_GSYM_GSYMCREATOR_H
+#define LLVM_DEBUGINFO_GSYM_GSYMCREATOR_H
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <string>
+#include <thread>
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringSet.h"
+#include "llvm/DebugInfo/GSYM/FileEntry.h"
+#include "llvm/DebugInfo/GSYM/FunctionInfo.h"
+#include "llvm/DebugInfo/GSYM/Range.h"
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/Path.h"
+
+namespace llvm {
+
+namespace gsym {
+class FileWriter;
+
+/// GsymCreator is used to emit GSYM data to a stand alone file or section
+/// within a file.
+///
+/// The GsymCreator is designed to be used in 3 stages:
+/// - Create FunctionInfo objects and add them
+/// - Finalize the GsymCreator object
+/// - Save to file or section
+///
+/// The first stage involves creating FunctionInfo objects from another source
+/// of information like compiler debug info metadata, DWARF or Breakpad files.
+/// Any strings in the FunctionInfo or contained information, like InlineInfo
+/// or LineTable objects, should get the string table offsets by calling
+/// GsymCreator::insertString(...). Any file indexes that are needed should be
+/// obtained by calling GsymCreator::insertFile(...). All of the function calls
+/// in GsymCreator are thread safe. This allows multiple threads to create and
+/// add FunctionInfo objects while parsing debug information.
+///
+/// Once all of the FunctionInfo objects have been added, the
+/// GsymCreator::finalize(...) must be called prior to saving. This function
+/// will sort the FunctionInfo objects, finalize the string table, and do any
+/// other passes on the information needed to prepare the information to be
+/// saved.
+///
+/// Once the object has been finalized, it can be saved to a file or section.
+///
+/// ENCODING
+///
+/// GSYM files are designed to be memory mapped into a process as shared, read
+/// only data, and used as is.
+///
+/// The GSYM file format when in a stand alone file consists of:
+/// - Header
+/// - Address Table
+/// - Function Info Offsets
+/// - File Table
+/// - String Table
+/// - Function Info Data
+///
+/// HEADER
+///
+/// The header is fully described in "llvm/DebugInfo/GSYM/Header.h".
+///
+/// ADDRESS TABLE
+///
+/// The address table immediately follows the header in the file and consists
+/// of Header.NumAddresses address offsets. These offsets are sorted and can be
+/// binary searched for efficient lookups. Addresses in the address table are
+/// stored as offsets from a 64 bit base address found in Header.BaseAddress.
+/// This allows the address table to contain 8, 16, or 32 offsets. This allows
+/// the address table to not require full 64 bit addresses for each address.
+/// The resulting GSYM size is smaller and causes fewer pages to be touched
+/// during address lookups when the address table is smaller. The size of the
+/// address offsets in the address table is specified in the header in
+/// Header.AddrOffSize. The first offset in the address table is aligned to
+/// Header.AddrOffSize alignment to ensure efficient access when loaded into
+/// memory.
+///
+/// FUNCTION INFO OFFSETS TABLE
+///
+/// The function info offsets table immediately follows the address table and
+/// consists of Header.NumAddresses 32 bit file offsets: one for each address
+/// in the address table. This data is aligned to a 4 byte boundary. The
+/// offsets in this table are the relative offsets from the start offset of the
+/// GSYM header and point to the function info data for each address in the
+/// address table. Keeping this data separate from the address table helps to
+/// reduce the number of pages that are touched when address lookups occur on a
+/// GSYM file.
+///
+/// FILE TABLE
+///
+/// The file table immediately follows the function info offsets table. The
+/// encoding of the FileTable is:
+///
+/// struct FileTable {
+/// uint32_t Count;
+/// FileEntry Files[];
+/// };
+///
+/// The file table starts with a 32 bit count of the number of files that are
+/// used in all of the function info, followed by that number of FileEntry
+/// structures. The file table is aligned to a 4 byte boundary, Each file in
+/// the file table is represented with a FileEntry structure.
+/// See "llvm/DebugInfo/GSYM/FileEntry.h" for details.
+///
+/// STRING TABLE
+///
+/// The string table follows the file table in stand alone GSYM files and
+/// contains all strings for everything contained in the GSYM file. Any string
+/// data should be added to the string table and any references to strings
+/// inside GSYM information must be stored as 32 bit string table offsets into
+/// this string table. The string table always starts with an empty string at
+/// offset zero and is followed by any strings needed by the GSYM information.
+/// The start of the string table is not aligned to any boundary.
+///
+/// FUNCTION INFO DATA
+///
+/// The function info data is the payload that contains information about the
+/// address that is being looked up. It contains all of the encoded
+/// FunctionInfo objects. Each encoded FunctionInfo's data is pointed to by an
+/// entry in the Function Info Offsets Table. For details on the exact encoding
+/// of FunctionInfo objects, see "llvm/DebugInfo/GSYM/FunctionInfo.h".
+class GsymCreator {
+ // Private member variables require Mutex protections
+ mutable std::recursive_mutex Mutex;
+ std::vector<FunctionInfo> Funcs;
+ StringTableBuilder StrTab;
+ StringSet<> StringStorage;
+ DenseMap<llvm::gsym::FileEntry, uint32_t> FileEntryToIndex;
+ std::vector<llvm::gsym::FileEntry> Files;
+ std::vector<uint8_t> UUID;
+ Optional<AddressRanges> ValidTextRanges;
+ AddressRanges Ranges;
+ llvm::Optional<uint64_t> BaseAddress;
+ bool Finalized = false;
+
+public:
+
+ GsymCreator();
+
+ /// Save a GSYM file to a stand alone file.
+ ///
+ /// \param Path The file path to save the GSYM file to.
+ /// \param ByteOrder The endianness to use when saving the file.
+ /// \returns An error object that indicates success or failure of the save.
+ llvm::Error save(StringRef Path, llvm::support::endianness ByteOrder) const;
+
+ /// Encode a GSYM into the file writer stream at the current position.
+ ///
+ /// \param O The stream to save the binary data to
+ /// \returns An error object that indicates success or failure of the save.
+ llvm::Error encode(FileWriter &O) const;
+
+ /// Insert a string into the GSYM string table.
+ ///
+ /// All strings used by GSYM files must be uniqued by adding them to this
+ /// string pool and using the returned offset for any string values.
+ ///
+ /// \param S The string to insert into the string table.
+ /// \param Copy If true, then make a backing copy of the string. If false,
+ /// the string is owned by another object that will stay around
+ /// long enough for the GsymCreator to save the GSYM file.
+ /// \returns The unique 32 bit offset into the string table.
+ uint32_t insertString(StringRef S, bool Copy = true);
+
+ /// Insert a file into this GSYM creator.
+ ///
+ /// Inserts a file by adding a FileEntry into the "Files" member variable if
+ /// the file has not already been added. The file path is split into
+ /// directory and filename which are both added to the string table. This
+ /// allows paths to be stored efficiently by reusing the directories that are
+ /// common between multiple files.
+ ///
+ /// \param Path The path to the file to insert.
+ /// \param Style The path style for the "Path" parameter.
+ /// \returns The unique file index for the inserted file.
+ uint32_t insertFile(StringRef Path,
+ sys::path::Style Style = sys::path::Style::native);
+
+ /// Add a function info to this GSYM creator.
+ ///
+ /// All information in the FunctionInfo object must use the
+ /// GsymCreator::insertString(...) function when creating string table
+ /// offsets for names and other strings.
+ ///
+ /// \param FI The function info object to emplace into our functions list.
+ void addFunctionInfo(FunctionInfo &&FI);
+
+ /// Finalize the data in the GSYM creator prior to saving the data out.
+ ///
+ /// Finalize must be called after all FunctionInfo objects have been added
+ /// and before GsymCreator::save() is called.
+ ///
+ /// \param OS Output stream to report duplicate function infos, overlapping
+ /// function infos, and function infos that were merged or removed.
+ /// \returns An error object that indicates success or failure of the
+ /// finalize.
+ llvm::Error finalize(llvm::raw_ostream &OS);
+
+ /// Set the UUID value.
+ ///
+ /// \param UUIDBytes The new UUID bytes.
+ void setUUID(llvm::ArrayRef<uint8_t> UUIDBytes) {
+ UUID.assign(UUIDBytes.begin(), UUIDBytes.end());
+ }
+
+ /// Thread safe iteration over all function infos.
+ ///
+ /// \param Callback A callback function that will get called with each
+ /// FunctionInfo. If the callback returns false, stop iterating.
+ void forEachFunctionInfo(
+ std::function<bool(FunctionInfo &)> const &Callback);
+
+ /// Thread safe const iteration over all function infos.
+ ///
+ /// \param Callback A callback function that will get called with each
+ /// FunctionInfo. If the callback returns false, stop iterating.
+ void forEachFunctionInfo(
+ std::function<bool(const FunctionInfo &)> const &Callback) const;
+
+ /// Get the current number of FunctionInfo objects contained in this
+ /// object.
+ size_t getNumFunctionInfos() const;
+
+ /// Check if an address has already been added as a function info.
+ ///
+ /// FunctionInfo data can come from many sources: debug info, symbol tables,
+ /// exception information, and more. Symbol tables should be added after
+ /// debug info and can use this function to see if a symbol's start address
+ /// has already been added to the GsymReader. Calling this before adding
+ /// a function info from a source other than debug info avoids clients adding
+ /// many redundant FunctionInfo objects from many sources only for them to be
+ /// removed during the finalize() call.
+ bool hasFunctionInfoForAddress(uint64_t Addr) const;
+
+ /// Set valid .text address ranges that all functions must be contained in.
+ void SetValidTextRanges(AddressRanges &TextRanges) {
+ ValidTextRanges = TextRanges;
+ }
+
+ /// Get the valid text ranges.
+ const Optional<AddressRanges> GetValidTextRanges() const {
+ return ValidTextRanges;
+ }
+
+ /// Check if an address is a valid code address.
+ ///
+ /// Any functions whose addresses do not exist within these function bounds
+ /// will not be converted into the final GSYM. This allows the object file
+ /// to figure out the valid file address ranges of all the code sections
+ /// and ensure we don't add invalid functions to the final output. Many
+ /// linkers have issues when dead stripping functions from DWARF debug info
+ /// where they set the DW_AT_low_pc to zero, but newer DWARF has the
+ /// DW_AT_high_pc as an offset from the DW_AT_low_pc and these size
+ /// attributes have no relocations that can be applied. This results in DWARF
+ /// where many functions have an DW_AT_low_pc of zero and a valid offset size
+ /// for DW_AT_high_pc. If we extract all valid ranges from an object file
+ /// that are marked with executable permissions, we can properly ensure that
+ /// these functions are removed.
+ ///
+ /// \param Addr An address to check.
+ ///
+ /// \returns True if the address is in the valid text ranges or if no valid
+ /// text ranges have been set, false otherwise.
+ bool IsValidTextAddress(uint64_t Addr) const;
+
+ /// Set the base address to use for the GSYM file.
+ ///
+ /// Setting the base address to use for the GSYM file. Object files typically
+ /// get loaded from a base address when the OS loads them into memory. Using
+ /// GSYM files for symbolication becomes easier if the base address in the
+ /// GSYM header is the same address as it allows addresses to be easily slid
+ /// and allows symbolication without needing to find the original base
+ /// address in the original object file.
+ ///
+ /// \param Addr The address to use as the base address of the GSYM file
+ /// when it is saved to disk.
+ void setBaseAddress(uint64_t Addr) {
+ BaseAddress = Addr;
+ }
+};
+
+} // namespace gsym
+} // namespace llvm
+
+#endif // #ifndef LLVM_DEBUGINFO_GSYM_GSYMCREATOR_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/GsymReader.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/GsymReader.h
new file mode 100644
index 0000000..2a4eac7
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/GsymReader.h
@@ -0,0 +1,313 @@
+//===- GsymReader.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_GSYM_GSYMREADER_H
+#define LLVM_DEBUGINFO_GSYM_GSYMREADER_H
+
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/DebugInfo/GSYM/FileEntry.h"
+#include "llvm/DebugInfo/GSYM/FunctionInfo.h"
+#include "llvm/DebugInfo/GSYM/Header.h"
+#include "llvm/DebugInfo/GSYM/LineEntry.h"
+#include "llvm/DebugInfo/GSYM/StringTable.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ErrorOr.h"
+
+#include <inttypes.h>
+#include <memory>
+#include <stdint.h>
+#include <string>
+#include <vector>
+
+namespace llvm {
+class MemoryBuffer;
+class raw_ostream;
+
+namespace gsym {
+
+/// GsymReader is used to read GSYM data from a file or buffer.
+///
+/// This class is optimized for very quick lookups when the endianness matches
+/// the host system. The Header, address table, address info offsets, and file
+/// table is designed to be mmap'ed as read only into memory and used without
+/// any parsing needed. If the endianness doesn't match, we swap these objects
+/// and tables into GsymReader::SwappedData and then point our header and
+/// ArrayRefs to this swapped internal data.
+///
+/// GsymReader objects must use one of the static functions to create an
+/// instance: GsymReader::openFile(...) and GsymReader::copyBuffer(...).
+
+class GsymReader {
+ GsymReader(std::unique_ptr<MemoryBuffer> Buffer);
+ llvm::Error parse();
+
+ std::unique_ptr<MemoryBuffer> MemBuffer;
+ StringRef GsymBytes;
+ llvm::support::endianness Endian;
+ const Header *Hdr = nullptr;
+ ArrayRef<uint8_t> AddrOffsets;
+ ArrayRef<uint32_t> AddrInfoOffsets;
+ ArrayRef<FileEntry> Files;
+ StringTable StrTab;
+ /// When the GSYM file's endianness doesn't match the host system then
+ /// we must decode all data structures that need to be swapped into
+ /// local storage and set point the ArrayRef objects above to these swapped
+ /// copies.
+ struct SwappedData {
+ Header Hdr;
+ std::vector<uint8_t> AddrOffsets;
+ std::vector<uint32_t> AddrInfoOffsets;
+ std::vector<FileEntry> Files;
+ };
+ std::unique_ptr<SwappedData> Swap;
+
+public:
+ GsymReader(GsymReader &&RHS);
+ ~GsymReader();
+
+ /// Construct a GsymReader from a file on disk.
+ ///
+ /// \param Path The file path the GSYM file to read.
+ /// \returns An expected GsymReader that contains the object or an error
+ /// object that indicates reason for failing to read the GSYM.
+ static llvm::Expected<GsymReader> openFile(StringRef Path);
+
+ /// Construct a GsymReader from a buffer.
+ ///
+ /// \param Bytes A set of bytes that will be copied and owned by the
+ /// returned object on success.
+ /// \returns An expected GsymReader that contains the object or an error
+ /// object that indicates reason for failing to read the GSYM.
+ static llvm::Expected<GsymReader> copyBuffer(StringRef Bytes);
+
+ /// Access the GSYM header.
+ /// \returns A native endian version of the GSYM header.
+ const Header &getHeader() const;
+
+ /// Get the full function info for an address.
+ ///
+ /// This should be called when a client will store a copy of the complete
+ /// FunctionInfo for a given address. For one off lookups, use the lookup()
+ /// function below.
+ ///
+ /// Symbolication server processes might want to parse the entire function
+ /// info for a given address and cache it if the process stays around to
+ /// service many symbolication addresses, like for parsing profiling
+ /// information.
+ ///
+ /// \param Addr A virtual address from the orignal object file to lookup.
+ ///
+ /// \returns An expected FunctionInfo that contains the function info object
+ /// or an error object that indicates reason for failing to lookup the
+ /// address.
+ llvm::Expected<FunctionInfo> getFunctionInfo(uint64_t Addr) const;
+
+ /// Lookup an address in the a GSYM.
+ ///
+ /// Lookup just the information needed for a specific address \a Addr. This
+ /// function is faster that calling getFunctionInfo() as it will only return
+ /// information that pertains to \a Addr and allows the parsing to skip any
+ /// extra information encoded for other addresses. For example the line table
+ /// parsing can stop when a matching LineEntry has been fouhnd, and the
+ /// InlineInfo can stop parsing early once a match has been found and also
+ /// skip information that doesn't match. This avoids memory allocations and
+ /// is much faster for lookups.
+ ///
+ /// \param Addr A virtual address from the orignal object file to lookup.
+ /// \returns An expected LookupResult that contains only the information
+ /// needed for the current address, or an error object that indicates reason
+ /// for failing to lookup the address.
+ llvm::Expected<LookupResult> lookup(uint64_t Addr) const;
+
+ /// Get a string from the string table.
+ ///
+ /// \param Offset The string table offset for the string to retrieve.
+ /// \returns The string from the strin table.
+ StringRef getString(uint32_t Offset) const { return StrTab[Offset]; }
+
+ /// Get the a file entry for the suppplied file index.
+ ///
+ /// Used to convert any file indexes in the FunctionInfo data back into
+ /// files. This function can be used for iteration, but is more commonly used
+ /// for random access when doing lookups.
+ ///
+ /// \param Index An index into the file table.
+ /// \returns An optional FileInfo that will be valid if the file index is
+ /// valid, or llvm::None if the file index is out of bounds,
+ Optional<FileEntry> getFile(uint32_t Index) const {
+ if (Index < Files.size())
+ return Files[Index];
+ return llvm::None;
+ }
+
+ /// Dump the entire Gsym data contained in this object.
+ ///
+ /// \param OS The output stream to dump to.
+ void dump(raw_ostream &OS);
+
+ /// Dump a FunctionInfo object.
+ ///
+ /// This function will convert any string table indexes and file indexes
+ /// into human readable format.
+ ///
+ /// \param OS The output stream to dump to.
+ ///
+ /// \param FI The object to dump.
+ void dump(raw_ostream &OS, const FunctionInfo &FI);
+
+ /// Dump a LineTable object.
+ ///
+ /// This function will convert any string table indexes and file indexes
+ /// into human readable format.
+ ///
+ ///
+ /// \param OS The output stream to dump to.
+ ///
+ /// \param LT The object to dump.
+ void dump(raw_ostream &OS, const LineTable <);
+
+ /// Dump a InlineInfo object.
+ ///
+ /// This function will convert any string table indexes and file indexes
+ /// into human readable format.
+ ///
+ /// \param OS The output stream to dump to.
+ ///
+ /// \param II The object to dump.
+ ///
+ /// \param Indent The indentation as number of spaces. Used for recurive
+ /// dumping.
+ void dump(raw_ostream &OS, const InlineInfo &II, uint32_t Indent = 0);
+
+ /// Dump a FileEntry object.
+ ///
+ /// This function will convert any string table indexes into human readable
+ /// format.
+ ///
+ /// \param OS The output stream to dump to.
+ ///
+ /// \param FE The object to dump.
+ void dump(raw_ostream &OS, Optional<FileEntry> FE);
+
+ /// Get the number of addresses in this Gsym file.
+ uint32_t getNumAddresses() const {
+ return Hdr->NumAddresses;
+ }
+
+ /// Gets an address from the address table.
+ ///
+ /// Addresses are stored as offsets frrom the gsym::Header::BaseAddress.
+ ///
+ /// \param Index A index into the address table.
+ /// \returns A resolved virtual address for adddress in the address table
+ /// or llvm::None if Index is out of bounds.
+ Optional<uint64_t> getAddress(size_t Index) const;
+
+protected:
+
+ /// Get an appropriate address info offsets array.
+ ///
+ /// The address table in the GSYM file is stored as array of 1, 2, 4 or 8
+ /// byte offsets from the The gsym::Header::BaseAddress. The table is stored
+ /// internally as a array of bytes that are in the correct endianness. When
+ /// we access this table we must get an array that matches those sizes. This
+ /// templatized helper function is used when accessing address offsets in the
+ /// AddrOffsets member variable.
+ ///
+ /// \returns An ArrayRef of an appropriate address offset size.
+ template <class T> ArrayRef<T>
+ getAddrOffsets() const {
+ return ArrayRef<T>(reinterpret_cast<const T *>(AddrOffsets.data()),
+ AddrOffsets.size()/sizeof(T));
+ }
+
+ /// Get an appropriate address from the address table.
+ ///
+ /// The address table in the GSYM file is stored as array of 1, 2, 4 or 8
+ /// byte address offsets from the The gsym::Header::BaseAddress. The table is
+ /// stored internally as a array of bytes that are in the correct endianness.
+ /// In order to extract an address from the address table we must access the
+ /// address offset using the correct size and then add it to the BaseAddress
+ /// in the header.
+ ///
+ /// \param Index An index into the AddrOffsets array.
+ /// \returns An virtual address that matches the original object file for the
+ /// address as the specified index, or llvm::None if Index is out of bounds.
+ template <class T> Optional<uint64_t>
+ addressForIndex(size_t Index) const {
+ ArrayRef<T> AIO = getAddrOffsets<T>();
+ if (Index < AIO.size())
+ return AIO[Index] + Hdr->BaseAddress;
+ return llvm::None;
+ }
+ /// Lookup an address offset in the AddrOffsets table.
+ ///
+ /// Given an address offset, look it up using a binary search of the
+ /// AddrOffsets table.
+ ///
+ /// \param AddrOffset An address offset, that has already been computed by
+ /// subtracting the gsym::Header::BaseAddress.
+ /// \returns The matching address offset index. This index will be used to
+ /// extract the FunctionInfo data's offset from the AddrInfoOffsets array.
+ template <class T>
+ llvm::Optional<uint64_t> getAddressOffsetIndex(const uint64_t AddrOffset) const {
+ ArrayRef<T> AIO = getAddrOffsets<T>();
+ const auto Begin = AIO.begin();
+ const auto End = AIO.end();
+ auto Iter = std::lower_bound(Begin, End, AddrOffset);
+ // Watch for addresses that fall between the gsym::Header::BaseAddress and
+ // the first address offset.
+ if (Iter == Begin && AddrOffset < *Begin)
+ return llvm::None;
+ if (Iter == End || AddrOffset < *Iter)
+ --Iter;
+ return std::distance(Begin, Iter);
+ }
+
+ /// Create a GSYM from a memory buffer.
+ ///
+ /// Called by both openFile() and copyBuffer(), this function does all of the
+ /// work of parsing the GSYM file and returning an error.
+ ///
+ /// \param MemBuffer A memory buffer that will transfer ownership into the
+ /// GsymReader.
+ /// \returns An expected GsymReader that contains the object or an error
+ /// object that indicates reason for failing to read the GSYM.
+ static llvm::Expected<llvm::gsym::GsymReader>
+ create(std::unique_ptr<MemoryBuffer> &MemBuffer);
+
+
+ /// Given an address, find the address index.
+ ///
+ /// Binary search the address table and find the matching address index.
+ ///
+ /// \param Addr A virtual address that matches the original object file
+ /// to lookup.
+ /// \returns An index into the address table. This index can be used to
+ /// extract the FunctionInfo data's offset from the AddrInfoOffsets array.
+ /// Returns an error if the address isn't in the GSYM with details of why.
+ Expected<uint64_t> getAddressIndex(const uint64_t Addr) const;
+
+ /// Given an address index, get the offset for the FunctionInfo.
+ ///
+ /// Looking up an address is done by finding the corresponding address
+ /// index for the address. This index is then used to get the offset of the
+ /// FunctionInfo data that we will decode using this function.
+ ///
+ /// \param Index An index into the address table.
+ /// \returns An optional GSYM data offset for the offset of the FunctionInfo
+ /// that needs to be decoded.
+ Optional<uint64_t> getAddressInfoOffset(size_t Index) const;
+};
+
+} // namespace gsym
+} // namespace llvm
+
+#endif // #ifndef LLVM_DEBUGINFO_GSYM_GSYMREADER_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/Header.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/Header.h
new file mode 100644
index 0000000..6652c59
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/Header.h
@@ -0,0 +1,129 @@
+//===- Header.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_GSYM_HEADER_H
+#define LLVM_DEBUGINFO_GSYM_HEADER_H
+
+#include "llvm/Support/Error.h"
+
+#include <cstddef>
+#include <cstdint>
+
+namespace llvm {
+class raw_ostream;
+class DataExtractor;
+
+namespace gsym {
+class FileWriter;
+
+constexpr uint32_t GSYM_MAGIC = 0x4753594d; // 'GSYM'
+constexpr uint32_t GSYM_CIGAM = 0x4d595347; // 'MYSG'
+constexpr uint32_t GSYM_VERSION = 1;
+constexpr size_t GSYM_MAX_UUID_SIZE = 20;
+
+/// The GSYM header.
+///
+/// The GSYM header is found at the start of a stand alone GSYM file, or as
+/// the first bytes in a section when GSYM is contained in a section of an
+/// executable file (ELF, mach-o, COFF).
+///
+/// The structure is encoded exactly as it appears in the structure definition
+/// with no gaps between members. Alignment should not change from system to
+/// system as the members were laid out so that they shouldn't align
+/// differently on different architectures.
+///
+/// When endianness of the system loading a GSYM file matches, the file can
+/// be mmap'ed in and a pointer to the header can be cast to the first bytes
+/// of the file (stand alone GSYM file) or section data (GSYM in a section).
+/// When endianness is swapped, the Header::decode() function should be used to
+/// decode the header.
+struct Header {
+ /// The magic bytes should be set to GSYM_MAGIC. This helps detect if a file
+ /// is a GSYM file by scanning the first 4 bytes of a file or section.
+ /// This value might appear byte swapped
+ uint32_t Magic;
+ /// The version can number determines how the header is decoded and how each
+ /// InfoType in FunctionInfo is encoded/decoded. As version numbers increase,
+ /// "Magic" and "Version" members should always appear at offset zero and 4
+ /// respectively to ensure clients figure out if they can parse the format.
+ uint16_t Version;
+ /// The size in bytes of each address offset in the address offsets table.
+ uint8_t AddrOffSize;
+ /// The size in bytes of the UUID encoded in the "UUID" member.
+ uint8_t UUIDSize;
+ /// The 64 bit base address that all address offsets in the address offsets
+ /// table are relative to. Storing a full 64 bit address allows our address
+ /// offsets table to be smaller on disk.
+ uint64_t BaseAddress;
+ /// The number of addresses stored in the address offsets table.
+ uint32_t NumAddresses;
+ /// The file relative offset of the start of the string table for strings
+ /// contained in the GSYM file. If the GSYM in contained in a stand alone
+ /// file this will be the file offset of the start of the string table. If
+ /// the GSYM is contained in a section within an executable file, this can
+ /// be the offset of the first string used in the GSYM file and can possibly
+ /// span one or more executable string tables. This allows the strings to
+ /// share string tables in an ELF or mach-o file.
+ uint32_t StrtabOffset;
+ /// The size in bytes of the string table. For a stand alone GSYM file, this
+ /// will be the exact size in bytes of the string table. When the GSYM data
+ /// is in a section within an executable file, this size can span one or more
+ /// sections that contains strings. This allows any strings that are already
+ /// stored in the executable file to be re-used, and any extra strings could
+ /// be added to another string table and the string table offset and size
+ /// can be set to span all needed string tables.
+ uint32_t StrtabSize;
+ /// The UUID of the original executable file. This is stored to allow
+ /// matching a GSYM file to an executable file when symbolication is
+ /// required. Only the first "UUIDSize" bytes of the UUID are valid. Any
+ /// bytes in the UUID value that appear after the first UUIDSize bytes should
+ /// be set to zero.
+ uint8_t UUID[GSYM_MAX_UUID_SIZE];
+
+ /// Check if a header is valid and return an error if anything is wrong.
+ ///
+ /// This function can be used prior to encoding a header to ensure it is
+ /// valid, or after decoding a header to ensure it is valid and supported.
+ ///
+ /// Check a correctly byte swapped header for errors:
+ /// - check magic value
+ /// - check that version number is supported
+ /// - check that the address offset size is supported
+ /// - check that the UUID size is valid
+ ///
+ /// \returns An error if anything is wrong in the header, or Error::success()
+ /// if there are no errors.
+ llvm::Error checkForError() const;
+
+ /// Decode an object from a binary data stream.
+ ///
+ /// \param Data The binary stream to read the data from. This object must
+ /// have the data for the object starting at offset zero. The data
+ /// can contain more data than needed.
+ ///
+ /// \returns A Header or an error describing the issue that was
+ /// encountered during decoding.
+ static llvm::Expected<Header> decode(DataExtractor &Data);
+
+ /// Encode this object into FileWriter stream.
+ ///
+ /// \param O The binary stream to write the data to at the current file
+ /// position.
+ ///
+ /// \returns An error object that indicates success or failure of the
+ /// encoding process.
+ llvm::Error encode(FileWriter &O) const;
+};
+
+bool operator==(const Header &LHS, const Header &RHS);
+raw_ostream &operator<<(raw_ostream &OS, const llvm::gsym::Header &H);
+
+} // namespace gsym
+} // namespace llvm
+
+#endif // #ifndef LLVM_DEBUGINFO_GSYM_HEADER_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/InlineInfo.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/InlineInfo.h
index 2224306..06126da 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/GSYM/InlineInfo.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/InlineInfo.h
@@ -1,9 +1,8 @@
//===- InlineInfo.h ---------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
@@ -11,7 +10,10 @@
#define LLVM_DEBUGINFO_GSYM_INLINEINFO_H
#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/GSYM/LineEntry.h"
+#include "llvm/DebugInfo/GSYM/LookupResult.h"
#include "llvm/DebugInfo/GSYM/Range.h"
+#include "llvm/Support/Error.h"
#include <stdint.h>
#include <vector>
@@ -21,6 +23,7 @@
namespace gsym {
+class GsymReader;
/// Inline information stores the name of the inline function along with
/// an array of address ranges. It also stores the call file and call line
/// that called this inline function. This allows us to unwind inline call
@@ -31,6 +34,30 @@
/// Any clients that encode information will need to ensure the ranges are
/// all contined correctly or lookups could fail. Add ranges in these objects
/// must be contained in the top level FunctionInfo address ranges as well.
+///
+/// ENCODING
+///
+/// When saved to disk, the inline info encodes all ranges to be relative to
+/// a parent address range. This will be the FunctionInfo's start address if
+/// the InlineInfo is directly contained in a FunctionInfo, or a the start
+/// address of the containing parent InlineInfo's first "Ranges" member. This
+/// allows address ranges to be efficiently encoded using ULEB128 encodings as
+/// we encode the offset and size of each range instead of full addresses. This
+/// also makes any encoded addresses easy to relocate as we just need to
+/// relocate the FunctionInfo's start address.
+///
+/// - The AddressRanges member "Ranges" is encoded using an appropriate base
+/// address as described above.
+/// - UINT8 boolean value that specifies if the InlineInfo object has children.
+/// - UINT32 string table offset that points to the name of the inline
+/// function.
+/// - ULEB128 integer that specifies the file of the call site that called
+/// this function.
+/// - ULEB128 integer that specifies the source line of the call site that
+/// called this function.
+/// - if this object has children, enocode each child InlineInfo using the
+/// the first address range's start address as the base address.
+///
struct InlineInfo {
uint32_t Name; ///< String table offset in the string table.
@@ -50,6 +77,52 @@
using InlineArray = std::vector<const InlineInfo *>;
+ /// Lookup a single address within the inline info data.
+ ///
+ /// Clients have the option to decode an entire InlineInfo object (using
+ /// InlineInfo::decode() ) or just find the matching inline info using this
+ /// function. The benefit of using this function is that only the information
+ /// needed for the lookup will be extracted, other info can be skipped and
+ /// parsing can stop as soon as the deepest match is found. This allows
+ /// symbolication tools to be fast and efficient and avoid allocation costs
+ /// when doing lookups.
+ ///
+ /// This function will augment the SourceLocations array \a SrcLocs with any
+ /// inline information that pertains to \a Addr. If no inline information
+ /// exists for \a Addr, then \a SrcLocs will be left untouched. If there is
+ /// inline information for \a Addr, then \a SrcLocs will be modifiied to
+ /// contain the deepest most inline function's SourceLocation at index zero
+ /// in the array and proceed up the the concrete function source file and
+ /// line at the end of the array.
+ ///
+ /// \param GR The GSYM reader that contains the string and file table that
+ /// will be used to fill in the source locations.
+ ///
+ /// \param Data The binary stream to read the data from. This object must
+ /// have the data for the LineTable object starting at offset zero. The data
+ /// can contain more data than needed.
+ ///
+ /// \param BaseAddr The base address to use when decoding the line table.
+ /// This will be the FunctionInfo's start address and will be used to
+ /// decode the correct addresses for the inline information.
+ ///
+ /// \param Addr The address to lookup.
+ ///
+ /// \param SrcLocs The inline source locations that matches \a Addr. This
+ /// array must be initialized with the matching line entry
+ /// from the line table upon entry. The name of the concrete
+ /// function must be supplied since it will get pushed to
+ /// the last SourceLocation entry and the inline information
+ /// will fill in the source file and line from the inline
+ /// information.
+ ///
+ /// \returns An error if the inline information is corrupt, or
+ /// Error::success() for all other cases, even when no information
+ /// is added to \a SrcLocs.
+ static llvm::Error lookup(const GsymReader &GR, DataExtractor &Data,
+ uint64_t BaseAddr, uint64_t Addr,
+ SourceLocations &SrcLocs);
+
/// Lookup an address in the InlineInfo object
///
/// This function is used to symbolicate an inline call stack and can
@@ -62,6 +135,37 @@
/// \returns optional vector of InlineInfo objects that describe the
/// inline call stack for a given address, false otherwise.
llvm::Optional<InlineArray> getInlineStack(uint64_t Addr) const;
+
+ /// Decode an InlineInfo object from a binary data stream.
+ ///
+ /// \param Data The binary stream to read the data from. This object must
+ /// have the data for the InlineInfo object starting at offset zero. The data
+ /// can contain more data than needed.
+ ///
+ /// \param BaseAddr The base address to use when decoding all address ranges.
+ /// This will be the FunctionInfo's start address if this object is directly
+ /// contained in a FunctionInfo object, or the start address of the first
+ /// address range in an InlineInfo object of this object is a child of
+ /// another InlineInfo object.
+ /// \returns An InlineInfo or an error describing the issue that was
+ /// encountered during decoding.
+ static llvm::Expected<InlineInfo> decode(DataExtractor &Data,
+ uint64_t BaseAddr);
+
+ /// Encode this InlineInfo object into FileWriter stream.
+ ///
+ /// \param O The binary stream to write the data to at the current file
+ /// position.
+ ///
+ /// \param BaseAddr The base address to use when encoding all address ranges.
+ /// This will be the FunctionInfo's start address if this object is directly
+ /// contained in a FunctionInfo object, or the start address of the first
+ /// address range in an InlineInfo object of this object is a child of
+ /// another InlineInfo object.
+ ///
+ /// \returns An error object that indicates success or failure or the
+ /// encoding process.
+ llvm::Error encode(FileWriter &O, uint64_t BaseAddr) const;
};
inline bool operator==(const InlineInfo &LHS, const InlineInfo &RHS) {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/LineEntry.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/LineEntry.h
index 6b93809..aac7c48 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/GSYM/LineEntry.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/LineEntry.h
@@ -1,9 +1,8 @@
//===- LineEntry.h ----------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/LineTable.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/LineTable.h
new file mode 100644
index 0000000..fba9b2c
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/LineTable.h
@@ -0,0 +1,233 @@
+//===- LineTable.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_GSYM_LINETABLE_H
+#define LLVM_DEBUGINFO_GSYM_LINETABLE_H
+
+#include "llvm/DebugInfo/GSYM/LineEntry.h"
+#include "llvm/Support/Error.h"
+#include <cstdint>
+#include <vector>
+
+namespace llvm {
+namespace gsym {
+
+struct FunctionInfo;
+class FileWriter;
+
+/// LineTable class contains deserialized versions of line tables for each
+/// function's address ranges.
+///
+/// When saved to disk, the line table is encoded using a modified version of
+/// the DWARF line tables that only tracks address to source file and line.
+///
+/// ENCODING
+///
+/// The line table starts with a small prolog that contains the following
+/// values:
+///
+/// ENCODING NAME DESCRIPTION
+/// ======== =========== ====================================================
+/// SLEB MinDelta The min line delta for special opcodes that advance
+/// the address and line number.
+/// SLEB MaxDelta The max line delta for single byte opcodes that
+/// advance the address and line number.
+/// ULEB FirstLine The value of the first source line number to
+/// initialize the LineEntry with.
+///
+/// Once these prolog items are read, we initialize a LineEntry struct with
+/// the start address of the function from the FunctionInfo's address range,
+/// a default file index of 1, and the line number set to "FirstLine" from
+/// the prolog above:
+///
+/// LineEntry Row(BaseAddr, 1, FirstLine);
+///
+/// The line table state machine is now initialized and ready to be parsed.
+/// The stream that follows this encodes the line entries in a compact
+/// form. Some opcodes cause "Row" to be modified and some opcodes may also
+/// push "Row" onto the end of the "LineTable.Lines" vector. The end result
+/// is a vector of LineEntry structs that is sorted in ascending address
+/// order.
+///
+/// NORMAL OPCODES
+///
+/// The opcodes 0 through 3 are normal in opcodes. Their encoding and
+/// descriptions are listed below:
+///
+/// ENCODING ENUMERATION VALUE DESCRIPTION
+/// ======== ================ ===== ========================================
+/// LTOC_EndSequence 0x00 Parsing is done.
+/// ULEB LTOC_SetFile 0x01 Row.File = ULEB
+/// ULEB LTOC_AdvancePC 0x02 Row.Addr += ULEB, push "Row".
+/// SLEB LTOC_AdvanceLine 0x03 Row.Line += SLEB
+/// LTOC_FirstSpecial 0x04 First special opcode (see SPECIAL
+/// OPCODES below).
+///
+/// SPECIAL OPCODES
+///
+/// Opcodes LTOC_FirstSpecial through 255 are special opcodes that always
+/// increment both the Row.Addr and Row.Line and push "Row" onto the
+/// LineEntry.Lines array. They do this by using some of the bits to
+/// increment/decrement the source line number, and some of the bits to
+/// increment the address. Line numbers can go up or down when making line
+/// tables, where addresses always only increase since line tables are sorted
+/// by address.
+///
+/// In order to calculate the amount to increment the line and address for
+/// these special opcodes, we calculate the number of values reserved for the
+/// line increment/decrement using the "MinDelta" and "MaxDelta" from the
+/// prolog:
+///
+/// const int64_t LineRange = MaxDelta - MinDelta + 1;
+///
+/// Then we can adjust the opcode to not include any of the normal opcodes:
+///
+/// const uint8_t AdjustedOp = Opcode - LTOC_FirstSpecial;
+///
+/// And we can calculate the line offset, and address offset:
+///
+/// const int64_t LineDelta = MinDelta + (AdjustedOp % LineRange);
+/// const uint64_t AddrDelta = (AdjustedOp / LineRange);
+///
+/// And use these to modify our "Row":
+///
+/// Row.Line += LineDelta;
+/// Row.Addr += AddrDelta;
+///
+/// And push a row onto the line table:
+///
+/// Lines.push_back(Row);
+///
+/// This is verify similar to the way that DWARF encodes its line tables. The
+/// only difference is the DWARF line tables have more normal opcodes and the
+/// "Row" contains more members, like source column number, bools for end of
+/// prologue, beginnging of epilogue, is statement and many others. There are
+/// also more complex rules that happen for the extra normal opcodes. By
+/// leaving these extra opcodes out, we leave more bits for the special
+/// opcodes that allows us to encode line tables in fewer bytes than standard
+/// DWARF encodings.
+///
+/// Opcodes that will push "Row" onto the LineEntry.Lines include the
+/// LTOC_AdvancePC opcode and all special opcodes. All other opcodes
+/// only modify the current "Row", or cause the line table to end.
+class LineTable {
+ typedef std::vector<gsym::LineEntry> Collection;
+ Collection Lines; ///< All line entries in the line table.
+public:
+ /// Lookup a single address within a line table's data.
+ ///
+ /// Clients have the option to decode an entire line table using
+ /// LineTable::decode() or just find a single matching entry using this
+ /// function. The benefit of using this function is that parsed LineEntry
+ /// objects that do not match will not be stored in an array. This will avoid
+ /// memory allocation costs and parsing can stop once a match has been found.
+ ///
+ /// \param Data The binary stream to read the data from. This object must
+ /// have the data for the LineTable object starting at offset zero. The data
+ /// can contain more data than needed.
+ ///
+ /// \param BaseAddr The base address to use when decoding the line table.
+ /// This will be the FunctionInfo's start address and will be used to
+ /// initialize the line table row prior to parsing any opcodes.
+ ///
+ /// \returns An LineEntry object if a match is found, error otherwise.
+ static Expected<LineEntry> lookup(DataExtractor &Data, uint64_t BaseAddr,
+ uint64_t Addr);
+
+ /// Decode an LineTable object from a binary data stream.
+ ///
+ /// \param Data The binary stream to read the data from. This object must
+ /// have the data for the LineTable object starting at offset zero. The data
+ /// can contain more data than needed.
+ ///
+ /// \param BaseAddr The base address to use when decoding the line table.
+ /// This will be the FunctionInfo's start address and will be used to
+ /// initialize the line table row prior to parsing any opcodes.
+ ///
+ /// \returns An LineTable or an error describing the issue that was
+ /// encountered during decoding.
+ static llvm::Expected<LineTable> decode(DataExtractor &Data,
+ uint64_t BaseAddr);
+ /// Encode this LineTable object into FileWriter stream.
+ ///
+ /// \param O The binary stream to write the data to at the current file
+ /// position.
+ ///
+ /// \param BaseAddr The base address to use when decoding the line table.
+ /// This will be the FunctionInfo's start address.
+ ///
+ /// \returns An error object that indicates success or failure or the
+ /// encoding process.
+ llvm::Error encode(FileWriter &O, uint64_t BaseAddr) const;
+ bool empty() const { return Lines.empty(); }
+ void clear() { Lines.clear(); }
+ /// Return the first line entry if the line table isn't empty.
+ ///
+ /// \returns An optional line entry with the first line entry if the line
+ /// table isn't empty, or llvm::None if the line table is emtpy.
+ Optional<LineEntry> first() const {
+ if (Lines.empty())
+ return llvm::None;
+ return Lines.front();
+ }
+ /// Return the last line entry if the line table isn't empty.
+ ///
+ /// \returns An optional line entry with the last line entry if the line
+ /// table isn't empty, or llvm::None if the line table is emtpy.
+ Optional<LineEntry> last() const {
+ if (Lines.empty())
+ return llvm::None;
+ return Lines.back();
+ }
+ void push(const LineEntry &LE) {
+ Lines.push_back(LE);
+ }
+ size_t isValid() const {
+ return !Lines.empty();
+ }
+ size_t size() const {
+ return Lines.size();
+ }
+ LineEntry &get(size_t i) {
+ assert(i < Lines.size());
+ return Lines[i];
+ }
+ const LineEntry &get(size_t i) const {
+ assert(i < Lines.size());
+ return Lines[i];
+ }
+ LineEntry &operator[](size_t i) {
+ return get(i);
+ }
+ const LineEntry &operator[](size_t i) const {
+ return get(i);
+ }
+ bool operator==(const LineTable &RHS) const {
+ return Lines == RHS.Lines;
+ }
+ bool operator!=(const LineTable &RHS) const {
+ return Lines != RHS.Lines;
+ }
+ bool operator<(const LineTable &RHS) const {
+ const auto LHSSize = Lines.size();
+ const auto RHSSize = RHS.Lines.size();
+ if (LHSSize == RHSSize)
+ return Lines < RHS.Lines;
+ return LHSSize < RHSSize;
+ }
+ Collection::const_iterator begin() const { return Lines.begin(); }
+ Collection::const_iterator end() const { return Lines.end(); }
+
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const gsym::LineTable <);
+
+} // namespace gsym
+} // namespace llvm
+
+#endif // #ifndef LLVM_DEBUGINFO_GSYM_LINETABLE_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/LookupResult.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/LookupResult.h
new file mode 100644
index 0000000..693a02c
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/LookupResult.h
@@ -0,0 +1,63 @@
+//===- LookupResult.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_GSYM_LOOKUPRESULT_H
+#define LLVM_DEBUGINFO_GSYM_LOOKUPRESULT_H
+
+#include "llvm/DebugInfo/GSYM/Range.h"
+#include "llvm/ADT/StringRef.h"
+#include <inttypes.h>
+#include <vector>
+
+namespace llvm {
+class raw_ostream;
+namespace gsym {
+struct FileEntry;
+
+struct SourceLocation {
+ StringRef Name; ///< Function or symbol name.
+ StringRef Dir; ///< Line entry source file directory path.
+ StringRef Base; ///< Line entry source file basename.
+ uint32_t Line = 0; ///< Source file line number.
+ uint32_t Offset = 0; ///< Byte size offset within the named function.
+};
+
+inline bool operator==(const SourceLocation &LHS, const SourceLocation &RHS) {
+ return LHS.Name == RHS.Name && LHS.Dir == RHS.Dir &&
+ LHS.Base == RHS.Base && LHS.Line == RHS.Line &&
+ LHS.Offset == RHS.Offset;
+}
+
+raw_ostream &operator<<(raw_ostream &OS, const SourceLocation &R);
+
+using SourceLocations = std::vector<SourceLocation>;
+
+
+struct LookupResult {
+ uint64_t LookupAddr = 0; ///< The address that this lookup pertains to.
+ AddressRange FuncRange; ///< The concrete function address range.
+ StringRef FuncName; ///< The concrete function name that contains LookupAddr.
+ /// The source locations that match this address. This information will only
+ /// be filled in if the FunctionInfo contains a line table. If an address is
+ /// for a concrete function with no inlined functions, this array will have
+ /// one entry. If an address points to an inline function, there will be one
+ /// SourceLocation for each inlined function with the last entry pointing to
+ /// the concrete function itself. This allows one address to generate
+ /// multiple locations and allows unwinding of inline call stacks. The
+ /// deepest inline function will appear at index zero in the source locations
+ /// array, and the concrete function will appear at the end of the array.
+ SourceLocations Locations;
+ std::string getSourceFile(uint32_t Index) const;
+};
+
+raw_ostream &operator<<(raw_ostream &OS, const LookupResult &R);
+
+} // namespace gsym
+} // namespace llvm
+
+#endif // #ifndef LLVM_DEBUGINFO_GSYM_LOOKUPRESULT_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/ObjectFileTransformer.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/ObjectFileTransformer.h
new file mode 100644
index 0000000..84a8d98
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/ObjectFileTransformer.h
@@ -0,0 +1,51 @@
+//===- ObjectFileTransformer.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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_GSYM_OBJECTFILETRANSFORMER_H
+#define LLVM_DEBUGINFO_GSYM_OBJECTFILETRANSFORMER_H
+
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+
+class raw_ostream;
+
+namespace object {
+class ObjectFile;
+}
+
+namespace gsym {
+
+struct CUInfo;
+class GsymCreator;
+
+class ObjectFileTransformer {
+public:
+ /// Extract any object file data that is needed by the GsymCreator.
+ ///
+ /// The extracted information includes the UUID of the binary and converting
+ /// all function symbols from any symbol tables into FunctionInfo objects.
+ ///
+ /// \param Obj The object file that contains the DWARF debug info.
+ ///
+ /// \param Log The stream to log warnings and non fatal issues to.
+ ///
+ /// \param Gsym The GSYM creator to populate with the function information
+ /// from the debug info.
+ ///
+ /// \returns An error indicating any fatal issues that happen when parsing
+ /// the DWARF, or Error::success() if all goes well.
+ static llvm::Error convert(const object::ObjectFile &Obj,
+ raw_ostream &Log,
+ GsymCreator &Gsym);
+};
+
+} // namespace gsym
+} // namespace llvm
+
+#endif // #ifndef LLVM_DEBUGINFO_GSYM_OBJECTFILETRANSFORMER_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/Range.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/Range.h
index 772ff24..b3e7692 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/GSYM/Range.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/Range.h
@@ -1,15 +1,15 @@
-//===- AddressRange.h -------------------------------------------*- C++ -*-===//
+//===- Range.h --------------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_DEBUGINFO_GSYM_RANGE_H
#define LLVM_DEBUGINFO_GSYM_RANGE_H
+#include "llvm/ADT/Optional.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/raw_ostream.h"
#include <stdint.h>
@@ -21,10 +21,13 @@
#define HEX64(v) llvm::format_hex(v, 18)
namespace llvm {
+class DataExtractor;
class raw_ostream;
namespace gsym {
+class FileWriter;
+
/// A class that represents an address range. The range is specified using
/// a start and an end address.
struct AddressRange {
@@ -47,6 +50,26 @@
bool operator<(const AddressRange &R) const {
return std::make_pair(Start, End) < std::make_pair(R.Start, R.End);
}
+ /// AddressRange objects are encoded and decoded to be relative to a base
+ /// address. This will be the FunctionInfo's start address if the AddressRange
+ /// is directly contained in a FunctionInfo, or a base address of the
+ /// containing parent AddressRange or AddressRanges. This allows address
+ /// ranges to be efficiently encoded using ULEB128 encodings as we encode the
+ /// offset and size of each range instead of full addresses. This also makes
+ /// encoded addresses easy to relocate as we just need to relocate one base
+ /// address.
+ /// @{
+ void decode(DataExtractor &Data, uint64_t BaseAddr, uint64_t &Offset);
+ void encode(FileWriter &O, uint64_t BaseAddr) const;
+ /// @}
+
+ /// Skip an address range object in the specified data a the specified
+ /// offset.
+ ///
+ /// \param Data The binary stream to read the data from.
+ ///
+ /// \param Offset The byte offset within \a Data.
+ static void skip(DataExtractor &Data, uint64_t &Offset);
};
raw_ostream &operator<<(raw_ostream &OS, const AddressRange &R);
@@ -66,6 +89,8 @@
void clear() { Ranges.clear(); }
bool empty() const { return Ranges.empty(); }
bool contains(uint64_t Addr) const;
+ bool contains(AddressRange Range) const;
+ Optional<AddressRange> getRangeThatContains(uint64_t Addr) const;
void insert(AddressRange Range);
size_t size() const { return Ranges.size(); }
bool operator==(const AddressRanges &RHS) const {
@@ -77,6 +102,24 @@
}
Collection::const_iterator begin() const { return Ranges.begin(); }
Collection::const_iterator end() const { return Ranges.end(); }
+
+ /// Address ranges are decoded and encoded to be relative to a base address.
+ /// See the AddressRange comment for the encode and decode methods for full
+ /// details.
+ /// @{
+ void decode(DataExtractor &Data, uint64_t BaseAddr, uint64_t &Offset);
+ void encode(FileWriter &O, uint64_t BaseAddr) const;
+ /// @}
+
+ /// Skip an address range object in the specified data a the specified
+ /// offset.
+ ///
+ /// \param Data The binary stream to read the data from.
+ ///
+ /// \param Offset The byte offset within \a Data.
+ ///
+ /// \returns The number of address ranges that were skipped.
+ static uint64_t skip(DataExtractor &Data, uint64_t &Offset);
};
raw_ostream &operator<<(raw_ostream &OS, const AddressRanges &AR);
diff --git a/linux-x64/clang/include/llvm/DebugInfo/GSYM/StringTable.h b/linux-x64/clang/include/llvm/DebugInfo/GSYM/StringTable.h
index 0001b8b..a96ae58 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/GSYM/StringTable.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/GSYM/StringTable.h
@@ -1,9 +1,8 @@
//===- StringTable.h --------------------------------------------*- C++ -*-===//
//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
+// 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
//
//===----------------------------------------------------------------------===//
diff --git a/linux-x64/clang/include/llvm/DebugInfo/MSF/MappedBlockStream.h b/linux-x64/clang/include/llvm/DebugInfo/MSF/MappedBlockStream.h
index 593d781..473c89e 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/MSF/MappedBlockStream.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/MSF/MappedBlockStream.h
@@ -24,8 +24,6 @@
namespace llvm {
namespace msf {
-struct MSFLayout;
-
/// MappedBlockStream represents data stored in an MSF file into chunks of a
/// particular size (called the Block Size), and whose chunks may not be
/// necessarily contiguous. The arrangement of these chunks MSF the file
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h
index 8be06f8..67963a0 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/DIA/DIAInjectedSource.h
@@ -25,7 +25,7 @@
std::string getFileName() const override;
std::string getObjectFileName() const override;
std::string getVirtualFileName() const override;
- PDB_SourceCompression getCompression() const override;
+ uint32_t getCompression() const override;
std::string getCode() const override;
private:
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/DIA/DIASession.h
index 6f62e60..09ab9e2 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/DIA/DIASession.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/DIA/DIASession.h
@@ -38,13 +38,13 @@
bool addressForRVA(uint32_t RVA, uint32_t &Section,
uint32_t &Offset) const override;
- std::unique_ptr<PDBSymbol>
- findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
+ std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
+ PDB_SymType Type) override;
std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
- PDB_SymType Type) const override;
- std::unique_ptr<PDBSymbol>
- findSymbolBySectOffset(uint32_t Section, uint32_t Offset,
- PDB_SymType Type) const override;
+ PDB_SymType Type) override;
+ std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Section,
+ uint32_t Offset,
+ PDB_SymType Type) override;
std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland &Compiland,
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/GenericError.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/GenericError.h
index ec85d92..1ef9b36 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/GenericError.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/GenericError.h
@@ -9,7 +9,6 @@
#ifndef LLVM_DEBUGINFO_PDB_ERROR_H
#define LLVM_DEBUGINFO_PDB_ERROR_H
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
namespace llvm {
@@ -20,7 +19,7 @@
dia_sdk_not_present,
dia_failed_loading,
signature_out_of_date,
- external_cmdline_ref,
+ no_matching_pch,
unspecified,
};
} // namespace pdb
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h
index 56e85d1..6ee6c7c 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBInjectedSource.h
@@ -9,16 +9,11 @@
#ifndef LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H
#define LLVM_DEBUGINFO_PDB_IPDBINJECTEDSOURCE_H
-#include "PDBTypes.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
+#include <cstdint>
#include <string>
namespace llvm {
-class raw_ostream;
-
namespace pdb {
-
/// IPDBInjectedSource defines an interface used to represent source files
/// which were injected directly into the PDB file during the compilation
/// process. This is used, for example, to add natvis files to a PDB, but
@@ -32,7 +27,10 @@
virtual std::string getFileName() const = 0;
virtual std::string getObjectFileName() const = 0;
virtual std::string getVirtualFileName() const = 0;
- virtual PDB_SourceCompression getCompression() const = 0;
+ // The returned value depends on the PDB producer,
+ // but 0 is guaranteed to mean "no compression".
+ // The enum PDB_SourceCompression lists known return values.
+ virtual uint32_t getCompression() const = 0;
virtual std::string getCode() const = 0;
};
} // namespace pdb
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBLineNumber.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBLineNumber.h
index 77e8899..47b6397 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBLineNumber.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBLineNumber.h
@@ -9,7 +9,7 @@
#ifndef LLVM_DEBUGINFO_PDB_IPDBLINENUMBER_H
#define LLVM_DEBUGINFO_PDB_IPDBLINENUMBER_H
-#include "PDBTypes.h"
+#include <cstdint>
namespace llvm {
namespace pdb {
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
index b24e712..f59e933 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
@@ -12,19 +12,15 @@
#include "PDBTypes.h"
#include "llvm/ADT/BitmaskEnum.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include <memory>
namespace llvm {
class raw_ostream;
+class StringRef;
namespace pdb {
-class IPDBSession;
-class PDBSymbolTypeVTable;
-class PDBSymbolTypeVTableShape;
-
enum class PdbSymbolIdField : uint32_t {
None = 0,
SymIndexId = 1 << 0,
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBSession.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBSession.h
index aa8d9c7..7e38654 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBSession.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/IPDBSession.h
@@ -42,13 +42,12 @@
return unique_dyn_cast_or_null<T>(getSymbolById(SymbolId));
}
+ virtual std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
+ PDB_SymType Type) = 0;
+ virtual std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
+ PDB_SymType Type) = 0;
virtual std::unique_ptr<PDBSymbol>
- findSymbolByAddress(uint64_t Address, PDB_SymType Type) const = 0;
- virtual std::unique_ptr<PDBSymbol>
- findSymbolByRVA(uint32_t RVA, PDB_SymType Type) const = 0;
- virtual std::unique_ptr<PDBSymbol>
- findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
- PDB_SymType Type) const = 0;
+ findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type) = 0;
virtual std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland &Compiland,
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
index 568f0c9..7b7337f 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptor.h
@@ -25,9 +25,9 @@
friend class DbiStreamBuilder;
public:
- DbiModuleDescriptor();
- DbiModuleDescriptor(const DbiModuleDescriptor &Info);
- ~DbiModuleDescriptor();
+ DbiModuleDescriptor() = default;
+ DbiModuleDescriptor(const DbiModuleDescriptor &Info) = default;
+ DbiModuleDescriptor &operator=(const DbiModuleDescriptor &Info) = default;
static Error initialize(BinaryStreamRef Stream, DbiModuleDescriptor &Info);
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
index 4f5d28b..82b63d7 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h
@@ -34,6 +34,34 @@
}
namespace pdb {
+// Represents merged or unmerged symbols. Merged symbols can be written to the
+// output file as is, but unmerged symbols must be rewritten first. In either
+// case, the size must be known up front.
+struct SymbolListWrapper {
+ explicit SymbolListWrapper(ArrayRef<uint8_t> Syms)
+ : SymPtr(const_cast<uint8_t *>(Syms.data())), SymSize(Syms.size()),
+ NeedsToBeMerged(false) {}
+ explicit SymbolListWrapper(void *SymSrc, uint32_t Length)
+ : SymPtr(SymSrc), SymSize(Length), NeedsToBeMerged(true) {}
+
+ ArrayRef<uint8_t> asArray() const {
+ return ArrayRef<uint8_t>(static_cast<const uint8_t *>(SymPtr), SymSize);
+ }
+
+ uint32_t size() const { return SymSize; }
+
+ void *SymPtr = nullptr;
+ uint32_t SymSize = 0;
+ bool NeedsToBeMerged = false;
+};
+
+/// Represents a string table reference at some offset in the module symbol
+/// stream.
+struct StringTableFixup {
+ uint32_t StrTabOffset = 0;
+ uint32_t SymOffsetOfReference = 0;
+};
+
class DbiModuleDescriptorBuilder {
friend class DbiStreamBuilder;
@@ -48,10 +76,28 @@
void setPdbFilePathNI(uint32_t NI);
void setObjFileName(StringRef Name);
+
+ // Callback to merge one source of unmerged symbols.
+ using MergeSymbolsCallback = Error (*)(void *Ctx, void *Symbols,
+ BinaryStreamWriter &Writer);
+
+ void setMergeSymbolsCallback(void *Ctx, MergeSymbolsCallback Callback) {
+ MergeSymsCtx = Ctx;
+ MergeSymsCallback = Callback;
+ }
+
+ void setStringTableFixups(std::vector<StringTableFixup> &&Fixups) {
+ StringTableFixups = std::move(Fixups);
+ }
+
void setFirstSectionContrib(const SectionContrib &SC);
void addSymbol(codeview::CVSymbol Symbol);
void addSymbolsInBulk(ArrayRef<uint8_t> BulkSymbols);
+ // Add symbols of known size which will be merged (rewritten) when committing
+ // the PDB to disk.
+ void addUnmergedSymbols(void *SymSrc, uint32_t SymLength);
+
void
addDebugSubsection(std::shared_ptr<codeview::DebugSubsection> Subsection);
@@ -77,8 +123,14 @@
void finalize();
Error finalizeMsfLayout();
- Error commit(BinaryStreamWriter &ModiWriter, const msf::MSFLayout &MsfLayout,
- WritableBinaryStreamRef MsfBuffer);
+ /// Commit the DBI descriptor to the DBI stream.
+ Error commit(BinaryStreamWriter &ModiWriter);
+
+ /// Commit the accumulated symbols to the module symbol stream. Safe to call
+ /// in parallel on different DbiModuleDescriptorBuilder objects. Only modifies
+ /// the pre-allocated stream in question.
+ Error commitSymbolStream(const msf::MSFLayout &MsfLayout,
+ WritableBinaryStreamRef MsfBuffer);
private:
uint32_t calculateC13DebugInfoSize() const;
@@ -91,10 +143,14 @@
std::string ModuleName;
std::string ObjFileName;
std::vector<std::string> SourceFiles;
- std::vector<ArrayRef<uint8_t>> Symbols;
+ std::vector<SymbolListWrapper> Symbols;
- std::vector<std::unique_ptr<codeview::DebugSubsectionRecordBuilder>>
- C13Builders;
+ void *MergeSymsCtx = nullptr;
+ MergeSymbolsCallback MergeSymsCallback = nullptr;
+
+ std::vector<StringTableFixup> StringTableFixups;
+
+ std::vector<codeview::DebugSubsectionRecordBuilder> C13Builders;
ModuleInfoHeader Layout;
};
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
index 1422327..5fb13ad 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiModuleList.h
@@ -39,6 +39,7 @@
DbiModuleSourceFilesIterator(const DbiModuleList &Modules, uint32_t Modi,
uint16_t Filei);
DbiModuleSourceFilesIterator() = default;
+ DbiModuleSourceFilesIterator(const DbiModuleSourceFilesIterator &R) = default;
DbiModuleSourceFilesIterator &
operator=(const DbiModuleSourceFilesIterator &R) = default;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
index d9be238..24664c3 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
@@ -57,7 +57,6 @@
void setFlags(uint16_t F);
void setMachineType(PDB_Machine M);
void setMachineType(COFF::MachineTypes M);
- void setSectionMap(ArrayRef<SecMapEntry> SecMap);
// Add given bytes as a new stream.
Error addDbgStream(pdb::DbgHeaderType Type, ArrayRef<uint8_t> Data);
@@ -84,9 +83,8 @@
SectionContribs.emplace_back(SC);
}
- // A helper function to create a Section Map from a COFF section header.
- static std::vector<SecMapEntry>
- createSectionMap(ArrayRef<llvm::object::coff_section> SecHdrs);
+ // Populate the Section Map from COFF section headers.
+ void createSectionMap(ArrayRef<llvm::object::coff_section> SecHdrs);
private:
struct DebugStream {
@@ -133,7 +131,7 @@
WritableBinaryStreamRef NamesBuffer;
MutableBinaryByteStream FileInfoBuffer;
std::vector<SectionContrib> SectionContribs;
- ArrayRef<SecMapEntry> SectionMap;
+ std::vector<SecMapEntry> SectionMap;
std::array<Optional<DebugStream>, (int)DbgHeaderType::Max> DbgStreams;
};
}
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h
index a497956..378d4cd 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h
@@ -9,6 +9,7 @@
#ifndef LLVM_DEBUGINFO_PDB_RAW_GSISTREAMBUILDER_H
#define LLVM_DEBUGINFO_PDB_RAW_GSISTREAMBUILDER_H
+#include "llvm/ADT/DenseSet.h"
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
@@ -37,6 +38,8 @@
} // namespace msf
namespace pdb {
struct GSIHashStreamBuilder;
+struct BulkPublic;
+struct SymbolDenseMapInfo;
class GSIStreamBuilder {
@@ -51,29 +54,94 @@
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer);
- uint32_t getPublicsStreamIndex() const;
- uint32_t getGlobalsStreamIndex() const;
- uint32_t getRecordStreamIdx() const { return RecordStreamIdx; }
+ uint32_t getPublicsStreamIndex() const { return PublicsStreamIndex; }
+ uint32_t getGlobalsStreamIndex() const { return GlobalsStreamIndex; }
+ uint32_t getRecordStreamIndex() const { return RecordStreamIndex; }
- void addPublicSymbol(const codeview::PublicSym32 &Pub);
+ // Add public symbols in bulk.
+ void addPublicSymbols(std::vector<BulkPublic> &&PublicsIn);
void addGlobalSymbol(const codeview::ProcRefSym &Sym);
void addGlobalSymbol(const codeview::DataSym &Sym);
void addGlobalSymbol(const codeview::ConstantSym &Sym);
+
+ // Add a pre-serialized global symbol record. The caller must ensure that the
+ // symbol data remains alive until the global stream is committed to disk.
void addGlobalSymbol(const codeview::CVSymbol &Sym);
private:
+ void finalizePublicBuckets();
+ void finalizeGlobalBuckets(uint32_t RecordZeroOffset);
+
+ template <typename T> void serializeAndAddGlobal(const T &Symbol);
+
uint32_t calculatePublicsHashStreamSize() const;
uint32_t calculateGlobalsHashStreamSize() const;
Error commitSymbolRecordStream(WritableBinaryStreamRef Stream);
Error commitPublicsHashStream(WritableBinaryStreamRef Stream);
Error commitGlobalsHashStream(WritableBinaryStreamRef Stream);
- uint32_t RecordStreamIdx = kInvalidStreamIndex;
+ uint32_t PublicsStreamIndex = kInvalidStreamIndex;
+ uint32_t GlobalsStreamIndex = kInvalidStreamIndex;
+ uint32_t RecordStreamIndex = kInvalidStreamIndex;
msf::MSFBuilder &Msf;
std::unique_ptr<GSIHashStreamBuilder> PSH;
std::unique_ptr<GSIHashStreamBuilder> GSH;
+
+ // List of all of the public records. These are stored unserialized so that we
+ // can defer copying the names until we are ready to commit the PDB.
+ std::vector<BulkPublic> Publics;
+
+ // List of all of the global records.
+ std::vector<codeview::CVSymbol> Globals;
+
+ // Hash table for deduplicating global typedef and constant records. Only used
+ // for globals.
+ llvm::DenseSet<codeview::CVSymbol, SymbolDenseMapInfo> GlobalsSeen;
};
+
+/// This struct is equivalent to codeview::PublicSym32, but it has been
+/// optimized for size to speed up bulk serialization and sorting operations
+/// during PDB writing.
+struct BulkPublic {
+ BulkPublic() : Flags(0), BucketIdx(0) {}
+
+ const char *Name = nullptr;
+ uint32_t NameLen = 0;
+
+ // Offset of the symbol record in the publics stream.
+ uint32_t SymOffset = 0;
+
+ // Section offset of the symbol in the image.
+ uint32_t Offset = 0;
+
+ // Section index of the section containing the symbol.
+ uint16_t Segment = 0;
+
+ // PublicSymFlags.
+ uint16_t Flags : 4;
+
+ // GSI hash table bucket index. The maximum value is IPHR_HASH.
+ uint16_t BucketIdx : 12;
+ static_assert(IPHR_HASH <= 1 << 12, "bitfield too small");
+
+ void setFlags(codeview::PublicSymFlags F) {
+ Flags = uint32_t(F);
+ assert(Flags == uint32_t(F) && "truncated");
+ }
+
+ void setBucketIdx(uint16_t B) {
+ assert(B < IPHR_HASH);
+ BucketIdx = B;
+ }
+
+ StringRef getName() const { return StringRef(Name, NameLen); }
+};
+
+static_assert(sizeof(BulkPublic) <= 24, "unexpected size increase");
+static_assert(std::is_trivially_copyable<BulkPublic>::value,
+ "should be trivial");
+
} // namespace pdb
} // namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/HashTable.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/HashTable.h
index 86c43a4..95c0a89 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/HashTable.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/HashTable.h
@@ -31,21 +31,21 @@
Error readSparseBitVector(BinaryStreamReader &Stream, SparseBitVector<> &V);
Error writeSparseBitVector(BinaryStreamWriter &Writer, SparseBitVector<> &Vec);
-template <typename ValueT, typename TraitsT> class HashTable;
+template <typename ValueT> class HashTable;
-template <typename ValueT, typename TraitsT>
+template <typename ValueT>
class HashTableIterator
- : public iterator_facade_base<HashTableIterator<ValueT, TraitsT>,
+ : public iterator_facade_base<HashTableIterator<ValueT>,
std::forward_iterator_tag,
- std::pair<uint32_t, ValueT>> {
- friend HashTable<ValueT, TraitsT>;
+ const std::pair<uint32_t, ValueT>> {
+ friend HashTable<ValueT>;
- HashTableIterator(const HashTable<ValueT, TraitsT> &Map, uint32_t Index,
+ HashTableIterator(const HashTable<ValueT> &Map, uint32_t Index,
bool IsEnd)
: Map(&Map), Index(Index), IsEnd(IsEnd) {}
public:
- HashTableIterator(const HashTable<ValueT, TraitsT> &Map) : Map(&Map) {
+ HashTableIterator(const HashTable<ValueT> &Map) : Map(&Map) {
int I = Map.Present.find_first();
if (I == -1) {
Index = 0;
@@ -56,6 +56,7 @@
}
}
+ HashTableIterator(const HashTableIterator &R) = default;
HashTableIterator &operator=(const HashTableIterator &R) {
Map = R.Map;
return *this;
@@ -72,6 +73,12 @@
assert(Map->Present.test(Index));
return Map->Buckets[Index];
}
+
+ // Implement postfix op++ in terms of prefix op++ by using the superclass
+ // implementation.
+ using iterator_facade_base<HashTableIterator<ValueT>,
+ std::forward_iterator_tag,
+ const std::pair<uint32_t, ValueT>>::operator++;
HashTableIterator &operator++() {
while (Index < Map->Buckets.size()) {
++Index;
@@ -87,24 +94,13 @@
bool isEnd() const { return IsEnd; }
uint32_t index() const { return Index; }
- const HashTable<ValueT, TraitsT> *Map;
+ const HashTable<ValueT> *Map;
uint32_t Index;
bool IsEnd;
};
-template <typename T> struct PdbHashTraits {};
-
-template <> struct PdbHashTraits<uint32_t> {
- uint32_t hashLookupKey(uint32_t N) const { return N; }
- uint32_t storageKeyToLookupKey(uint32_t N) const { return N; }
- uint32_t lookupKeyToStorageKey(uint32_t N) { return N; }
-};
-
-template <typename ValueT, typename TraitsT = PdbHashTraits<ValueT>>
+template <typename ValueT>
class HashTable {
- using iterator = HashTableIterator<ValueT, TraitsT>;
- friend iterator;
-
struct Header {
support::ulittle32_t Size;
support::ulittle32_t Capacity;
@@ -113,10 +109,11 @@
using BucketList = std::vector<std::pair<uint32_t, ValueT>>;
public:
- HashTable() { Buckets.resize(8); }
+ using const_iterator = HashTableIterator<ValueT>;
+ friend const_iterator;
- explicit HashTable(TraitsT Traits) : HashTable(8, std::move(Traits)) {}
- HashTable(uint32_t Capacity, TraitsT Traits) : Traits(Traits) {
+ HashTable() { Buckets.resize(8); }
+ explicit HashTable(uint32_t Capacity) {
Buckets.resize(Capacity);
}
@@ -216,19 +213,20 @@
uint32_t capacity() const { return Buckets.size(); }
uint32_t size() const { return Present.count(); }
- iterator begin() const { return iterator(*this); }
- iterator end() const { return iterator(*this, 0, true); }
+ const_iterator begin() const { return const_iterator(*this); }
+ const_iterator end() const { return const_iterator(*this, 0, true); }
/// Find the entry whose key has the specified hash value, using the specified
/// traits defining hash function and equality.
- template <typename Key> iterator find_as(const Key &K) const {
+ template <typename Key, typename TraitsT>
+ const_iterator find_as(const Key &K, TraitsT &Traits) const {
uint32_t H = Traits.hashLookupKey(K) % capacity();
uint32_t I = H;
Optional<uint32_t> FirstUnused;
do {
if (isPresent(I)) {
if (Traits.storageKeyToLookupKey(Buckets[I].first) == K)
- return iterator(*this, I, false);
+ return const_iterator(*this, I, false);
} else {
if (!FirstUnused)
FirstUnused = I;
@@ -247,17 +245,19 @@
// table were Present. But this would violate the load factor constraints
// that we impose, so it should never happen.
assert(FirstUnused);
- return iterator(*this, *FirstUnused, true);
+ return const_iterator(*this, *FirstUnused, true);
}
/// Set the entry using a key type that the specified Traits can convert
/// from a real key to an internal key.
- template <typename Key> bool set_as(const Key &K, ValueT V) {
- return set_as_internal(K, std::move(V), None);
+ template <typename Key, typename TraitsT>
+ bool set_as(const Key &K, ValueT V, TraitsT &Traits) {
+ return set_as_internal(K, std::move(V), Traits, None);
}
- template <typename Key> ValueT get(const Key &K) const {
- auto Iter = find_as(K);
+ template <typename Key, typename TraitsT>
+ ValueT get(const Key &K, TraitsT &Traits) const {
+ auto Iter = find_as(K, Traits);
assert(Iter != end());
return (*Iter).second;
}
@@ -266,7 +266,6 @@
bool isPresent(uint32_t K) const { return Present.test(K); }
bool isDeleted(uint32_t K) const { return Deleted.test(K); }
- TraitsT Traits;
BucketList Buckets;
mutable SparseBitVector<> Present;
mutable SparseBitVector<> Deleted;
@@ -274,9 +273,10 @@
private:
/// Set the entry using a key type that the specified Traits can convert
/// from a real key to an internal key.
- template <typename Key>
- bool set_as_internal(const Key &K, ValueT V, Optional<uint32_t> InternalKey) {
- auto Entry = find_as(K);
+ template <typename Key, typename TraitsT>
+ bool set_as_internal(const Key &K, ValueT V, TraitsT &Traits,
+ Optional<uint32_t> InternalKey) {
+ auto Entry = find_as(K, Traits);
if (Entry != end()) {
assert(isPresent(Entry.index()));
assert(Traits.storageKeyToLookupKey(Buckets[Entry.index()].first) == K);
@@ -293,15 +293,16 @@
Present.set(Entry.index());
Deleted.reset(Entry.index());
- grow();
+ grow(Traits);
- assert((find_as(K)) != end());
+ assert((find_as(K, Traits)) != end());
return true;
}
static uint32_t maxLoad(uint32_t capacity) { return capacity * 2 / 3 + 1; }
- void grow() {
+ template <typename TraitsT>
+ void grow(TraitsT &Traits) {
uint32_t S = size();
uint32_t MaxLoad = maxLoad(capacity());
if (S < maxLoad(capacity()))
@@ -313,10 +314,11 @@
// Growing requires rebuilding the table and re-hashing every item. Make a
// copy with a larger capacity, insert everything into the copy, then swap
// it in.
- HashTable NewMap(NewCapacity, Traits);
+ HashTable NewMap(NewCapacity);
for (auto I : Present) {
auto LookupKey = Traits.storageKeyToLookupKey(Buckets[I].first);
- NewMap.set_as_internal(LookupKey, Buckets[I].second, Buckets[I].first);
+ NewMap.set_as_internal(LookupKey, Buckets[I].second, Traits,
+ Buckets[I].first);
}
Buckets.swap(NewMap.Buckets);
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/InjectedSourceStream.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/InjectedSourceStream.h
new file mode 100644
index 0000000..d0cac37
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/InjectedSourceStream.h
@@ -0,0 +1,44 @@
+//===- InjectedSourceStream.h - PDB Headerblock Stream Access ---*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBINJECTEDSOURCESTREAM_H
+#define LLVM_DEBUGINFO_PDB_RAW_PDBINJECTEDSOURCESTREAM_H
+
+#include "llvm/DebugInfo/PDB/Native/HashTable.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace msf {
+class MappedBlockStream;
+}
+namespace pdb {
+class PDBFile;
+class PDBStringTable;
+
+class InjectedSourceStream {
+public:
+ InjectedSourceStream(std::unique_ptr<msf::MappedBlockStream> Stream);
+ Error reload(const PDBStringTable &Strings);
+
+ using const_iterator = HashTable<SrcHeaderBlockEntry>::const_iterator;
+ const_iterator begin() const { return InjectedSourceTable.begin(); }
+ const_iterator end() const { return InjectedSourceTable.end(); }
+
+ uint32_t size() const { return InjectedSourceTable.size(); }
+
+private:
+ std::unique_ptr<msf::MappedBlockStream> Stream;
+
+ const SrcHeaderBlockHeader* Header;
+ HashTable<SrcHeaderBlockEntry> InjectedSourceTable;
+};
+}
+}
+
+#endif
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
index c49d796..1df059f 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NamedStreamMap.h
@@ -59,7 +59,7 @@
NamedStreamMapTraits HashTraits;
/// Closed hash table from Offset -> StreamNumber, where Offset is the offset
/// of the stream name in NamesBuffer.
- HashTable<support::ulittle32_t, NamedStreamMapTraits> OffsetIndexMap;
+ HashTable<support::ulittle32_t> OffsetIndexMap;
/// Buffer of string data.
std::vector<char> NamesBuffer;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h
new file mode 100644
index 0000000..ca1e22b
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeEnumInjectedSources.h
@@ -0,0 +1,43 @@
+//==- NativeEnumInjectedSources.cpp - Native Injected Source Enumerator --*-==//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMINJECTEDSOURCES_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMINJECTEDSOURCES_H
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBInjectedSource.h"
+#include "llvm/DebugInfo/PDB/Native/InjectedSourceStream.h"
+
+namespace llvm {
+namespace pdb {
+
+class InjectedSourceStream;
+class PDBStringTable;
+
+class NativeEnumInjectedSources : public IPDBEnumChildren<IPDBInjectedSource> {
+public:
+ NativeEnumInjectedSources(PDBFile &File, const InjectedSourceStream &IJS,
+ const PDBStringTable &Strings);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<IPDBInjectedSource>
+ getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<IPDBInjectedSource> getNext() override;
+ void reset() override;
+
+private:
+ PDBFile &File;
+ const InjectedSourceStream &Stream;
+ const PDBStringTable &Strings;
+ InjectedSourceStream::const_iterator Cur;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h
new file mode 100644
index 0000000..32a4515
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeEnumLineNumbers.h
@@ -0,0 +1,39 @@
+//==- NativeEnumLineNumbers.h - Native Line Number Enumerator ------------*-==//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMLINENUMBERS_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMLINENUMBERS_H
+
+#include "llvm/DebugInfo/CodeView/DebugLinesSubsection.h"
+#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
+#include "llvm/DebugInfo/CodeView/StringsAndChecksums.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/Native/NativeLineNumber.h"
+
+namespace llvm {
+namespace pdb {
+class IPDBLineNumber;
+
+class NativeEnumLineNumbers : public IPDBEnumChildren<IPDBLineNumber> {
+public:
+ explicit NativeEnumLineNumbers(std::vector<NativeLineNumber> LineNums);
+
+ uint32_t getChildCount() const override;
+ ChildTypePtr getChildAtIndex(uint32_t Index) const override;
+ ChildTypePtr getNext() override;
+ void reset() override;
+
+private:
+ std::vector<NativeLineNumber> Lines;
+ uint32_t Index;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
new file mode 100644
index 0000000..480b3fb
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbols.h
@@ -0,0 +1,41 @@
+//==- NativeEnumSymbols.h - Native Symbols Enumerator impl -------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOLS_H
+
+#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include <vector>
+
+namespace llvm {
+namespace pdb {
+
+class NativeSession;
+
+class NativeEnumSymbols : public IPDBEnumChildren<PDBSymbol> {
+public:
+ NativeEnumSymbols(NativeSession &Session, std::vector<SymIndexId> Symbols);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+
+private:
+ std::vector<SymIndexId> Symbols;
+ uint32_t Index;
+ NativeSession &Session;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
new file mode 100644
index 0000000..b219055
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeFunctionSymbol.h
@@ -0,0 +1,47 @@
+//===- NativeFunctionSymbol.h - info about function symbols -----*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEFUNCTIONSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEFUNCTIONSYMBOL_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeFunctionSymbol : public NativeRawSymbol {
+public:
+ NativeFunctionSymbol(NativeSession &Session, SymIndexId Id,
+ const codeview::ProcSym &Sym, uint32_t RecordOffset);
+
+ ~NativeFunctionSymbol() override;
+
+ void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const override;
+
+ uint32_t getAddressOffset() const override;
+ uint32_t getAddressSection() const override;
+ std::string getName() const override;
+ uint64_t getLength() const override;
+ uint32_t getRelativeVirtualAddress() const override;
+ uint64_t getVirtualAddress() const override;
+ std::unique_ptr<IPDBEnumSymbols>
+ findInlineFramesByVA(uint64_t VA) const override;
+
+protected:
+ const codeview::ProcSym Sym;
+ uint32_t RecordOffset = 0;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEFUNCTIONSYMBOL_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
new file mode 100644
index 0000000..2f6aba0
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeInlineSiteSymbol.h
@@ -0,0 +1,46 @@
+//===- NativeInlineSiteSymbol.h - info about inline sites -------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeInlineSiteSymbol : public NativeRawSymbol {
+public:
+ NativeInlineSiteSymbol(NativeSession &Session, SymIndexId Id,
+ const codeview::InlineSiteSym &Sym,
+ uint64_t ParentAddr);
+
+ ~NativeInlineSiteSymbol() override;
+
+ void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const override;
+
+ std::string getName() const override;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByVA(uint64_t VA, uint32_t Length) const override;
+
+private:
+ const codeview::InlineSiteSym Sym;
+ uint64_t ParentAddr;
+
+ void getLineOffset(uint32_t OffsetInFunc, uint32_t &LineOffset,
+ uint32_t &FileOffset) const;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEINLINESITESYMBOL_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h
new file mode 100644
index 0000000..5dedc70
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeLineNumber.h
@@ -0,0 +1,52 @@
+//===- NativeLineNumber.h - Native line number implementation ---*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVELINENUMBER_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVELINENUMBER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+class NativeLineNumber : public IPDBLineNumber {
+public:
+ explicit NativeLineNumber(const NativeSession &Session,
+ const codeview::LineInfo Line,
+ uint32_t ColumnNumber, uint32_t Length,
+ uint32_t Section, uint32_t Offset,
+ uint32_t SrcFileId, uint32_t CompilandId);
+
+ uint32_t getLineNumber() const override;
+ uint32_t getLineNumberEnd() const override;
+ uint32_t getColumnNumber() const override;
+ uint32_t getColumnNumberEnd() const override;
+ uint32_t getAddressSection() const override;
+ uint32_t getAddressOffset() const override;
+ uint32_t getRelativeVirtualAddress() const override;
+ uint64_t getVirtualAddress() const override;
+ uint32_t getLength() const override;
+ uint32_t getSourceFileId() const override;
+ uint32_t getCompilandId() const override;
+ bool isStatement() const override;
+
+private:
+ const NativeSession &Session;
+ const codeview::LineInfo Line;
+ uint32_t ColumnNumber;
+ uint32_t Section;
+ uint32_t Offset;
+ uint32_t Length;
+ uint32_t SrcFileId;
+ uint32_t CompilandId;
+};
+} // namespace pdb
+} // namespace llvm
+#endif
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h
new file mode 100644
index 0000000..9f410e2
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativePublicSymbol.h
@@ -0,0 +1,43 @@
+//===- NativePublicSymbol.h - info about public symbols ---------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEPUBLICSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEPUBLICSYMBOL_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativePublicSymbol : public NativeRawSymbol {
+public:
+ NativePublicSymbol(NativeSession &Session, SymIndexId Id,
+ const codeview::PublicSym32 &Sym);
+
+ ~NativePublicSymbol() override;
+
+ void dump(raw_ostream &OS, int Indent, PdbSymbolIdField ShowIdFields,
+ PdbSymbolIdField RecurseIdFields) const override;
+
+ uint32_t getAddressOffset() const override;
+ uint32_t getAddressSection() const override;
+ std::string getName() const override;
+ uint32_t getRelativeVirtualAddress() const override;
+ uint64_t getVirtualAddress() const override;
+
+protected:
+ const codeview::PublicSym32 Sym;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEPUBLICSYMBOL_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeSession.h
index ee7d8cd..5f8fc58 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeSession.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeSession.h
@@ -26,6 +26,11 @@
class NativeExeSymbol;
class NativeSession : public IPDBSession {
+ struct PdbSearchOptions {
+ StringRef ExePath;
+ // FIXME: Add other PDB search options (_NT_SYMBOL_PATH, symsrv)
+ };
+
public:
NativeSession(std::unique_ptr<PDBFile> PdbFile,
std::unique_ptr<BumpPtrAllocator> Allocator);
@@ -33,8 +38,11 @@
static Error createFromPdb(std::unique_ptr<MemoryBuffer> MB,
std::unique_ptr<IPDBSession> &Session);
+ static Error createFromPdbPath(StringRef PdbPath,
+ std::unique_ptr<IPDBSession> &Session);
static Error createFromExe(StringRef Path,
std::unique_ptr<IPDBSession> &Session);
+ static Expected<std::string> searchForPdb(const PdbSearchOptions &Opts);
uint64_t getLoadAddress() const override;
bool setLoadAddress(uint64_t Address) override;
@@ -46,13 +54,13 @@
bool addressForRVA(uint32_t RVA, uint32_t &Section,
uint32_t &Offset) const override;
- std::unique_ptr<PDBSymbol>
- findSymbolByAddress(uint64_t Address, PDB_SymType Type) const override;
+ std::unique_ptr<PDBSymbol> findSymbolByAddress(uint64_t Address,
+ PDB_SymType Type) override;
std::unique_ptr<PDBSymbol> findSymbolByRVA(uint32_t RVA,
- PDB_SymType Type) const override;
- std::unique_ptr<PDBSymbol>
- findSymbolBySectOffset(uint32_t Sect, uint32_t Offset,
- PDB_SymType Type) const override;
+ PDB_SymType Type) override;
+ std::unique_ptr<PDBSymbol> findSymbolBySectOffset(uint32_t Sect,
+ uint32_t Offset,
+ PDB_SymType Type) override;
std::unique_ptr<IPDBEnumLineNumbers>
findLineNumbers(const PDBSymbolCompiland &Compiland,
@@ -100,15 +108,29 @@
NativeExeSymbol &getNativeGlobalScope() const;
SymbolCache &getSymbolCache() { return Cache; }
const SymbolCache &getSymbolCache() const { return Cache; }
+ uint32_t getRVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
+ uint64_t getVAFromSectOffset(uint32_t Section, uint32_t Offset) const;
+ bool moduleIndexForVA(uint64_t VA, uint16_t &ModuleIndex) const;
+ bool moduleIndexForSectOffset(uint32_t Sect, uint32_t Offset,
+ uint16_t &ModuleIndex) const;
+ Expected<ModuleDebugStreamRef> getModuleDebugStream(uint32_t Index) const;
private:
void initializeExeSymbol();
+ void parseSectionContribs();
std::unique_ptr<PDBFile> Pdb;
std::unique_ptr<BumpPtrAllocator> Allocator;
SymbolCache Cache;
SymIndexId ExeSymbol = 0;
+ uint64_t LoadAddress = 0;
+
+ /// Map from virtual address to module index.
+ using IMap =
+ IntervalMap<uint64_t, uint16_t, 8, IntervalMapHalfOpenInfo<uint64_t>>;
+ IMap::Allocator IMapAllocator;
+ IMap AddrToModuleIndex;
};
} // namespace pdb
} // namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeSourceFile.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeSourceFile.h
new file mode 100644
index 0000000..eb6336f
--- /dev/null
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeSourceFile.h
@@ -0,0 +1,40 @@
+//===- NativeSourceFile.h - Native source file implementation ---*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVESOURCEFILE_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVESOURCEFILE_H
+
+#include "llvm/DebugInfo/CodeView/DebugChecksumsSubsection.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
+#include "llvm/DebugInfo/PDB/Native/PDBStringTable.h"
+
+namespace llvm {
+namespace pdb {
+class NativeSession;
+
+class NativeSourceFile : public IPDBSourceFile {
+public:
+ explicit NativeSourceFile(NativeSession &Session, uint32_t FileId,
+ const codeview::FileChecksumEntry &Checksum);
+
+ std::string getFileName() const override;
+ uint32_t getUniqueId() const override;
+ std::string getChecksum() const override;
+ PDB_Checksum getChecksumType() const override;
+ std::unique_ptr<IPDBEnumChildren<PDBSymbolCompiland>>
+ getCompilands() const override;
+
+private:
+ NativeSession &Session;
+ uint32_t FileId;
+ const codeview::FileChecksumEntry Checksum;
+};
+} // namespace pdb
+} // namespace llvm
+#endif
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h
index a7ea287..358ddf5 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeFunctionSig.h
@@ -70,4 +70,4 @@
} // namespace pdb
} // namespace llvm
-#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
\ No newline at end of file
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h
index 446f77d..7a3dfae 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypePointer.h
@@ -57,4 +57,4 @@
} // namespace pdb
} // namespace llvm
-#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
\ No newline at end of file
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h
index fe8a6f7..e7fb41b 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeTypedef.h
@@ -38,4 +38,4 @@
} // namespace pdb
} // namespace llvm
-#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
\ No newline at end of file
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEPOINTER_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h
index 8f4dee3..e1b31a2 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeUDT.h
@@ -70,4 +70,4 @@
} // namespace pdb
} // namespace llvm
-#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H
\ No newline at end of file
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEUDT_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h
index 4ec0f9b..4ae8f14 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/NativeTypeVTShape.h
@@ -42,4 +42,4 @@
} // namespace pdb
} // namespace llvm
-#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEVTSHAPE_H
\ No newline at end of file
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVETYPEVTSHAPE_H
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/PDBFile.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/PDBFile.h
index cb9bd07..56de403 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/PDBFile.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/PDBFile.h
@@ -32,6 +32,7 @@
class DbiStream;
class GlobalsStream;
class InfoStream;
+class InjectedSourceStream;
class PDBStringTable;
class PDBFileBuilder;
class PublicsStream;
@@ -83,7 +84,12 @@
ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
- std::unique_ptr<msf::MappedBlockStream> createIndexedStream(uint16_t SN);
+ std::unique_ptr<msf::MappedBlockStream>
+ createIndexedStream(uint16_t SN) const;
+ Expected<std::unique_ptr<msf::MappedBlockStream>>
+ safelyCreateIndexedStream(uint32_t StreamIndex) const;
+ Expected<std::unique_ptr<msf::MappedBlockStream>>
+ safelyCreateNamedStream(StringRef Name);
msf::MSFStreamLayout getStreamLayout(uint32_t StreamIdx) const;
msf::MSFStreamLayout getFpmStreamLayout() const;
@@ -99,6 +105,7 @@
Expected<PublicsStream &> getPDBPublicsStream();
Expected<SymbolStream &> getPDBSymbolStream();
Expected<PDBStringTable &> getStringTable();
+ Expected<InjectedSourceStream &> getInjectedSourceStream();
BumpPtrAllocator &getAllocator() { return Allocator; }
@@ -110,15 +117,11 @@
bool hasPDBSymbolStream();
bool hasPDBTpiStream() const;
bool hasPDBStringTable();
+ bool hasPDBInjectedSourceStream();
uint32_t getPointerSize();
private:
- Expected<std::unique_ptr<msf::MappedBlockStream>>
- safelyCreateIndexedStream(const msf::MSFLayout &Layout,
- BinaryStreamRef MsfData,
- uint32_t StreamIndex) const;
-
std::string FilePath;
BumpPtrAllocator &Allocator;
@@ -135,6 +138,7 @@
std::unique_ptr<SymbolStream> Symbols;
std::unique_ptr<msf::MappedBlockStream> DirectoryStream;
std::unique_ptr<msf::MappedBlockStream> StringTableStream;
+ std::unique_ptr<InjectedSourceStream> InjectedSources;
std::unique_ptr<PDBStringTable> Strings;
};
}
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
index 72000bd..87ba049 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
@@ -80,7 +80,6 @@
Error finalizeMsfLayout();
Expected<uint32_t> allocateNamedStream(StringRef Name, uint32_t Size);
- void commitFpm(WritableBinaryStream &MsfBuffer, const msf::MSFLayout &Layout);
void commitInjectedSources(WritableBinaryStream &MsfBuffer,
const msf::MSFLayout &Layout);
void commitSrcHeaderBlock(WritableBinaryStream &MsfBuffer,
@@ -97,7 +96,7 @@
PDBStringTableBuilder Strings;
StringTableHashTraits InjectedSourceHashTraits;
- HashTable<SrcHeaderBlockEntry, StringTableHashTraits> InjectedSourceTable;
+ HashTable<SrcHeaderBlockEntry> InjectedSourceTable;
SmallVector<InjectedSourceDescriptor, 2> InjectedSources;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/SymbolCache.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
index 0b15ab4..1ff6ca1 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/SymbolCache.h
@@ -10,11 +10,15 @@
#define LLVM_DEBUGINFO_PDB_NATIVE_SYMBOLCACHE_H
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/IntervalMap.h"
+#include "llvm/DebugInfo/CodeView/Line.h"
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeIndex.h"
#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/PDB/Native/ModuleDebugStream.h"
#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
-#include "llvm/Support/Allocator.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSourceFile.h"
#include <memory>
#include <vector>
@@ -33,26 +37,53 @@
/// an Id. Id allocation is an implementation, with the only guarantee
/// being that once an Id is allocated, the symbol can be assumed to be
/// cached.
- std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
+ mutable std::vector<std::unique_ptr<NativeRawSymbol>> Cache;
/// For type records from the TPI stream which have been paresd and cached,
/// stores a mapping to SymIndexId of the cached symbol.
- DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
+ mutable DenseMap<codeview::TypeIndex, SymIndexId> TypeIndexToSymbolId;
/// For field list members which have been parsed and cached, stores a mapping
/// from (IndexOfClass, MemberIndex) to the corresponding SymIndexId of the
/// cached symbol.
- DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
+ mutable DenseMap<std::pair<codeview::TypeIndex, uint32_t>, SymIndexId>
FieldListMembersToSymbolId;
/// List of SymIndexIds for each compiland, indexed by compiland index as they
/// appear in the PDB file.
- std::vector<SymIndexId> Compilands;
+ mutable std::vector<SymIndexId> Compilands;
+
+ /// List of source files, indexed by unique source file index.
+ mutable std::vector<std::unique_ptr<NativeSourceFile>> SourceFiles;
+
+ /// Map from string table offset to source file Id.
+ mutable DenseMap<uint32_t, SymIndexId> FileNameOffsetToId;
/// Map from global symbol offset to SymIndexId.
- DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
+ mutable DenseMap<uint32_t, SymIndexId> GlobalOffsetToSymbolId;
- SymIndexId createSymbolPlaceholder() {
+ /// Map from segment and code offset to function symbols.
+ mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId> AddressToSymbolId;
+ /// Map from segment and code offset to public symbols.
+ mutable DenseMap<std::pair<uint32_t, uint32_t>, SymIndexId>
+ AddressToPublicSymId;
+
+ /// Map from module index and symbol table offset to SymIndexId.
+ mutable DenseMap<std::pair<uint16_t, uint32_t>, SymIndexId>
+ SymTabOffsetToSymbolId;
+
+ struct LineTableEntry {
+ uint64_t Addr;
+ codeview::LineInfo Line;
+ uint32_t ColumnNumber;
+ uint32_t FileNameIndex;
+ bool IsTerminalEntry;
+ };
+
+ std::vector<LineTableEntry> findLineTable(uint16_t Modi) const;
+ mutable DenseMap<uint16_t, std::vector<LineTableEntry>> LineTable;
+
+ SymIndexId createSymbolPlaceholder() const {
SymIndexId Id = Cache.size();
Cache.push_back(nullptr);
return Id;
@@ -60,7 +91,7 @@
template <typename ConcreteSymbolT, typename CVRecordT, typename... Args>
SymIndexId createSymbolForType(codeview::TypeIndex TI, codeview::CVType CVT,
- Args &&... ConstructorArgs) {
+ Args &&...ConstructorArgs) const {
CVRecordT Record;
if (auto EC =
codeview::TypeDeserializer::deserializeAs<CVRecordT>(CVT, Record)) {
@@ -73,21 +104,26 @@
}
SymIndexId createSymbolForModifiedType(codeview::TypeIndex ModifierTI,
- codeview::CVType CVT);
+ codeview::CVType CVT) const;
SymIndexId createSimpleType(codeview::TypeIndex TI,
- codeview::ModifierOptions Mods);
+ codeview::ModifierOptions Mods) const;
+
+ std::unique_ptr<PDBSymbol> findFunctionSymbolBySectOffset(uint32_t Sect,
+ uint32_t Offset);
+ std::unique_ptr<PDBSymbol> findPublicSymbolBySectOffset(uint32_t Sect,
+ uint32_t Offset);
public:
SymbolCache(NativeSession &Session, DbiStream *Dbi);
template <typename ConcreteSymbolT, typename... Args>
- SymIndexId createSymbol(Args &&... ConstructorArgs) {
+ SymIndexId createSymbol(Args &&...ConstructorArgs) const {
SymIndexId Id = Cache.size();
// Initial construction must not access the cache, since it must be done
// atomically.
- auto Result = llvm::make_unique<ConcreteSymbolT>(
+ auto Result = std::make_unique<ConcreteSymbolT>(
Session, Id, std::forward<Args>(ConstructorArgs)...);
Result->SymbolId = Id;
@@ -109,7 +145,7 @@
std::unique_ptr<IPDBEnumSymbols>
createGlobalsEnumerator(codeview::SymbolKind Kind);
- SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
+ SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI) const;
template <typename ConcreteSymbolT, typename... Args>
SymIndexId getOrCreateFieldListMember(codeview::TypeIndex FieldListTI,
@@ -127,6 +163,15 @@
}
SymIndexId getOrCreateGlobalSymbolByOffset(uint32_t Offset);
+ SymIndexId getOrCreateInlineSymbol(codeview::InlineSiteSym Sym,
+ uint64_t ParentAddr, uint16_t Modi,
+ uint32_t RecordOffset) const;
+
+ std::unique_ptr<PDBSymbol>
+ findSymbolBySectOffset(uint32_t Sect, uint32_t Offset, PDB_SymType Type);
+
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findLineNumbersByVA(uint64_t VA, uint32_t Length) const;
std::unique_ptr<PDBSymbolCompiland> getOrCreateCompiland(uint32_t Index);
uint32_t getNumCompilands() const;
@@ -139,6 +184,10 @@
ConcreteT &getNativeSymbolById(SymIndexId SymbolId) const {
return static_cast<ConcreteT &>(getNativeSymbolById(SymbolId));
}
+
+ std::unique_ptr<IPDBSourceFile> getSourceFileById(SymIndexId FileId) const;
+ SymIndexId
+ getOrCreateSourceFile(const codeview::FileChecksumEntry &Checksum) const;
};
} // namespace pdb
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/TpiStream.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/TpiStream.h
index 1b7fd2d..7028886 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/TpiStream.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/TpiStream.h
@@ -9,7 +9,7 @@
#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
#define LLVM_DEBUGINFO_PDB_RAW_PDBTPISTREAM_H
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
+#include "llvm/DebugInfo/CodeView/CVRecord.h"
#include "llvm/DebugInfo/PDB/Native/HashTable.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
index 72d98e9..9ef2ee6 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h
@@ -54,16 +54,20 @@
void setVersionHeader(PdbRaw_TpiVer Version);
void addTypeRecord(ArrayRef<uint8_t> Type, Optional<uint32_t> Hash);
+ void addTypeRecords(ArrayRef<uint8_t> Types, ArrayRef<uint16_t> Sizes,
+ ArrayRef<uint32_t> Hashes);
Error finalizeMsfLayout();
- uint32_t getRecordCount() const { return TypeRecords.size(); }
+ uint32_t getRecordCount() const { return TypeRecordCount; }
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer);
uint32_t calculateSerializedLength();
private:
+ void updateTypeIndexOffsets(ArrayRef<uint16_t> Sizes);
+
uint32_t calculateHashBufferSize() const;
uint32_t calculateIndexOffsetSize() const;
Error finalize();
@@ -71,10 +75,11 @@
msf::MSFBuilder &Msf;
BumpPtrAllocator &Allocator;
+ uint32_t TypeRecordCount = 0;
size_t TypeRecordBytes = 0;
PdbRaw_TpiVer VerHeader = PdbRaw_TpiVer::PdbTpiV80;
- std::vector<ArrayRef<uint8_t>> TypeRecords;
+ std::vector<ArrayRef<uint8_t>> TypeRecBuffers;
std::vector<uint32_t> TypeHashes;
std::vector<codeview::TypeIndexOffset> TypeIndexOffsets;
uint32_t HashStreamIndex = kInvalidStreamIndex;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBExtras.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBExtras.h
index f5c3a5f..802d18a 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBExtras.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBExtras.h
@@ -9,16 +9,15 @@
#ifndef LLVM_DEBUGINFO_PDB_PDBEXTRAS_H
#define LLVM_DEBUGINFO_PDB_PDBEXTRAS_H
+#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/Support/raw_ostream.h"
-
+#include <cstdint>
#include <unordered_map>
namespace llvm {
-class raw_ostream;
-
namespace pdb {
using TagStats = std::unordered_map<PDB_SymType, int>;
@@ -37,13 +36,12 @@
raw_ostream &operator<<(raw_ostream &OS, const PDB_MemberAccess &Access);
raw_ostream &operator<<(raw_ostream &OS, const PDB_UdtType &Type);
raw_ostream &operator<<(raw_ostream &OS, const PDB_Machine &Machine);
-raw_ostream &operator<<(raw_ostream &OS,
- const PDB_SourceCompression &Compression);
raw_ostream &operator<<(raw_ostream &OS, const Variant &Value);
raw_ostream &operator<<(raw_ostream &OS, const VersionInfo &Version);
raw_ostream &operator<<(raw_ostream &OS, const TagStats &Stats);
+raw_ostream& dumpPDBSourceCompression(raw_ostream& OS, uint32_t Compression);
template <typename T>
void dumpSymbolField(raw_ostream &OS, StringRef Name, T Value, int Indent) {
@@ -52,7 +50,6 @@
OS << Name << ": " << Value;
}
-
} // end namespace pdb
} // end namespace llvm
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBSymbol.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBSymbol.h
index d9004a8..24cf1e4 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBSymbol.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBSymbol.h
@@ -17,13 +17,11 @@
#include "llvm/Support/Casting.h"
#define FORWARD_SYMBOL_METHOD(MethodName) \
- auto MethodName() const->decltype(RawSymbol->MethodName()) { \
- return RawSymbol->MethodName(); \
- }
+ decltype(auto) MethodName() const { return RawSymbol->MethodName(); }
#define FORWARD_CONCRETE_SYMBOL_ID_METHOD_WITH_NAME(ConcreteType, PrivateName, \
PublicName) \
- auto PublicName##Id() const->decltype(RawSymbol->PrivateName##Id()) { \
+ decltype(auto) PublicName##Id() const { \
return RawSymbol->PrivateName##Id(); \
} \
std::unique_ptr<ConcreteType> PublicName() const { \
@@ -44,7 +42,6 @@
class raw_ostream;
namespace pdb {
-class IPDBRawSymbol;
class IPDBSession;
#define DECLARE_PDB_SYMBOL_CONCRETE_TYPE(TagValue) \
@@ -131,7 +128,7 @@
auto BaseIter = RawSymbol->findChildren(T::Tag);
if (!BaseIter)
return nullptr;
- return llvm::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter));
+ return std::make_unique<ConcreteSymbolEnumerator<T>>(std::move(BaseIter));
}
std::unique_ptr<IPDBEnumSymbols> findAllChildren(PDB_SymType Type) const;
std::unique_ptr<IPDBEnumSymbols> findAllChildren() const;
@@ -143,7 +140,14 @@
StringRef Name,
PDB_NameSearchFlags Flags,
uint32_t RVA) const;
+ std::unique_ptr<IPDBEnumSymbols> findInlineFramesByVA(uint64_t VA) const;
std::unique_ptr<IPDBEnumSymbols> findInlineFramesByRVA(uint32_t RVA) const;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByVA(uint64_t VA, uint32_t Length) const;
+ std::unique_ptr<IPDBEnumLineNumbers>
+ findInlineeLinesByRVA(uint32_t RVA, uint32_t Length) const;
+
+ std::string getName() const;
const IPDBRawSymbol &getRawSymbol() const { return *RawSymbol; }
IPDBRawSymbol &getRawSymbol() { return *RawSymbol; }
diff --git a/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBTypes.h b/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBTypes.h
index 742cb85..e7c2ded 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBTypes.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/PDB/PDBTypes.h
@@ -9,6 +9,7 @@
#ifndef LLVM_DEBUGINFO_PDB_PDBTYPES_H
#define LLVM_DEBUGINFO_PDB_PDBTYPES_H
+#include "llvm/ADT/APFloat.h"
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/IPDBFrameData.h"
@@ -28,6 +29,7 @@
class IPDBInjectedSource;
class IPDBLineNumber;
class IPDBSectionContrib;
+class IPDBSession;
class IPDBSourceFile;
class IPDBTable;
class PDBSymDumper;
@@ -146,11 +148,69 @@
WceMipsV2 = 0x169
};
-enum class PDB_SourceCompression {
- None,
- RunLengthEncoded,
- Huffman,
- LZ,
+// A struct with an inner unnamed enum with explicit underlying type resuls
+// in an enum class that can implicitly convert to the underlying type, which
+// is convenient for this enum.
+struct PDB_SourceCompression {
+ enum : uint32_t {
+ // No compression. Produced e.g. by `link.exe /natvis:foo.natvis`.
+ None,
+ // Not known what produces this.
+ RunLengthEncoded,
+ // Not known what produces this.
+ Huffman,
+ // Not known what produces this.
+ LZ,
+ // Produced e.g. by `csc /debug`. The encoded data is its own mini-stream
+ // with the following layout (in little endian):
+ // GUID LanguageTypeGuid;
+ // GUID LanguageVendorGuid;
+ // GUID DocumentTypeGuid;
+ // GUID HashFunctionGuid;
+ // uint32_t HashDataSize;
+ // uint32_t CompressedDataSize;
+ // Followed by HashDataSize bytes containing a hash checksum,
+ // followed by CompressedDataSize bytes containing source contents.
+ //
+ // CompressedDataSize can be 0, in this case only the hash data is present.
+ // (CompressedDataSize is != 0 e.g. if `/embed` is passed to csc.exe.)
+ // The compressed data format is:
+ // uint32_t UncompressedDataSize;
+ // If UncompressedDataSize is 0, the data is stored uncompressed and
+ // CompressedDataSize stores the uncompressed size.
+ // If UncompressedDataSize is != 0, then the data is in raw deflate
+ // encoding as described in rfc1951.
+ //
+ // A GUID is 16 bytes, stored in the usual
+ // uint32_t
+ // uint16_t
+ // uint16_t
+ // uint8_t[24]
+ // layout.
+ //
+ // Well-known GUIDs for LanguageTypeGuid are:
+ // 63a08714-fc37-11d2-904c-00c04fa302a1 C
+ // 3a12d0b7-c26c-11d0-b442-00a0244a1dd2 C++
+ // 3f5162f8-07c6-11d3-9053-00c04fa302a1 C#
+ // af046cd1-d0e1-11d2-977c-00a0c9b4d50c Cobol
+ // ab4f38c9-b6e6-43ba-be3b-58080b2ccce3 F#
+ // 3a12d0b4-c26c-11d0-b442-00a0244a1dd2 Java
+ // 3a12d0b6-c26c-11d0-b442-00a0244a1dd2 JScript
+ // af046cd2-d0e1-11d2-977c-00a0c9b4d50c Pascal
+ // 3a12d0b8-c26c-11d0-b442-00a0244a1dd2 Visual Basic
+ //
+ // Well-known GUIDs for LanguageVendorGuid are:
+ // 994b45c4-e6e9-11d2-903f-00c04fa302a1 Microsoft
+ //
+ // Well-known GUIDs for DocumentTypeGuid are:
+ // 5a869d0b-6611-11d3-bd2a-0000f80849bd Text
+ //
+ // Well-known GUIDs for HashFunctionGuid are:
+ // 406ea660-64cf-4c82-b6f0-42d48172a799 MD5 (HashDataSize is 16)
+ // ff1816ec-aa5e-4d10-87f7-6f4963833460 SHA1 (HashDataSize is 20)
+ // 8829d00f-11b8-4213-878b-770e8597ac16 SHA256 (HashDataSize is 32)
+ DotNet = 101,
+ };
};
/// These values correspond to the CV_call_e enumeration, and are documented
@@ -405,6 +465,88 @@
char *String;
} Value;
+ bool isIntegralType() const {
+ switch (Type) {
+ case Bool:
+ case Int8:
+ case Int16:
+ case Int32:
+ case Int64:
+ case UInt8:
+ case UInt16:
+ case UInt32:
+ case UInt64:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+#define VARIANT_WIDTH(Enum, NumBits) \
+ case PDB_VariantType::Enum: \
+ return NumBits;
+
+ unsigned getBitWidth() const {
+ switch (Type) {
+ VARIANT_WIDTH(Bool, 1u)
+ VARIANT_WIDTH(Int8, 8u)
+ VARIANT_WIDTH(Int16, 16u)
+ VARIANT_WIDTH(Int32, 32u)
+ VARIANT_WIDTH(Int64, 64u)
+ VARIANT_WIDTH(Single, 32u)
+ VARIANT_WIDTH(Double, 64u)
+ VARIANT_WIDTH(UInt8, 8u)
+ VARIANT_WIDTH(UInt16, 16u)
+ VARIANT_WIDTH(UInt32, 32u)
+ VARIANT_WIDTH(UInt64, 64u)
+ default:
+ assert(false && "Variant::toAPSInt called on non-numeric type");
+ return 0u;
+ }
+ }
+
+#undef VARIANT_WIDTH
+
+#define VARIANT_APSINT(Enum, NumBits, IsUnsigned) \
+ case PDB_VariantType::Enum: \
+ return APSInt(APInt(NumBits, Value.Enum), IsUnsigned);
+
+ APSInt toAPSInt() const {
+ switch (Type) {
+ VARIANT_APSINT(Bool, 1u, true)
+ VARIANT_APSINT(Int8, 8u, false)
+ VARIANT_APSINT(Int16, 16u, false)
+ VARIANT_APSINT(Int32, 32u, false)
+ VARIANT_APSINT(Int64, 64u, false)
+ VARIANT_APSINT(UInt8, 8u, true)
+ VARIANT_APSINT(UInt16, 16u, true)
+ VARIANT_APSINT(UInt32, 32u, true)
+ VARIANT_APSINT(UInt64, 64u, true)
+ default:
+ assert(false && "Variant::toAPSInt called on non-integral type");
+ return APSInt();
+ }
+ }
+
+#undef VARIANT_APSINT
+
+ APFloat toAPFloat() const {
+ // Float constants may be tagged as integers.
+ switch (Type) {
+ case PDB_VariantType::Single:
+ case PDB_VariantType::UInt32:
+ case PDB_VariantType::Int32:
+ return APFloat(Value.Single);
+ case PDB_VariantType::Double:
+ case PDB_VariantType::UInt64:
+ case PDB_VariantType::Int64:
+ return APFloat(Value.Double);
+ default:
+ assert(false && "Variant::toAPFloat called on non-floating-point type");
+ return APFloat::getZero(APFloat::IEEEsingle());
+ }
+ }
+
#define VARIANT_EQUAL_CASE(Enum) \
case PDB_VariantType::Enum: \
return Value.Enum == Other.Value.Enum;
diff --git a/linux-x64/clang/include/llvm/DebugInfo/Symbolize/DIPrinter.h b/linux-x64/clang/include/llvm/DebugInfo/Symbolize/DIPrinter.h
index db7a61a..3d7e069 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/Symbolize/DIPrinter.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/Symbolize/DIPrinter.h
@@ -14,13 +14,14 @@
#ifndef LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H
#define LLVM_DEBUGINFO_SYMBOLIZE_DIPRINTER_H
-#include "llvm/Support/raw_ostream.h"
+#include <string>
namespace llvm {
struct DILineInfo;
class DIInliningInfo;
struct DIGlobal;
struct DILocal;
+class raw_ostream;
namespace symbolize {
@@ -34,7 +35,6 @@
bool PrintPretty;
int PrintSourceContext;
bool Verbose;
- bool Basenames;
OutputStyle Style;
void print(const DILineInfo &Info, bool Inlined);
@@ -43,11 +43,10 @@
public:
DIPrinter(raw_ostream &OS, bool PrintFunctionNames = true,
bool PrintPretty = false, int PrintSourceContext = 0,
- bool Verbose = false, bool Basenames = false,
- OutputStyle Style = OutputStyle::LLVM)
+ bool Verbose = false, OutputStyle Style = OutputStyle::LLVM)
: OS(OS), PrintFunctionNames(PrintFunctionNames),
PrintPretty(PrintPretty), PrintSourceContext(PrintSourceContext),
- Verbose(Verbose), Basenames(Basenames), Style(Style) {}
+ Verbose(Verbose), Style(Style) {}
DIPrinter &operator<<(const DILineInfo &Info);
DIPrinter &operator<<(const DIInliningInfo &Info);
@@ -58,4 +57,3 @@
}
#endif
-
diff --git a/linux-x64/clang/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h b/linux-x64/clang/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h
index 506ecc4..51e92b8 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/Symbolize/SymbolizableModule.h
@@ -25,11 +25,12 @@
virtual ~SymbolizableModule() = default;
virtual DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset,
- FunctionNameKind FNKind,
+ DILineInfoSpecifier LineInfoSpecifier,
bool UseSymbolTable) const = 0;
virtual DIInliningInfo
symbolizeInlinedCode(object::SectionedAddress ModuleOffset,
- FunctionNameKind FNKind, bool UseSymbolTable) const = 0;
+ DILineInfoSpecifier LineInfoSpecifier,
+ bool UseSymbolTable) const = 0;
virtual DIGlobal
symbolizeData(object::SectionedAddress ModuleOffset) const = 0;
virtual std::vector<DILocal>
diff --git a/linux-x64/clang/include/llvm/DebugInfo/Symbolize/Symbolize.h b/linux-x64/clang/include/llvm/DebugInfo/Symbolize/Symbolize.h
index d3da28c..1c8fa11 100644
--- a/linux-x64/clang/include/llvm/DebugInfo/Symbolize/Symbolize.h
+++ b/linux-x64/clang/include/llvm/DebugInfo/Symbolize/Symbolize.h
@@ -16,6 +16,7 @@
#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
#include "llvm/Object/Binary.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/Error.h"
#include <algorithm>
#include <cstdint>
@@ -31,18 +32,23 @@
using namespace object;
using FunctionNameKind = DILineInfoSpecifier::FunctionNameKind;
+using FileLineInfoKind = DILineInfoSpecifier::FileLineInfoKind;
class LLVMSymbolizer {
public:
struct Options {
FunctionNameKind PrintFunctions = FunctionNameKind::LinkageName;
+ FileLineInfoKind PathStyle = FileLineInfoKind::AbsoluteFilePath;
bool UseSymbolTable = true;
bool Demangle = true;
bool RelativeAddresses = false;
+ bool UntagAddresses = false;
+ bool UseDIA = false;
std::string DefaultArch;
std::vector<std::string> DsymHints;
std::string FallbackDebugPath;
std::string DWPName;
+ std::vector<std::string> DebugFileDirectory;
};
LLVMSymbolizer() = default;
@@ -97,6 +103,9 @@
ObjectFile *lookUpDebuglinkObject(const std::string &Path,
const ObjectFile *Obj,
const std::string &ArchName);
+ ObjectFile *lookUpBuildIDObject(const std::string &Path,
+ const ELFObjectFileBase *Obj,
+ const std::string &ArchName);
/// Returns pair of pointers to object and debug object.
Expected<ObjectPair> getOrCreateObjectPair(const std::string &Path,
@@ -108,7 +117,8 @@
Expected<ObjectFile *> getOrCreateObject(const std::string &Path,
const std::string &ArchName);
- std::map<std::string, std::unique_ptr<SymbolizableModule>> Modules;
+ std::map<std::string, std::unique_ptr<SymbolizableModule>, std::less<>>
+ Modules;
/// Contains cached results of getOrCreateObjectPair().
std::map<std::pair<std::string, std::string>, ObjectPair>