summaryrefslogtreecommitdiff
path: root/include/llvm/DebugInfo
diff options
context:
space:
mode:
Diffstat (limited to 'include/llvm/DebugInfo')
-rw-r--r--include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h70
-rw-r--r--include/llvm/DebugInfo/CodeView/CVRecord.h44
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeView.h59
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewRegisters.def268
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewSymbols.def7
-rw-r--r--include/llvm/DebugInfo/CodeView/CodeViewTypes.def3
-rw-r--r--include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h65
-rw-r--r--include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h87
-rw-r--r--include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h3
-rw-r--r--include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h81
-rw-r--r--include/llvm/DebugInfo/CodeView/RecordName.h (renamed from include/llvm/DebugInfo/CodeView/TypeName.h)10
-rw-r--r--include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h53
-rw-r--r--include/llvm/DebugInfo/CodeView/StringsAndChecksums.h9
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolDeserializer.h6
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolRecord.h13
-rw-r--r--include/llvm/DebugInfo/CodeView/SymbolSerializer.h5
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeCollection.h10
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeDeserializer.h13
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeHashing.h204
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeIndex.h2
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h10
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecord.h13
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h78
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeSerializer.h159
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeStreamMerger.h28
-rw-r--r--include/llvm/DebugInfo/CodeView/TypeTableBuilder.h137
-rw-r--r--include/llvm/DebugInfo/DIContext.h127
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h41
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h58
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFContext.h261
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h13
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h5
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h10
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLine.h19
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h43
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h3
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h36
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFDie.h18
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFExpression.h151
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFFormValue.h17
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFObject.h79
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFSection.h7
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h2
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnit.h135
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h4
-rw-r--r--include/llvm/DebugInfo/DWARF/DWARFVerifier.h152
-rw-r--r--include/llvm/DebugInfo/MSF/MSFBuilder.h1
-rw-r--r--include/llvm/DebugInfo/MSF/MSFCommon.h34
-rw-r--r--include/llvm/DebugInfo/MSF/MSFStreamLayout.h35
-rw-r--r--include/llvm/DebugInfo/MSF/MappedBlockStream.h4
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h37
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h1
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIASession.h1
-rw-r--r--include/llvm/DebugInfo/PDB/DIA/DIATable.h32
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBRawSymbol.h1
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBSession.h2
-rw-r--r--include/llvm/DebugInfo/PDB/IPDBTable.h28
-rw-r--r--include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h11
-rw-r--r--include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h82
-rw-r--r--include/llvm/DebugInfo/PDB/Native/GlobalsStream.h57
-rw-r--r--include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h4
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h60
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h51
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h1
-rw-r--r--include/llvm/DebugInfo/PDB/Native/NativeSession.h11
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBFile.h10
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h8
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PublicsStream.h24
-rw-r--r--include/llvm/DebugInfo/PDB/Native/PublicsStreamBuilder.h54
-rw-r--r--include/llvm/DebugInfo/PDB/Native/RawTypes.h14
-rw-r--r--include/llvm/DebugInfo/PDB/Native/SymbolStream.h2
-rw-r--r--include/llvm/DebugInfo/PDB/PDBSymbol.h4
-rw-r--r--include/llvm/DebugInfo/PDB/PDBTypes.h34
-rw-r--r--include/llvm/DebugInfo/Symbolize/Symbolize.h8
75 files changed, 2280 insertions, 951 deletions
diff --git a/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h
new file mode 100644
index 0000000000000..bd1743511ed4b
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/AppendingTypeTableBuilder.h
@@ -0,0 +1,70 @@
+//===- AppendingTypeTableBuilder.h -------------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_APPENDINGTYPETABLEBUILDER_H
+#define LLVM_DEBUGINFO_CODEVIEW_APPENDINGTYPETABLEBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+
+class ContinuationRecordBuilder;
+
+class AppendingTypeTableBuilder : public TypeCollection {
+
+ BumpPtrAllocator &RecordStorage;
+ SimpleTypeSerializer SimpleSerializer;
+
+ /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
+ SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
+
+public:
+ explicit AppendingTypeTableBuilder(BumpPtrAllocator &Storage);
+ ~AppendingTypeTableBuilder();
+
+ // TypeTableCollection overrides
+ Optional<TypeIndex> getFirst() override;
+ Optional<TypeIndex> getNext(TypeIndex Prev) override;
+ CVType getType(TypeIndex Index) override;
+ StringRef getTypeName(TypeIndex Index) override;
+ bool contains(TypeIndex Index) override;
+ uint32_t size() override;
+ uint32_t capacity() override;
+
+ // public interface
+ void reset();
+ TypeIndex nextTypeIndex() const;
+
+ BumpPtrAllocator &getAllocator() { return RecordStorage; }
+
+ ArrayRef<ArrayRef<uint8_t>> records() const;
+ TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
+ TypeIndex insertRecord(ContinuationRecordBuilder &Builder);
+
+ template <typename T> TypeIndex writeLeafType(T &Record) {
+ ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record);
+ return insertRecordBytes(Data);
+ }
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
diff --git a/include/llvm/DebugInfo/CodeView/CVRecord.h b/include/llvm/DebugInfo/CodeView/CVRecord.h
index 44040e04388af..9f3a753ad1ae1 100644
--- a/include/llvm/DebugInfo/CodeView/CVRecord.h
+++ b/include/llvm/DebugInfo/CodeView/CVRecord.h
@@ -61,30 +61,38 @@ template <typename Kind> struct RemappedRecord {
SmallVector<std::pair<uint32_t, TypeIndex>, 8> Mappings;
};
+/// Read a complete record from a stream at a random offset.
+template <typename Kind>
+inline Expected<CVRecord<Kind>> readCVRecordFromStream(BinaryStreamRef Stream,
+ uint32_t Offset) {
+ const RecordPrefix *Prefix = nullptr;
+ BinaryStreamReader Reader(Stream);
+ Reader.setOffset(Offset);
+
+ if (auto EC = Reader.readObject(Prefix))
+ return std::move(EC);
+ if (Prefix->RecordLen < 2)
+ return make_error<CodeViewError>(cv_error_code::corrupt_record);
+ Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind));
+
+ Reader.setOffset(Offset);
+ ArrayRef<uint8_t> RawData;
+ if (auto EC = Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
+ return std::move(EC);
+ return codeview::CVRecord<Kind>(K, RawData);
+}
+
} // end namespace codeview
template <typename Kind>
struct VarStreamArrayExtractor<codeview::CVRecord<Kind>> {
Error operator()(BinaryStreamRef Stream, uint32_t &Len,
codeview::CVRecord<Kind> &Item) {
- using namespace codeview;
- const RecordPrefix *Prefix = nullptr;
- BinaryStreamReader Reader(Stream);
- uint32_t Offset = Reader.getOffset();
-
- if (auto EC = Reader.readObject(Prefix))
- return EC;
- if (Prefix->RecordLen < 2)
- return make_error<CodeViewError>(cv_error_code::corrupt_record);
- Kind K = static_cast<Kind>(uint16_t(Prefix->RecordKind));
-
- Reader.setOffset(Offset);
- ArrayRef<uint8_t> RawData;
- if (auto EC =
- Reader.readBytes(RawData, Prefix->RecordLen + sizeof(uint16_t)))
- return EC;
- Item = codeview::CVRecord<Kind>(K, RawData);
- Len = Item.length();
+ auto ExpectedRec = codeview::readCVRecordFromStream<Kind>(Stream, 0);
+ if (!ExpectedRec)
+ return ExpectedRec.takeError();
+ Item = *ExpectedRec;
+ Len = ExpectedRec->length();
return Error::success();
}
};
diff --git a/include/llvm/DebugInfo/CodeView/CodeView.h b/include/llvm/DebugInfo/CodeView/CodeView.h
index b7a7e33abadf8..1a4f510c24abe 100644
--- a/include/llvm/DebugInfo/CodeView/CodeView.h
+++ b/include/llvm/DebugInfo/CodeView/CodeView.h
@@ -124,6 +124,7 @@ enum class CPUType : uint16_t {
ARM_XMAC = 0x66,
ARM_WMMX = 0x67,
ARM7 = 0x68,
+ ARM64 = 0x69,
Omni = 0x70,
Ia64 = 0x80,
Ia64_2 = 0x81,
@@ -157,7 +158,11 @@ enum SourceLanguage : uint8_t {
Java = 0x0d,
JScript = 0x0e,
MSIL = 0x0f,
- HLSL = 0x10
+ HLSL = 0x10,
+
+ /// The DMD compiler emits 'D' for the CV source language. Microsoft doesn't
+ /// have an enumerator for it yet.
+ D = 'D',
};
/// These values correspond to the CV_call_e enumeration, and are documented
@@ -500,55 +505,9 @@ enum class FrameCookieKind : uint8_t {
// Corresponds to CV_HREG_e enum.
enum class RegisterId : uint16_t {
- Unknown = 0,
- VFrame = 30006,
- AL = 1,
- CL = 2,
- DL = 3,
- BL = 4,
- AH = 5,
- CH = 6,
- DH = 7,
- BH = 8,
- AX = 9,
- CX = 10,
- DX = 11,
- BX = 12,
- SP = 13,
- BP = 14,
- SI = 15,
- DI = 16,
- EAX = 17,
- ECX = 18,
- EDX = 19,
- EBX = 20,
- ESP = 21,
- EBP = 22,
- ESI = 23,
- EDI = 24,
- ES = 25,
- CS = 26,
- SS = 27,
- DS = 28,
- FS = 29,
- GS = 30,
- IP = 31,
- RAX = 328,
- RBX = 329,
- RCX = 330,
- RDX = 331,
- RSI = 332,
- RDI = 333,
- RBP = 334,
- RSP = 335,
- R8 = 336,
- R9 = 337,
- R10 = 338,
- R11 = 339,
- R12 = 340,
- R13 = 341,
- R14 = 342,
- R15 = 343,
+#define CV_REGISTER(name, value) name = value,
+#include "CodeViewRegisters.def"
+#undef CV_REGISTER
};
/// These values correspond to the THUNK_ORDINAL enumeration.
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def b/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
new file mode 100644
index 0000000000000..3f06602948668
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/CodeViewRegisters.def
@@ -0,0 +1,268 @@
+//===-- CodeViewRegisters.def - CodeView registers --------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// See CV_HREG_e in cvconst.h. This should match the constants there.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef CV_REGISTER
+#define CV_REGISTER(name, value)
+#endif
+
+// This currently only contains the "register subset shraed by all processor
+// types" (ERR etc.) and the x86 registers.
+
+CV_REGISTER(ERR, 30000)
+CV_REGISTER(TEB, 30001)
+CV_REGISTER(TIMER, 30002)
+CV_REGISTER(EFAD1, 30003)
+CV_REGISTER(EFAD2, 30004)
+CV_REGISTER(EFAD3, 30005)
+CV_REGISTER(VFRAME, 30006)
+CV_REGISTER(HANDLE, 30007)
+CV_REGISTER(PARAMS, 30008)
+CV_REGISTER(LOCALS, 30009)
+CV_REGISTER(TID, 30010)
+CV_REGISTER(ENV, 30011)
+CV_REGISTER(CMDLN, 30012)
+
+CV_REGISTER(NONE, 0)
+CV_REGISTER(AL, 1)
+CV_REGISTER(CL, 2)
+CV_REGISTER(DL, 3)
+CV_REGISTER(BL, 4)
+CV_REGISTER(AH, 5)
+CV_REGISTER(CH, 6)
+CV_REGISTER(DH, 7)
+CV_REGISTER(BH, 8)
+CV_REGISTER(AX, 9)
+CV_REGISTER(CX, 10)
+CV_REGISTER(DX, 11)
+CV_REGISTER(BX, 12)
+CV_REGISTER(SP, 13)
+CV_REGISTER(BP, 14)
+CV_REGISTER(SI, 15)
+CV_REGISTER(DI, 16)
+CV_REGISTER(EAX, 17)
+CV_REGISTER(ECX, 18)
+CV_REGISTER(EDX, 19)
+CV_REGISTER(EBX, 20)
+CV_REGISTER(ESP, 21)
+CV_REGISTER(EBP, 22)
+CV_REGISTER(ESI, 23)
+CV_REGISTER(EDI, 24)
+CV_REGISTER(ES, 25)
+CV_REGISTER(CS, 26)
+CV_REGISTER(SS, 27)
+CV_REGISTER(DS, 28)
+CV_REGISTER(FS, 29)
+CV_REGISTER(GS, 30)
+CV_REGISTER(IP, 31)
+CV_REGISTER(FLAGS, 32)
+CV_REGISTER(EIP, 33)
+CV_REGISTER(EFLAGS, 34)
+CV_REGISTER(TEMP, 40)
+CV_REGISTER(TEMPH, 41)
+CV_REGISTER(QUOTE, 42)
+CV_REGISTER(PCDR3, 43)
+CV_REGISTER(PCDR4, 44)
+CV_REGISTER(PCDR5, 45)
+CV_REGISTER(PCDR6, 46)
+CV_REGISTER(PCDR7, 47)
+CV_REGISTER(CR0, 80)
+CV_REGISTER(CR1, 81)
+CV_REGISTER(CR2, 82)
+CV_REGISTER(CR3, 83)
+CV_REGISTER(CR4, 84)
+CV_REGISTER(DR0, 90)
+CV_REGISTER(DR1, 91)
+CV_REGISTER(DR2, 92)
+CV_REGISTER(DR3, 93)
+CV_REGISTER(DR4, 94)
+CV_REGISTER(DR5, 95)
+CV_REGISTER(DR6, 96)
+CV_REGISTER(DR7, 97)
+CV_REGISTER(GDTR, 110)
+CV_REGISTER(GDTL, 111)
+CV_REGISTER(IDTR, 112)
+CV_REGISTER(IDTL, 113)
+CV_REGISTER(LDTR, 114)
+CV_REGISTER(TR, 115)
+
+CV_REGISTER(PSEUDO1, 116)
+CV_REGISTER(PSEUDO2, 117)
+CV_REGISTER(PSEUDO3, 118)
+CV_REGISTER(PSEUDO4, 119)
+CV_REGISTER(PSEUDO5, 120)
+CV_REGISTER(PSEUDO6, 121)
+CV_REGISTER(PSEUDO7, 122)
+CV_REGISTER(PSEUDO8, 123)
+CV_REGISTER(PSEUDO9, 124)
+
+CV_REGISTER(ST0, 128)
+CV_REGISTER(ST1, 129)
+CV_REGISTER(ST2, 130)
+CV_REGISTER(ST3, 131)
+CV_REGISTER(ST4, 132)
+CV_REGISTER(ST5, 133)
+CV_REGISTER(ST6, 134)
+CV_REGISTER(ST7, 135)
+CV_REGISTER(CTRL, 136)
+CV_REGISTER(STAT, 137)
+CV_REGISTER(TAG, 138)
+CV_REGISTER(FPIP, 139)
+CV_REGISTER(FPCS, 140)
+CV_REGISTER(FPDO, 141)
+CV_REGISTER(FPDS, 142)
+CV_REGISTER(ISEM, 143)
+CV_REGISTER(FPEIP, 144)
+CV_REGISTER(FPEDO, 145)
+
+CV_REGISTER(MM0, 146)
+CV_REGISTER(MM1, 147)
+CV_REGISTER(MM2, 148)
+CV_REGISTER(MM3, 149)
+CV_REGISTER(MM4, 150)
+CV_REGISTER(MM5, 151)
+CV_REGISTER(MM6, 152)
+CV_REGISTER(MM7, 153)
+
+CV_REGISTER(XMM0, 154)
+CV_REGISTER(XMM1, 155)
+CV_REGISTER(XMM2, 156)
+CV_REGISTER(XMM3, 157)
+CV_REGISTER(XMM4, 158)
+CV_REGISTER(XMM5, 159)
+CV_REGISTER(XMM6, 160)
+CV_REGISTER(XMM7, 161)
+
+CV_REGISTER(MXCSR, 211)
+
+CV_REGISTER(EDXEAX, 212)
+
+CV_REGISTER(EMM0L, 220)
+CV_REGISTER(EMM1L, 221)
+CV_REGISTER(EMM2L, 222)
+CV_REGISTER(EMM3L, 223)
+CV_REGISTER(EMM4L, 224)
+CV_REGISTER(EMM5L, 225)
+CV_REGISTER(EMM6L, 226)
+CV_REGISTER(EMM7L, 227)
+
+CV_REGISTER(EMM0H, 228)
+CV_REGISTER(EMM1H, 229)
+CV_REGISTER(EMM2H, 230)
+CV_REGISTER(EMM3H, 231)
+CV_REGISTER(EMM4H, 232)
+CV_REGISTER(EMM5H, 233)
+CV_REGISTER(EMM6H, 234)
+CV_REGISTER(EMM7H, 235)
+
+CV_REGISTER(MM00, 236)
+CV_REGISTER(MM01, 237)
+CV_REGISTER(MM10, 238)
+CV_REGISTER(MM11, 239)
+CV_REGISTER(MM20, 240)
+CV_REGISTER(MM21, 241)
+CV_REGISTER(MM30, 242)
+CV_REGISTER(MM31, 243)
+CV_REGISTER(MM40, 244)
+CV_REGISTER(MM41, 245)
+CV_REGISTER(MM50, 246)
+CV_REGISTER(MM51, 247)
+CV_REGISTER(MM60, 248)
+CV_REGISTER(MM61, 249)
+CV_REGISTER(MM70, 250)
+CV_REGISTER(MM71, 251)
+
+CV_REGISTER(BND0, 396)
+CV_REGISTER(BND1, 397)
+CV_REGISTER(BND2, 398)
+
+
+CV_REGISTER(XMM8, 252)
+CV_REGISTER(XMM9, 253)
+CV_REGISTER(XMM10, 254)
+CV_REGISTER(XMM11, 255)
+CV_REGISTER(XMM12, 256)
+CV_REGISTER(XMM13, 257)
+CV_REGISTER(XMM14, 258)
+CV_REGISTER(XMM15, 259)
+
+
+CV_REGISTER(SIL, 324)
+CV_REGISTER(DIL, 325)
+CV_REGISTER(BPL, 326)
+CV_REGISTER(SPL, 327)
+
+CV_REGISTER(RAX, 328)
+CV_REGISTER(RBX, 329)
+CV_REGISTER(RCX, 330)
+CV_REGISTER(RDX, 331)
+CV_REGISTER(RSI, 332)
+CV_REGISTER(RDI, 333)
+CV_REGISTER(RBP, 334)
+CV_REGISTER(RSP, 335)
+
+CV_REGISTER(R8, 336)
+CV_REGISTER(R9, 337)
+CV_REGISTER(R10, 338)
+CV_REGISTER(R11, 339)
+CV_REGISTER(R12, 340)
+CV_REGISTER(R13, 341)
+CV_REGISTER(R14, 342)
+CV_REGISTER(R15, 343)
+
+CV_REGISTER(R8B, 344)
+CV_REGISTER(R9B, 345)
+CV_REGISTER(R10B, 346)
+CV_REGISTER(R11B, 347)
+CV_REGISTER(R12B, 348)
+CV_REGISTER(R13B, 349)
+CV_REGISTER(R14B, 350)
+CV_REGISTER(R15B, 351)
+
+CV_REGISTER(R8W, 352)
+CV_REGISTER(R9W, 353)
+CV_REGISTER(R10W, 354)
+CV_REGISTER(R11W, 355)
+CV_REGISTER(R12W, 356)
+CV_REGISTER(R13W, 357)
+CV_REGISTER(R14W, 358)
+CV_REGISTER(R15W, 359)
+
+CV_REGISTER(R8D, 360)
+CV_REGISTER(R9D, 361)
+CV_REGISTER(R10D, 362)
+CV_REGISTER(R11D, 363)
+CV_REGISTER(R12D, 364)
+CV_REGISTER(R13D, 365)
+CV_REGISTER(R14D, 366)
+CV_REGISTER(R15D, 367)
+
+
+// cvconst.h defines both CV_REG_YMM0 (252) and CV_AMD64_YMM0 (368). Keep the
+// original prefix to distinguish them.
+
+CV_REGISTER(AMD64_YMM0, 368)
+CV_REGISTER(AMD64_YMM1, 369)
+CV_REGISTER(AMD64_YMM2, 370)
+CV_REGISTER(AMD64_YMM3, 371)
+CV_REGISTER(AMD64_YMM4, 372)
+CV_REGISTER(AMD64_YMM5, 373)
+CV_REGISTER(AMD64_YMM6, 374)
+CV_REGISTER(AMD64_YMM7, 375)
+CV_REGISTER(AMD64_YMM8, 376)
+CV_REGISTER(AMD64_YMM9, 377)
+CV_REGISTER(AMD64_YMM10, 378)
+CV_REGISTER(AMD64_YMM11, 379)
+CV_REGISTER(AMD64_YMM12, 380)
+CV_REGISTER(AMD64_YMM13, 381)
+CV_REGISTER(AMD64_YMM14, 382)
+CV_REGISTER(AMD64_YMM15, 383)
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def b/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def
index 32813d861d909..41c5380767983 100644
--- a/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def
+++ b/include/llvm/DebugInfo/CodeView/CodeViewSymbols.def
@@ -1,4 +1,4 @@
-//===-- CVLeafTypes.def - All CodeView leaf types ---------------*- C++ -*-===//
+//===-- CodeViewSymbols.def - All CodeView leaf types -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -184,6 +184,9 @@ CV_SYMBOL(S_LDATA_HLSL32 , 0x1163)
CV_SYMBOL(S_GDATA_HLSL32_EX, 0x1164)
CV_SYMBOL(S_LDATA_HLSL32_EX, 0x1165)
+CV_SYMBOL(S_FASTLINK, 0x1167) // Undocumented
+SYMBOL_RECORD_ALIAS(S_INLINEES, 0x1168, InlineesSym, CallerSym) // Undocumented
+
// Known symbol types
SYMBOL_RECORD(S_END , 0x0006, ScopeEndSym)
SYMBOL_RECORD_ALIAS(S_INLINESITE_END , 0x114e, InlineSiteEnd, ScopeEndSym)
@@ -232,7 +235,7 @@ SYMBOL_RECORD(S_HEAPALLOCSITE , 0x115e, HeapAllocationSiteSym)
SYMBOL_RECORD(S_FRAMECOOKIE , 0x113a, FrameCookieSym)
SYMBOL_RECORD(S_CALLEES , 0x115a, CallerSym)
-SYMBOL_RECORD_ALIAS(S_CALLERS , 0x115b, CalleeSym, CallerSym)
+SYMBOL_RECORD_ALIAS(S_CALLERS, 0x115b, CalleeSym, CallerSym)
SYMBOL_RECORD(S_UDT , 0x1108, UDTSym)
SYMBOL_RECORD_ALIAS(S_COBOLUDT , 0x1109, CobolUDT, UDTSym)
diff --git a/include/llvm/DebugInfo/CodeView/CodeViewTypes.def b/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
index 8c193bb13cb7e..69ce9606a670f 100644
--- a/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
+++ b/include/llvm/DebugInfo/CodeView/CodeViewTypes.def
@@ -1,5 +1,4 @@
-
-//===-- CVLeafTypes.def - All CodeView leaf types ---------------*- C++ -*-===//
+//===-- CodeViewTypes.def - All CodeView leaf types -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h b/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h
new file mode 100644
index 0000000000000..7f851a2595dc0
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/ContinuationRecordBuilder.h
@@ -0,0 +1,65 @@
+//===- ContinuationRecordBuilder.h ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_CONTINUATIONRECORDBUILDER_H
+#define LLVM_DEBUGINFO_CODEVIEW_CONTINUATIONRECORDBUILDER_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 {
+enum class ContinuationRecordKind { FieldList, MethodOverloadList };
+
+class ContinuationRecordBuilder {
+ SmallVector<uint32_t, 4> SegmentOffsets;
+ Optional<ContinuationRecordKind> Kind;
+ AppendingBinaryByteStream Buffer;
+ BinaryStreamWriter SegmentWriter;
+ TypeRecordMapping Mapping;
+ ArrayRef<uint8_t> InjectedSegmentBytes;
+
+ uint32_t getCurrentSegmentLength() const;
+
+ void insertSegmentEnd(uint32_t Offset);
+ CVType createSegmentRecord(uint32_t OffBegin, uint32_t OffEnd,
+ Optional<TypeIndex> RefersTo);
+
+public:
+ ContinuationRecordBuilder();
+ ~ContinuationRecordBuilder();
+
+ void begin(ContinuationRecordKind RecordKind);
+
+ // This template is explicitly instantiated in the implementation file for all
+ // supported types. The method itself is ugly, so inlining it into the header
+ // file clutters an otherwise straightforward interface.
+ template <typename RecordType> void writeMemberType(RecordType &Record);
+
+ std::vector<CVType> end(TypeIndex Index);
+};
+} // namespace codeview
+} // namespace llvm
+
+#endif \ No newline at end of file
diff --git a/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
new file mode 100644
index 0000000000000..d8ac3343c15f9
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h
@@ -0,0 +1,87 @@
+//===- GlobalTypeTableBuilder.h ----------------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPETABLEBUILDER_H
+#define LLVM_DEBUGINFO_CODEVIEW_GLOBALTYPETABLEBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeHashing.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+
+class ContinuationRecordBuilder;
+
+class GlobalTypeTableBuilder : public TypeCollection {
+ /// Storage for records. These need to outlive the TypeTableBuilder.
+ BumpPtrAllocator &RecordStorage;
+
+ /// A serializer that can write non-continuation leaf types. Only used as
+ /// a convenience function so that we can provide an interface method to
+ /// write an unserialized record.
+ SimpleTypeSerializer SimpleSerializer;
+
+ /// Hash table.
+ DenseMap<GloballyHashedType, TypeIndex> HashedRecords;
+
+ /// 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().
+ SmallVector<GloballyHashedType, 2> SeenHashes;
+
+public:
+ explicit GlobalTypeTableBuilder(BumpPtrAllocator &Storage);
+ ~GlobalTypeTableBuilder();
+
+ // TypeTableCollection overrides
+ Optional<TypeIndex> getFirst() override;
+ Optional<TypeIndex> getNext(TypeIndex Prev) override;
+ CVType getType(TypeIndex Index) override;
+ StringRef getTypeName(TypeIndex Index) override;
+ bool contains(TypeIndex Index) override;
+ uint32_t size() override;
+ uint32_t capacity() override;
+
+ // public interface
+ void reset();
+ TypeIndex nextTypeIndex() const;
+
+ BumpPtrAllocator &getAllocator() { return RecordStorage; }
+
+ ArrayRef<ArrayRef<uint8_t>> records() const;
+ ArrayRef<GloballyHashedType> hashes() const;
+
+ using CreateRecord = llvm::function_ref<ArrayRef<uint8_t>()>;
+
+ TypeIndex insertRecordAs(GloballyHashedType Hash, CreateRecord Create);
+ TypeIndex insertRecordBytes(ArrayRef<uint8_t> Data);
+ TypeIndex insertRecord(ContinuationRecordBuilder &Builder);
+
+ template <typename T> TypeIndex writeLeafType(T &Record) {
+ ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record);
+ return insertRecordBytes(Data);
+ }
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H
diff --git a/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
index cc0c24301d498..16d78692c839a 100644
--- a/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
+++ b/include/llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h
@@ -67,9 +67,12 @@ public:
void reset(ArrayRef<uint8_t> Data, uint32_t RecordCountHint);
void reset(StringRef Data, uint32_t RecordCountHint);
+ void reset(BinaryStreamReader &Reader, uint32_t RecordCountHint);
uint32_t getOffsetOfType(TypeIndex Index);
+ Optional<CVType> tryGetType(TypeIndex Index);
+
CVType getType(TypeIndex Index) override;
StringRef getTypeName(TypeIndex Index) override;
bool contains(TypeIndex Index) override;
diff --git a/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h
new file mode 100644
index 0000000000000..9030918ebbb32
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h
@@ -0,0 +1,81 @@
+//===- MergingTypeTableBuilder.h ---------------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H
+#define LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/SimpleTypeSerializer.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeHashing.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/Support/Allocator.h"
+#include <cassert>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+namespace llvm {
+namespace codeview {
+
+class ContinuationRecordBuilder;
+
+class MergingTypeTableBuilder : public TypeCollection {
+ /// Storage for records. These need to outlive the TypeTableBuilder.
+ BumpPtrAllocator &RecordStorage;
+
+ /// A serializer that can write non-continuation leaf types. Only used as
+ /// a convenience function so that we can provide an interface method to
+ /// write an unserialized record.
+ SimpleTypeSerializer SimpleSerializer;
+
+ /// Hash table.
+ DenseMap<LocallyHashedType, TypeIndex> HashedRecords;
+
+ /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
+ SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
+
+public:
+ explicit MergingTypeTableBuilder(BumpPtrAllocator &Storage);
+ ~MergingTypeTableBuilder();
+
+ // TypeTableCollection overrides
+ Optional<TypeIndex> getFirst() override;
+ Optional<TypeIndex> getNext(TypeIndex Prev) override;
+ CVType getType(TypeIndex Index) override;
+ StringRef getTypeName(TypeIndex Index) override;
+ bool contains(TypeIndex Index) override;
+ uint32_t size() override;
+ uint32_t capacity() override;
+
+ // public interface
+ void reset();
+ TypeIndex nextTypeIndex() const;
+
+ BumpPtrAllocator &getAllocator() { return RecordStorage; }
+
+ ArrayRef<ArrayRef<uint8_t>> records() const;
+
+ TypeIndex insertRecordAs(hash_code Hash, ArrayRef<uint8_t> &Record);
+ TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
+ TypeIndex insertRecord(ContinuationRecordBuilder &Builder);
+
+ template <typename T> TypeIndex writeLeafType(T &Record) {
+ ArrayRef<uint8_t> Data = SimpleSerializer.serialize(Record);
+ return insertRecordBytes(Data);
+ }
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_MERGINGTYPETABLEBUILDER_H
diff --git a/include/llvm/DebugInfo/CodeView/TypeName.h b/include/llvm/DebugInfo/CodeView/RecordName.h
index a987b4afd283a..b022108df3d65 100644
--- a/include/llvm/DebugInfo/CodeView/TypeName.h
+++ b/include/llvm/DebugInfo/CodeView/RecordName.h
@@ -1,4 +1,4 @@
-//===- TypeName.h --------------------------------------------- *- C++ --*-===//
+//===- RecordName.h ------------------------------------------- *- C++ --*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,16 +7,18 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPENAME_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPENAME_H
+#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"
namespace llvm {
namespace codeview {
std::string computeTypeName(TypeCollection &Types, TypeIndex Index);
-}
+StringRef getSymbolName(CVSymbol Sym);
+} // namespace codeview
} // namespace llvm
#endif
diff --git a/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h b/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h
new file mode 100644
index 0000000000000..a85d9270186bf
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/SimpleTypeSerializer.h
@@ -0,0 +1,53 @@
+//===- SimpleTypeSerializer.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_SIMPLETYPESERIALIZER_H
+#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 SimpleTypeSerializer {
+ std::vector<uint8_t> ScratchBuffer;
+
+public:
+ SimpleTypeSerializer();
+ ~SimpleTypeSerializer();
+
+ // This template is explicitly instantiated in the implementation file for all
+ // supported types. The method itself is ugly, so inlining it into the header
+ // file clutters an otherwise straightforward interface.
+ template <typename T> ArrayRef<uint8_t> serialize(T &Record);
+
+ // Don't allow serialization of field list records using this interface.
+ ArrayRef<uint8_t> serialize(const FieldListRecord &Record) = delete;
+};
+
+} // end namespace codeview
+} // end namespace llvm
+
+#endif // LLVM_DEBUGINFO_CODEVIEW_SIMPLETYPESERIALIZER_H
diff --git a/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h
index 1a83882246652..22a333e631a03 100644
--- a/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h
+++ b/include/llvm/DebugInfo/CodeView/StringsAndChecksums.h
@@ -31,8 +31,13 @@ public:
StringsAndChecksumsRef(const DebugStringTableSubsectionRef &Strings,
const DebugChecksumsSubsectionRef &Checksums);
+ void setStrings(const DebugStringTableSubsectionRef &Strings);
void setChecksums(const DebugChecksumsSubsectionRef &CS);
+ void reset();
+ void resetStrings();
+ void resetChecksums();
+
template <typename T> void initialize(T &&FragmentRange) {
for (const DebugSubsectionRecord &R : FragmentRange) {
if (Strings && Checksums)
@@ -67,8 +72,8 @@ private:
void initializeStrings(const DebugSubsectionRecord &SR);
void initializeChecksums(const DebugSubsectionRecord &FCR);
- std::unique_ptr<DebugStringTableSubsectionRef> OwnedStrings;
- std::unique_ptr<DebugChecksumsSubsectionRef> OwnedChecksums;
+ std::shared_ptr<DebugStringTableSubsectionRef> OwnedStrings;
+ std::shared_ptr<DebugChecksumsSubsectionRef> OwnedChecksums;
const DebugStringTableSubsectionRef *Strings = nullptr;
const DebugChecksumsSubsectionRef *Checksums = nullptr;
diff --git a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
index 5b6599d8c1db0..b5479db97a150 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolDeserializer.h
@@ -46,6 +46,12 @@ public:
return EC;
return Error::success();
}
+ template <typename T> static Expected<T> deserializeAs(CVSymbol Symbol) {
+ T Record(Symbol.kind());
+ if (auto EC = deserializeAs<T>(Symbol, Record))
+ return std::move(EC);
+ return Record;
+ }
explicit SymbolDeserializer(SymbolVisitorDelegate *Delegate,
CodeViewContainer Container)
diff --git a/include/llvm/DebugInfo/CodeView/SymbolRecord.h b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
index f3086cf3dbb91..cf267f23967bc 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolRecord.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolRecord.h
@@ -363,12 +363,12 @@ public:
: SymbolRecord(SymbolRecordKind::PublicSym32),
RecordOffset(RecordOffset) {}
- PublicSymFlags Flags;
- uint32_t Offset;
- uint16_t Segment;
+ PublicSymFlags Flags = PublicSymFlags::None;
+ uint32_t Offset = 0;
+ uint16_t Segment = 0;
StringRef Name;
- uint32_t RecordOffset;
+ uint32_t RecordOffset = 0;
};
// S_REGISTER
@@ -942,9 +942,14 @@ public:
uint32_t RecordOffset;
};
+// S_ANNOTATION
+
using CVSymbol = CVRecord<SymbolKind>;
using CVSymbolArray = VarStreamArray<CVSymbol>;
+Expected<CVSymbol> readSymbolFromStream(BinaryStreamRef Stream,
+ uint32_t Offset);
+
} // end namespace codeview
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
index b63ced5217b44..f4d8ab0c3c2ed 100644
--- a/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
+++ b/include/llvm/DebugInfo/CodeView/SymbolSerializer.h
@@ -28,7 +28,10 @@ namespace codeview {
class SymbolSerializer : public SymbolVisitorCallbacks {
BumpPtrAllocator &Storage;
- std::vector<uint8_t> RecordBuffer;
+ // Since this is a fixed size buffer, use a stack allocated buffer. This
+ // yields measurable performance increase over the repeated heap allocations
+ // when serializing many independent records via writeOneSymbol.
+ std::array<uint8_t, MaxRecordLength> RecordBuffer;
MutableBinaryByteStream Stream;
BinaryStreamWriter Writer;
SymbolRecordMapping Mapping;
diff --git a/include/llvm/DebugInfo/CodeView/TypeCollection.h b/include/llvm/DebugInfo/CodeView/TypeCollection.h
index 0f856f57a7275..e9fc9b0de8efe 100644
--- a/include/llvm/DebugInfo/CodeView/TypeCollection.h
+++ b/include/llvm/DebugInfo/CodeView/TypeCollection.h
@@ -31,6 +31,16 @@ public:
virtual bool contains(TypeIndex Index) = 0;
virtual uint32_t size() = 0;
virtual uint32_t capacity() = 0;
+
+ template <typename TFunc> void ForEachRecord(TFunc Func) {
+ Optional<TypeIndex> Next = getFirst();
+
+ while (Next.hasValue()) {
+ TypeIndex N = *Next;
+ Func(N, getType(N));
+ Next = getNext(N);
+ }
+ }
};
}
}
diff --git a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
index 965cdfd85f489..9887d901773a0 100644
--- a/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
+++ b/include/llvm/DebugInfo/CodeView/TypeDeserializer.h
@@ -52,6 +52,19 @@ public:
return Error::success();
}
+ template <typename T>
+ static Expected<T> deserializeAs(ArrayRef<uint8_t> Data) {
+ const RecordPrefix *Prefix =
+ reinterpret_cast<const RecordPrefix *>(Data.data());
+ TypeRecordKind K =
+ static_cast<TypeRecordKind>(uint16_t(Prefix->RecordKind));
+ T Record(K);
+ CVType CVT(static_cast<TypeLeafKind>(K), Data);
+ if (auto EC = deserializeAs<T>(CVT, Record))
+ return std::move(EC);
+ return Record;
+ }
+
Error visitTypeBegin(CVType &Record) override {
assert(!Mapping && "Already in a type mapping!");
Mapping = llvm::make_unique<MappingInfo>(Record.content());
diff --git a/include/llvm/DebugInfo/CodeView/TypeHashing.h b/include/llvm/DebugInfo/CodeView/TypeHashing.h
new file mode 100644
index 0000000000000..741337533701c
--- /dev/null
+++ b/include/llvm/DebugInfo/CodeView/TypeHashing.h
@@ -0,0 +1,204 @@
+//===- TypeHashing.h ---------------------------------------------*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPEHASHING_H
+#define LLVM_DEBUGINFO_CODEVIEW_TYPEHASHING_H
+
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/Hashing.h"
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/TypeCollection.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+
+#include "llvm/Support/FormatProviders.h"
+
+#include <type_traits>
+
+namespace llvm {
+namespace codeview {
+
+/// A locally hashed type represents a straightforward hash code of a serialized
+/// record. The record is simply serialized, and then the bytes are hashed by
+/// a standard algorithm. This is sufficient for the case of de-duplicating
+/// records within a single sequence of types, because if two records both have
+/// a back-reference to the same type in the same stream, they will both have
+/// the same numeric value for the TypeIndex of the back reference.
+struct LocallyHashedType {
+ hash_code Hash;
+ ArrayRef<uint8_t> RecordData;
+
+ /// Given a type, compute its local hash.
+ static LocallyHashedType hashType(ArrayRef<uint8_t> RecordData);
+
+ /// Given a sequence of types, compute all of the local hashes.
+ template <typename Range>
+ static std::vector<LocallyHashedType> hashTypes(Range &&Records) {
+ std::vector<LocallyHashedType> Hashes;
+ Hashes.reserve(std::distance(std::begin(Records), std::end(Records)));
+ for (const auto &R : Records)
+ Hashes.push_back(hashType(R));
+
+ return Hashes;
+ }
+
+ static std::vector<LocallyHashedType>
+ hashTypeCollection(TypeCollection &Types) {
+ std::vector<LocallyHashedType> Hashes;
+ Types.ForEachRecord([&Hashes](TypeIndex TI, const CVType &Type) {
+ Hashes.push_back(hashType(Type.RecordData));
+ });
+ return Hashes;
+ }
+};
+
+enum class GlobalTypeHashAlg : uint16_t { SHA1 = 0 };
+
+/// A globally hashed type represents a hash value that is sufficient to
+/// uniquely identify a record across multiple type streams or type sequences.
+/// This works by, for any given record A which references B, replacing the
+/// TypeIndex that refers to B with a previously-computed global hash for B. As
+/// this is a recursive algorithm (e.g. the global hash of B also depends on the
+/// global hashes of the types that B refers to), a global hash can uniquely
+/// identify identify that A occurs in another stream that has a completely
+/// different graph structure. Although the hash itself is slower to compute,
+/// probing is much faster with a globally hashed type, because the hash itself
+/// is considered "as good as" the original type. Since type records can be
+/// quite large, this makes the equality comparison of the hash much faster than
+/// equality comparison of a full record.
+struct GloballyHashedType {
+ GloballyHashedType() = default;
+ GloballyHashedType(StringRef H)
+ : GloballyHashedType(ArrayRef<uint8_t>(H.bytes_begin(), H.bytes_end())) {}
+ GloballyHashedType(ArrayRef<uint8_t> H) {
+ assert(H.size() == 20);
+ ::memcpy(Hash.data(), H.data(), 20);
+ }
+ std::array<uint8_t, 20> 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
+ /// that RecordData might reference, indexable by TypeIndex.
+ static GloballyHashedType hashType(ArrayRef<uint8_t> RecordData,
+ ArrayRef<GloballyHashedType> PreviousTypes,
+ ArrayRef<GloballyHashedType> PreviousIds);
+
+ /// 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
+ /// that RecordData might reference, indexable by TypeIndex.
+ static GloballyHashedType hashType(CVType Type,
+ ArrayRef<GloballyHashedType> PreviousTypes,
+ ArrayRef<GloballyHashedType> PreviousIds) {
+ return hashType(Type.RecordData, PreviousTypes, PreviousIds);
+ }
+
+ /// Given a sequence of combined type and ID records, compute global hashes
+ /// for each of them, returning the results in a vector of hashed types.
+ template <typename Range>
+ static std::vector<GloballyHashedType> hashTypes(Range &&Records) {
+ std::vector<GloballyHashedType> Hashes;
+ for (const auto &R : Records)
+ Hashes.push_back(hashType(R, Hashes, Hashes));
+
+ return Hashes;
+ }
+
+ /// Given a sequence of combined type and ID records, compute global hashes
+ /// for each of them, returning the results in a vector of hashed types.
+ template <typename Range>
+ static std::vector<GloballyHashedType>
+ hashIds(Range &&Records, ArrayRef<GloballyHashedType> TypeHashes) {
+ std::vector<GloballyHashedType> IdHashes;
+ for (const auto &R : Records)
+ IdHashes.push_back(hashType(R, TypeHashes, IdHashes));
+
+ return IdHashes;
+ }
+
+ static std::vector<GloballyHashedType>
+ hashTypeCollection(TypeCollection &Types) {
+ std::vector<GloballyHashedType> Hashes;
+ Types.ForEachRecord([&Hashes](TypeIndex TI, const CVType &Type) {
+ Hashes.push_back(hashType(Type.RecordData, Hashes, Hashes));
+ });
+ 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> {
+ static codeview::LocallyHashedType Empty;
+ static codeview::LocallyHashedType Tombstone;
+
+ static codeview::LocallyHashedType getEmptyKey() { return Empty; }
+
+ static codeview::LocallyHashedType getTombstoneKey() { return Tombstone; }
+
+ static unsigned getHashValue(codeview::LocallyHashedType Val) {
+ return Val.Hash;
+ }
+
+ static bool isEqual(codeview::LocallyHashedType LHS,
+ codeview::LocallyHashedType RHS) {
+ if (LHS.Hash != RHS.Hash)
+ return false;
+ return LHS.RecordData == RHS.RecordData;
+ }
+};
+
+template <> struct DenseMapInfo<codeview::GloballyHashedType> {
+ static codeview::GloballyHashedType Empty;
+ static codeview::GloballyHashedType Tombstone;
+
+ static codeview::GloballyHashedType getEmptyKey() { return Empty; }
+
+ static codeview::GloballyHashedType getTombstoneKey() { return Tombstone; }
+
+ static unsigned getHashValue(codeview::GloballyHashedType Val) {
+ return *reinterpret_cast<const unsigned *>(Val.Hash.data());
+ }
+
+ static bool isEqual(codeview::GloballyHashedType LHS,
+ codeview::GloballyHashedType RHS) {
+ return LHS.Hash == RHS.Hash;
+ }
+};
+
+template <> struct format_provider<codeview::LocallyHashedType> {
+public:
+ static void format(const codeview::LocallyHashedType &V,
+ llvm::raw_ostream &Stream, StringRef Style) {
+ write_hex(Stream, V.Hash, HexPrintStyle::Upper, 8);
+ }
+};
+
+template <> struct format_provider<codeview::GloballyHashedType> {
+public:
+ static void format(const codeview::GloballyHashedType &V,
+ llvm::raw_ostream &Stream, StringRef Style) {
+ for (uint8_t B : V.Hash) {
+ write_hex(Stream, B, HexPrintStyle::Upper, 2);
+ }
+ }
+};
+
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/CodeView/TypeIndex.h b/include/llvm/DebugInfo/CodeView/TypeIndex.h
index e0c2226bdbd74..c71281de71455 100644
--- a/include/llvm/DebugInfo/CodeView/TypeIndex.h
+++ b/include/llvm/DebugInfo/CodeView/TypeIndex.h
@@ -98,6 +98,7 @@ public:
static const uint32_t FirstNonSimpleIndex = 0x1000;
static const uint32_t SimpleKindMask = 0x000000ff;
static const uint32_t SimpleModeMask = 0x00000700;
+ static const uint32_t DecoratedItemIdMask = 0x80000000;
public:
TypeIndex() : Index(static_cast<uint32_t>(SimpleTypeKind::None)) {}
@@ -110,6 +111,7 @@ public:
uint32_t getIndex() const { return Index; }
void setIndex(uint32_t I) { Index = I; }
bool isSimple() const { return Index < FirstNonSimpleIndex; }
+ bool isDecoratedItemId() const { return !!(Index & DecoratedItemIdMask); }
bool isNoneType() const { return *this == None(); }
diff --git a/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h b/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
index afe8942159e84..c424a09ece890 100644
--- a/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
+++ b/include/llvm/DebugInfo/CodeView/TypeIndexDiscovery.h
@@ -30,11 +30,17 @@ void discoverTypeIndices(const CVType &Type,
SmallVectorImpl<TiReference> &Refs);
void discoverTypeIndices(const CVType &Type,
SmallVectorImpl<TypeIndex> &Indices);
+void discoverTypeIndices(ArrayRef<uint8_t> RecordData,
+ SmallVectorImpl<TypeIndex> &Indices);
/// Discover type indices in symbol records. Returns false if this is an unknown
/// record.
-bool discoverTypeIndices(const CVSymbol &Symbol,
- SmallVectorImpl<TiReference> &Refs);
+bool discoverTypeIndicesInSymbol(const CVSymbol &Symbol,
+ SmallVectorImpl<TiReference> &Refs);
+bool discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData,
+ SmallVectorImpl<TiReference> &Refs);
+bool discoverTypeIndicesInSymbol(ArrayRef<uint8_t> RecordData,
+ SmallVectorImpl<TypeIndex> &Indices);
}
}
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecord.h b/include/llvm/DebugInfo/CodeView/TypeRecord.h
index 7942c0c0bc215..508bdd395f74e 100644
--- a/include/llvm/DebugInfo/CodeView/TypeRecord.h
+++ b/include/llvm/DebugInfo/CodeView/TypeRecord.h
@@ -334,6 +334,11 @@ public:
uint32_t Attrs;
Optional<MemberPointerInfo> MemberInfo;
+ void setAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
+ uint8_t Size) {
+ Attrs = calcAttrs(PK, PM, PO, Size);
+ }
+
private:
static uint32_t calcAttrs(PointerKind PK, PointerMode PM, PointerOptions PO,
uint8_t Size) {
@@ -412,6 +417,14 @@ public:
return (Options & ClassOptions::HasUniqueName) != ClassOptions::None;
}
+ bool isNested() const {
+ return (Options & ClassOptions::Nested) != ClassOptions::None;
+ }
+
+ bool isForwardRef() const {
+ return (Options & ClassOptions::ForwardReference) != ClassOptions::None;
+ }
+
uint16_t getMemberCount() const { return MemberCount; }
ClassOptions getOptions() const { return Options; }
TypeIndex getFieldList() const { return FieldList; }
diff --git a/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h b/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
deleted file mode 100644
index 5a6507ee7f5b4..0000000000000
--- a/include/llvm/DebugInfo/CodeView/TypeRecordBuilder.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//===- TypeRecordBuilder.h --------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPERECORDBUILDER_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPERECORDBUILDER_H
-
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/Support/EndianStream.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace llvm {
-namespace codeview {
-
-class TypeRecordBuilder {
-private:
- TypeRecordBuilder(const TypeRecordBuilder &) = delete;
- TypeRecordBuilder &operator=(const TypeRecordBuilder &) = delete;
-
-public:
- explicit TypeRecordBuilder(TypeRecordKind Kind);
-
- void writeUInt8(uint8_t Value);
- void writeInt16(int16_t Value);
- void writeUInt16(uint16_t Value);
- void writeInt32(int32_t Value);
- void writeUInt32(uint32_t Value);
- void writeInt64(int64_t Value);
- void writeUInt64(uint64_t Value);
- void writeTypeIndex(TypeIndex TypeInd);
- void writeTypeRecordKind(TypeRecordKind Kind);
- void writeEncodedInteger(int64_t Value);
- void writeEncodedSignedInteger(int64_t Value);
- void writeEncodedUnsignedInteger(uint64_t Value);
- void writeNullTerminatedString(StringRef Value);
- void writeGuid(StringRef Guid);
- void writeBytes(StringRef Value) { Stream << Value; }
-
- llvm::StringRef str();
-
- uint64_t size() const { return Stream.tell(); }
- TypeRecordKind kind() const { return Kind; }
-
- /// Returns the number of bytes remaining before this record is larger than
- /// the maximum record length. Accounts for the extra two byte size field in
- /// the header.
- size_t maxBytesRemaining() const { return MaxRecordLength - size() - 2; }
-
- void truncate(uint64_t Size) {
- // This works because raw_svector_ostream is not buffered.
- assert(Size < Buffer.size());
- Buffer.resize(Size);
- }
-
- void reset(TypeRecordKind K) {
- Buffer.clear();
- Kind = K;
- writeTypeRecordKind(K);
- }
-
-private:
- TypeRecordKind Kind;
- llvm::SmallVector<char, 256> Buffer;
- llvm::raw_svector_ostream Stream;
- llvm::support::endian::Writer<llvm::support::endianness::little> Writer;
-};
-}
-}
-
-#endif
diff --git a/include/llvm/DebugInfo/CodeView/TypeSerializer.h b/include/llvm/DebugInfo/CodeView/TypeSerializer.h
deleted file mode 100644
index 0e734a8170bdf..0000000000000
--- a/include/llvm/DebugInfo/CodeView/TypeSerializer.h
+++ /dev/null
@@ -1,159 +0,0 @@
-//===- TypeSerializer.h -----------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_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 TypeHasher;
-
-class TypeSerializer : public TypeVisitorCallbacks {
- struct SubRecord {
- SubRecord(TypeLeafKind K, uint32_t S) : Kind(K), Size(S) {}
-
- TypeLeafKind Kind;
- uint32_t Size = 0;
- };
- struct RecordSegment {
- SmallVector<SubRecord, 16> SubRecords;
-
- uint32_t length() const {
- uint32_t L = sizeof(RecordPrefix);
- for (const auto &R : SubRecords) {
- L += R.Size;
- }
- return L;
- }
- };
-
- using MutableRecordList = SmallVector<MutableArrayRef<uint8_t>, 2>;
-
- static constexpr uint8_t ContinuationLength = 8;
- BumpPtrAllocator &RecordStorage;
- RecordSegment CurrentSegment;
- MutableRecordList FieldListSegments;
-
- Optional<TypeLeafKind> TypeKind;
- Optional<TypeLeafKind> MemberKind;
- std::vector<uint8_t> RecordBuffer;
- MutableBinaryByteStream Stream;
- BinaryStreamWriter Writer;
- TypeRecordMapping Mapping;
-
- /// Private type record hashing implementation details are handled here.
- std::unique_ptr<TypeHasher> Hasher;
-
- /// Contains a list of all records indexed by TypeIndex.toArrayIndex().
- SmallVector<ArrayRef<uint8_t>, 2> SeenRecords;
-
- /// Temporary storage that we use to copy a record's data while re-writing
- /// its type indices.
- SmallVector<uint8_t, 256> RemapStorage;
-
- TypeIndex nextTypeIndex() const;
-
- bool isInFieldList() const;
- MutableArrayRef<uint8_t> getCurrentSubRecordData();
- MutableArrayRef<uint8_t> getCurrentRecordData();
- Error writeRecordPrefix(TypeLeafKind Kind);
-
- Expected<MutableArrayRef<uint8_t>>
- addPadding(MutableArrayRef<uint8_t> Record);
-
-public:
- explicit TypeSerializer(BumpPtrAllocator &Storage, bool Hash = true);
- ~TypeSerializer() override;
-
- void reset();
-
- BumpPtrAllocator &getAllocator() { return RecordStorage; }
-
- ArrayRef<ArrayRef<uint8_t>> records() const;
- TypeIndex insertRecordBytes(ArrayRef<uint8_t> &Record);
- TypeIndex insertRecord(const RemappedType &Record);
- Expected<TypeIndex> visitTypeEndGetIndex(CVType &Record);
-
- using TypeVisitorCallbacks::visitTypeBegin;
- Error visitTypeBegin(CVType &Record) override;
- Error visitTypeEnd(CVType &Record) override;
- Error visitMemberBegin(CVMemberRecord &Record) override;
- Error visitMemberEnd(CVMemberRecord &Record) override;
-
-#define TYPE_RECORD(EnumName, EnumVal, Name) \
- virtual Error visitKnownRecord(CVType &CVR, Name##Record &Record) override { \
- return visitKnownRecordImpl(CVR, Record); \
- }
-#define TYPE_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#define MEMBER_RECORD(EnumName, EnumVal, Name) \
- Error visitKnownMember(CVMemberRecord &CVR, Name##Record &Record) override { \
- return visitKnownMemberImpl<Name##Record>(CVR, Record); \
- }
-#define MEMBER_RECORD_ALIAS(EnumName, EnumVal, Name, AliasName)
-#include "llvm/DebugInfo/CodeView/CodeViewTypes.def"
-
-private:
- template <typename RecordKind>
- Error visitKnownRecordImpl(CVType &CVR, RecordKind &Record) {
- return Mapping.visitKnownRecord(CVR, Record);
- }
-
- template <typename RecordType>
- Error visitKnownMemberImpl(CVMemberRecord &CVR, RecordType &Record) {
- assert(CVR.Kind == static_cast<TypeLeafKind>(Record.getKind()));
-
- if (auto EC = Writer.writeEnum(CVR.Kind))
- return EC;
-
- if (auto EC = Mapping.visitKnownMember(CVR, Record))
- return EC;
-
- // Get all the data that was just written and is yet to be committed to
- // the current segment. Then pad it to 4 bytes.
- MutableArrayRef<uint8_t> ThisRecord = getCurrentSubRecordData();
- auto ExpectedRecord = addPadding(ThisRecord);
- if (!ExpectedRecord)
- return ExpectedRecord.takeError();
- ThisRecord = *ExpectedRecord;
-
- CurrentSegment.SubRecords.emplace_back(CVR.Kind, ThisRecord.size());
- CVR.Data = ThisRecord;
-
- // Both the last subrecord and the total length of this segment should be
- // multiples of 4.
- assert(ThisRecord.size() % 4 == 0);
- assert(CurrentSegment.length() % 4 == 0);
-
- return Error::success();
- }
-};
-
-} // end namespace codeview
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_CODEVIEW_TYPESERIALIZER_H
diff --git a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
index d78fab47db668..59e216abcb11c 100644
--- a/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
+++ b/include/llvm/DebugInfo/CodeView/TypeStreamMerger.h
@@ -19,7 +19,9 @@ namespace llvm {
namespace codeview {
class TypeIndex;
-class TypeTableBuilder;
+struct GloballyHashedType;
+class GlobalTypeTableBuilder;
+class MergingTypeTableBuilder;
/// \brief Merge one set of type records into another. This method assumes
/// that all records are type records, and there are no Id records present.
@@ -34,7 +36,7 @@ class TypeTableBuilder;
///
/// \returns Error::success() if the operation succeeded, otherwise an
/// appropriate error code.
-Error mergeTypeRecords(TypeTableBuilder &Dest,
+Error mergeTypeRecords(MergingTypeTableBuilder &Dest,
SmallVectorImpl<TypeIndex> &SourceToDest,
const CVTypeArray &Types);
@@ -59,7 +61,7 @@ Error mergeTypeRecords(TypeTableBuilder &Dest,
///
/// \returns Error::success() if the operation succeeded, otherwise an
/// appropriate error code.
-Error mergeIdRecords(TypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
+Error mergeIdRecords(MergingTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
SmallVectorImpl<TypeIndex> &SourceToDest,
const CVTypeArray &Ids);
@@ -78,11 +80,27 @@ Error mergeIdRecords(TypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
///
/// \returns Error::success() if the operation succeeded, otherwise an
/// appropriate error code.
-Error mergeTypeAndIdRecords(TypeTableBuilder &DestIds,
- TypeTableBuilder &DestTypes,
+Error mergeTypeAndIdRecords(MergingTypeTableBuilder &DestIds,
+ MergingTypeTableBuilder &DestTypes,
SmallVectorImpl<TypeIndex> &SourceToDest,
const CVTypeArray &IdsAndTypes);
+Error mergeTypeAndIdRecords(GlobalTypeTableBuilder &DestIds,
+ GlobalTypeTableBuilder &DestTypes,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &IdsAndTypes,
+ ArrayRef<GloballyHashedType> Hashes);
+
+Error mergeTypeRecords(GlobalTypeTableBuilder &Dest,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Types,
+ ArrayRef<GloballyHashedType> Hashes);
+
+Error mergeIdRecords(GlobalTypeTableBuilder &Dest, ArrayRef<TypeIndex> Types,
+ SmallVectorImpl<TypeIndex> &SourceToDest,
+ const CVTypeArray &Ids,
+ ArrayRef<GloballyHashedType> Hashes);
+
} // end namespace codeview
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h b/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
deleted file mode 100644
index 1069dcd453349..0000000000000
--- a/include/llvm/DebugInfo/CodeView/TypeTableBuilder.h
+++ /dev/null
@@ -1,137 +0,0 @@
-//===- TypeTableBuilder.h ---------------------------------------*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
-#define LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
-
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/DebugInfo/CodeView/CodeView.h"
-#include "llvm/DebugInfo/CodeView/TypeIndex.h"
-#include "llvm/DebugInfo/CodeView/TypeRecord.h"
-#include "llvm/DebugInfo/CodeView/TypeSerializer.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Error.h"
-#include <algorithm>
-#include <cassert>
-#include <cstdint>
-#include <type_traits>
-
-namespace llvm {
-namespace codeview {
-
-class TypeTableBuilder {
-private:
- TypeIndex handleError(Error EC) const {
- assert(false && "Couldn't write Type!");
- consumeError(std::move(EC));
- return TypeIndex();
- }
-
- BumpPtrAllocator &Allocator;
- TypeSerializer Serializer;
-
-public:
- explicit TypeTableBuilder(BumpPtrAllocator &Allocator,
- bool WriteUnique = true)
- : Allocator(Allocator), Serializer(Allocator, WriteUnique) {}
- TypeTableBuilder(const TypeTableBuilder &) = delete;
- TypeTableBuilder &operator=(const TypeTableBuilder &) = delete;
-
- bool empty() const { return Serializer.records().empty(); }
-
- BumpPtrAllocator &getAllocator() const { return Allocator; }
-
- template <typename T> TypeIndex writeKnownType(T &Record) {
- static_assert(!std::is_same<T, FieldListRecord>::value,
- "Can't serialize FieldList!");
-
- CVType Type;
- Type.Type = static_cast<TypeLeafKind>(Record.getKind());
- if (auto EC = Serializer.visitTypeBegin(Type))
- return handleError(std::move(EC));
- if (auto EC = Serializer.visitKnownRecord(Type, Record))
- return handleError(std::move(EC));
-
- auto ExpectedIndex = Serializer.visitTypeEndGetIndex(Type);
- if (!ExpectedIndex)
- return handleError(ExpectedIndex.takeError());
-
- return *ExpectedIndex;
- }
-
- TypeIndex writeSerializedRecord(ArrayRef<uint8_t> Record) {
- return Serializer.insertRecordBytes(Record);
- }
-
- TypeIndex writeSerializedRecord(const RemappedType &Record) {
- return Serializer.insertRecord(Record);
- }
-
- template <typename TFunc> void ForEachRecord(TFunc Func) {
- uint32_t Index = TypeIndex::FirstNonSimpleIndex;
-
- for (auto Record : Serializer.records()) {
- Func(TypeIndex(Index), Record);
- ++Index;
- }
- }
-
- ArrayRef<ArrayRef<uint8_t>> records() const { return Serializer.records(); }
-};
-
-class FieldListRecordBuilder {
- TypeTableBuilder &TypeTable;
- BumpPtrAllocator Allocator;
- TypeSerializer TempSerializer;
- CVType Type;
-
-public:
- explicit FieldListRecordBuilder(TypeTableBuilder &TypeTable)
- : TypeTable(TypeTable), TempSerializer(Allocator, false) {
- Type.Type = TypeLeafKind::LF_FIELDLIST;
- }
-
- void begin() {
- TempSerializer.reset();
-
- if (auto EC = TempSerializer.visitTypeBegin(Type))
- consumeError(std::move(EC));
- }
-
- template <typename T> void writeMemberType(T &Record) {
- CVMemberRecord CVMR;
- CVMR.Kind = static_cast<TypeLeafKind>(Record.getKind());
- if (auto EC = TempSerializer.visitMemberBegin(CVMR))
- consumeError(std::move(EC));
- if (auto EC = TempSerializer.visitKnownMember(CVMR, Record))
- consumeError(std::move(EC));
- if (auto EC = TempSerializer.visitMemberEnd(CVMR))
- consumeError(std::move(EC));
- }
-
- TypeIndex end(bool Write) {
- TypeIndex Index;
- if (auto EC = TempSerializer.visitTypeEnd(Type)) {
- consumeError(std::move(EC));
- return TypeIndex();
- }
-
- if (Write) {
- for (auto Record : TempSerializer.records())
- Index = TypeTable.writeSerializedRecord(Record);
- }
-
- return Index;
- }
-};
-
-} // end namespace codeview
-} // end namespace llvm
-
-#endif // LLVM_DEBUGINFO_CODEVIEW_TYPETABLEBUILDER_H
diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h
index 936813dc6abc0..abace93786077 100644
--- a/include/llvm/DebugInfo/DIContext.h
+++ b/include/llvm/DebugInfo/DIContext.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/raw_ostream.h"
#include <cassert>
#include <cstdint>
#include <memory>
@@ -26,9 +27,7 @@
namespace llvm {
-class raw_ostream;
-
-/// DILineInfo - a format-neutral container for source line information.
+/// A format-neutral container for source line information.
struct DILineInfo {
std::string FileName;
std::string FunctionName;
@@ -46,20 +45,35 @@ struct DILineInfo {
FileName == RHS.FileName && FunctionName == RHS.FunctionName &&
StartLine == RHS.StartLine && Discriminator == RHS.Discriminator;
}
+
bool operator!=(const DILineInfo &RHS) const {
return !(*this == RHS);
}
+
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);
}
+
+ explicit operator bool() const { return *this != DILineInfo(); }
+
+ void dump(raw_ostream &OS) {
+ OS << "Line info: ";
+ if (FileName != "<invalid>")
+ OS << "file '" << FileName << "', ";
+ if (FunctionName != "<invalid>")
+ OS << "function '" << FunctionName << "', ";
+ OS << "line " << Line << ", ";
+ OS << "column " << Column << ", ";
+ OS << "start line " << StartLine << '\n';
+ }
};
using DILineInfoTable = SmallVector<std::pair<uint64_t, DILineInfo>, 16>;
-/// DIInliningInfo - a format-neutral container for inlined code description.
+/// A format-neutral container for inlined code description.
class DIInliningInfo {
SmallVector<DILineInfo, 4> Frames;
@@ -85,7 +99,7 @@ public:
}
};
-/// DIGlobal - container for description of a global variable.
+/// Container for description of a global variable.
struct DIGlobal {
std::string Name;
uint64_t Start = 0;
@@ -98,8 +112,8 @@ struct DIGlobal {
/// preference regarding the type of name resolution the caller wants.
enum class DINameKind { None, ShortName, LinkageName };
-/// DILineInfoSpecifier - controls which fields of DILineInfo container
-/// should be filled with data.
+/// Controls which fields of DILineInfo container should be filled
+/// with data.
struct DILineInfoSpecifier {
enum class FileLineInfoKind { None, Default, AbsoluteFilePath };
using FunctionNameKind = DINameKind;
@@ -112,48 +126,54 @@ struct DILineInfoSpecifier {
: 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) \
+ DIDT_ID_##ENUM_NAME,
+#include "llvm/BinaryFormat/Dwarf.def"
+#undef HANDLE_DWARF_SECTION
+ DIDT_ID_UUID,
+ DIDT_ID_Count
+};
+static_assert(DIDT_ID_Count <= 32, "section types overflow storage");
+
/// Selects which debug sections get dumped.
-enum DIDumpType {
+enum DIDumpType : unsigned {
DIDT_Null,
- DIDT_All,
- DIDT_Abbrev,
- DIDT_AbbrevDwo,
- DIDT_Aranges,
- DIDT_Frames,
- DIDT_Info,
- DIDT_InfoDwo,
- DIDT_Types,
- DIDT_TypesDwo,
- DIDT_Line,
- DIDT_LineDwo,
- DIDT_Loc,
- DIDT_LocDwo,
- DIDT_Macro,
- DIDT_Ranges,
- DIDT_Pubnames,
- DIDT_Pubtypes,
- DIDT_GnuPubnames,
- DIDT_GnuPubtypes,
- DIDT_Str,
- DIDT_StrOffsets,
- DIDT_StrDwo,
- DIDT_StrOffsetsDwo,
- DIDT_AppleNames,
- DIDT_AppleTypes,
- DIDT_AppleNamespaces,
- DIDT_AppleObjC,
- DIDT_CUIndex,
- DIDT_GdbIndex,
- DIDT_TUIndex,
+ DIDT_All = ~0U,
+#define HANDLE_DWARF_SECTION(ENUM_NAME, ELF_NAME, CMDLINE_NAME) \
+ DIDT_##ENUM_NAME = 1U << DIDT_ID_##ENUM_NAME,
+#include "llvm/BinaryFormat/Dwarf.def"
+#undef HANDLE_DWARF_SECTION
+ DIDT_UUID = 1 << DIDT_ID_UUID,
};
/// Container for dump options that control which debug information will be
/// dumped.
struct DIDumpOptions {
- DIDumpType DumpType = DIDT_All;
- bool DumpEH = false;
- bool SummarizeTypes = false;
- bool Brief = false;
+ unsigned DumpType = DIDT_All;
+ unsigned RecurseDepth = -1U;
+ bool ShowAddresses = true;
+ bool ShowChildren = false;
+ bool ShowParents = false;
+ bool ShowForm = false;
+ bool SummarizeTypes = false;
+ bool Verbose = false;
+
+ /// Return default option set for printing a single DIE without children.
+ static DIDumpOptions getForSingleDIE() {
+ DIDumpOptions Opts;
+ Opts.RecurseDepth = 0;
+ return Opts;
+ }
+
+ /// Return the options with RecurseDepth set to 0 unless explicitly required.
+ DIDumpOptions noImplicitRecursion() const {
+ DIDumpOptions Opts = *this;
+ if (RecurseDepth == -1U && !ShowChildren)
+ Opts.RecurseDepth = 0;
+ return Opts;
+ }
};
class DIContext {
@@ -170,7 +190,7 @@ public:
virtual void dump(raw_ostream &OS, DIDumpOptions DumpOpts) = 0;
- virtual bool verify(raw_ostream &OS, DIDumpType DumpType = DIDT_All) {
+ virtual bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) {
// No verifier? Just say things went well.
return true;
}
@@ -202,22 +222,23 @@ public:
/// Calculate the address of the given section.
/// The section need not be present in the local address space. The addresses
/// need to be consistent with the addresses used to query the DIContext and
- /// the output of this function should be deterministic, i.e. repeated calls with
- /// the same Sec should give the same address.
+ /// the output of this function should be deterministic, i.e. repeated calls
+ /// with the same Sec should give the same address.
virtual uint64_t getSectionLoadAddress(const object::SectionRef &Sec) const {
return 0;
}
/// If conveniently available, return the content of the given Section.
///
- /// When the section is available in the local address space, in relocated (loaded)
- /// form, e.g. because it was relocated by a JIT for execution, this function
- /// should provide the contents of said section in `Data`. If the loaded section
- /// is not available, or the cost of retrieving it would be prohibitive, this
- /// function should return false. In that case, relocations will be read from the
- /// local (unrelocated) object file and applied on the fly. Note that this method
- /// is used purely for optimzation purposes in the common case of JITting in the
- /// local address space, so returning false should always be correct.
+ /// When the section is available in the local address space, in relocated
+ /// (loaded) form, e.g. because it was relocated by a JIT for execution, this
+ /// function should provide the contents of said section in `Data`. If the
+ /// loaded section is not available, or the cost of retrieving it would be
+ /// prohibitive, this function should return false. In that case, relocations
+ /// will be read from the local (unrelocated) object file and applied on the
+ /// fly. Note that this method is used purely for optimzation purposes in the
+ /// common case of JITting in the local address space, so returning false
+ /// should always be correct.
virtual bool getLoadedSectionContents(const object::SectionRef &Sec,
StringRef &Data) const {
return false;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
index 190a69b757390..84b23398b8ccd 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h
@@ -28,31 +28,54 @@ class raw_ostream;
class DWARFAbbreviationDeclaration {
public:
struct AttributeSpec {
- AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<int64_t> V)
- : Attr(A), Form(F), ByteSizeOrValue(V) {}
+ AttributeSpec(dwarf::Attribute A, dwarf::Form F, int64_t Value)
+ : Attr(A), Form(F), Value(Value) {
+ assert(isImplicitConst());
+ }
+ AttributeSpec(dwarf::Attribute A, dwarf::Form F, Optional<uint8_t> ByteSize)
+ : Attr(A), Form(F) {
+ assert(!isImplicitConst());
+ this->ByteSize.HasByteSize = ByteSize.hasValue();
+ if (this->ByteSize.HasByteSize)
+ this->ByteSize.ByteSize = *ByteSize;
+ }
dwarf::Attribute Attr;
dwarf::Form Form;
+ private:
/// The following field is used for ByteSize for non-implicit_const
/// attributes and as value for implicit_const ones, indicated by
/// Form == DW_FORM_implicit_const.
/// The following cases are distinguished:
- /// * Form != DW_FORM_implicit_const and ByteSizeOrValue has a value:
- /// ByteSizeOrValue contains the fixed size in bytes
- /// for the Form in this object.
- /// * Form != DW_FORM_implicit_const and ByteSizeOrValue is None:
+ /// * Form != DW_FORM_implicit_const and HasByteSize is true:
+ /// ByteSize contains the fixed size in bytes for the Form in this
+ /// object.
+ /// * Form != DW_FORM_implicit_const and HasByteSize is false:
/// byte size of Form either varies according to the DWARFUnit
/// that it is contained in or the value size varies and must be
/// decoded from the debug information in order to determine its size.
/// * Form == DW_FORM_implicit_const:
- /// ByteSizeOrValue contains value for the implicit_const attribute.
- Optional<int64_t> ByteSizeOrValue;
-
+ /// Value contains value for the implicit_const attribute.
+ struct ByteSizeStorage {
+ bool HasByteSize;
+ uint8_t ByteSize;
+ };
+ union {
+ ByteSizeStorage ByteSize;
+ int64_t Value;
+ };
+
+ public:
bool isImplicitConst() const {
return Form == dwarf::DW_FORM_implicit_const;
}
+ int64_t getImplicitConstValue() const {
+ assert(isImplicitConst());
+ return Value;
+ }
+
/// Get the fixed byte size of this Form if possible. This function might
/// use the DWARFUnit to calculate the size of the Form, like for
/// DW_AT_address and DW_AT_ref_addr, so this isn't just an accessor for
diff --git a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
index eb6d0f541c1ed..0bade10f6201b 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h
@@ -13,7 +13,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/Dwarf.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
-#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include <cstdint>
#include <utility>
@@ -21,6 +21,9 @@ namespace llvm {
class raw_ostream;
+/// This implements the Apple accelerator table format, a precursor of the
+/// DWARF 5 accelerator table format.
+/// TODO: Factor out a common base class for both formats.
class DWARFAcceleratorTable {
struct Header {
uint32_t Magic;
@@ -43,13 +46,51 @@ class DWARFAcceleratorTable {
struct HeaderData HdrData;
DWARFDataExtractor AccelSection;
DataExtractor StringSection;
+ bool IsValid = false;
public:
+ /// An iterator for the entries associated with one key. Each entry can have
+ /// multiple DWARFFormValues.
+ class ValueIterator : public std::iterator<std::input_iterator_tag,
+ ArrayRef<DWARFFormValue>> {
+ const DWARFAcceleratorTable *AccelTable = nullptr;
+ SmallVector<DWARFFormValue, 3> AtomForms; ///< The decoded data entry.
+
+ unsigned DataOffset = 0; ///< Offset into the section.
+ unsigned Data = 0; ///< Current data entry.
+ unsigned NumData = 0; ///< Number of data entries.
+
+ /// Advance the iterator.
+ void Next();
+ public:
+ /// Construct a new iterator for the entries at \p DataOffset.
+ ValueIterator(const DWARFAcceleratorTable &AccelTable, unsigned DataOffset);
+ /// End marker.
+ ValueIterator() = default;
+
+ const ArrayRef<DWARFFormValue> operator*() const {
+ return AtomForms;
+ }
+ ValueIterator &operator++() { Next(); return *this; }
+ ValueIterator operator++(int) {
+ ValueIterator I = *this;
+ Next();
+ return I;
+ }
+ friend bool operator==(const ValueIterator &A, const ValueIterator &B) {
+ return A.NumData == B.NumData && A.DataOffset == B.DataOffset;
+ }
+ friend bool operator!=(const ValueIterator &A, const ValueIterator &B) {
+ return !(A == B);
+ }
+ };
+
+
DWARFAcceleratorTable(const DWARFDataExtractor &AccelSection,
DataExtractor StringSection)
: AccelSection(AccelSection), StringSection(StringSection) {}
- bool extract();
+ llvm::Error extract();
uint32_t getNumBuckets();
uint32_t getNumHashes();
uint32_t getSizeHdr();
@@ -61,12 +102,15 @@ public:
/// performing a lookup by name.
///
/// \param HashDataOffset an offset into the hash data table
- /// \returns DIEOffset the offset into the .debug_info section for the DIE
- /// related to the input hash data offset. Currently this function returns
- /// only the DIEOffset but it can be modified to return more data regarding
- /// the DIE
- uint32_t readAtoms(uint32_t &HashDataOffset);
+ /// \returns <DieOffset, DieTag>
+ /// 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);
void dump(raw_ostream &OS) const;
+
+ /// Look up all entries in the accelerator table matching \c Key.
+ iterator_range<ValueIterator> equal_range(StringRef Key) const;
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFContext.h b/include/llvm/DebugInfo/DWARF/DWARFContext.h
index ee2e805050c01..2ddbc4b91ba2e 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFContext.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFContext.h
@@ -17,6 +17,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
@@ -26,6 +27,7 @@
#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
#include "llvm/DebugInfo/DWARF/DWARFDie.h"
#include "llvm/DebugInfo/DWARF/DWARFGdbIndex.h"
+#include "llvm/DebugInfo/DWARF/DWARFObject.h"
#include "llvm/DebugInfo/DWARF/DWARFSection.h"
#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
@@ -42,13 +44,18 @@
namespace llvm {
class DataExtractor;
+class MCRegisterInfo;
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 pure virtual
-/// methods that a concrete implementation provides.
+/// information parsing. The actual data is supplied through DWARFObj.
class DWARFContext : public DIContext {
DWARFUnitSection<DWARFCompileUnit> CUs;
std::deque<DWARFUnitSection<DWARFTypeUnit>> TUs;
@@ -62,6 +69,10 @@ class DWARFContext : public DIContext {
std::unique_ptr<DWARFDebugFrame> DebugFrame;
std::unique_ptr<DWARFDebugFrame> EHFrame;
std::unique_ptr<DWARFDebugMacro> Macro;
+ std::unique_ptr<DWARFAcceleratorTable> AppleNames;
+ std::unique_ptr<DWARFAcceleratorTable> AppleTypes;
+ std::unique_ptr<DWARFAcceleratorTable> AppleNamespaces;
+ std::unique_ptr<DWARFAcceleratorTable> AppleObjC;
DWARFUnitSection<DWARFCompileUnit> DWOCUs;
std::deque<DWARFUnitSection<DWARFTypeUnit>> DWOTUs;
@@ -78,6 +89,9 @@ class DWARFContext : public DIContext {
StringMap<std::weak_ptr<DWOFile>> DWOFiles;
std::weak_ptr<DWOFile> DWP;
bool CheckedForDWP = false;
+ std::string DWPName;
+
+ std::unique_ptr<MCRegisterInfo> RegInfo;
/// Read compile units from the debug_info section (if necessary)
/// and store them in CUs.
@@ -95,18 +109,34 @@ class DWARFContext : public DIContext {
/// and store them in DWOTUs.
void parseDWOTypeUnits();
+protected:
+ std::unique_ptr<const DWARFObject> DObj;
+
public:
- DWARFContext() : DIContext(CK_DWARF) {}
+ DWARFContext(std::unique_ptr<const DWARFObject> DObj,
+ std::string DWPName = "");
+ ~DWARFContext();
+
DWARFContext(DWARFContext &) = delete;
DWARFContext &operator=(DWARFContext &) = delete;
+ const DWARFObject &getDWARFObj() const { return *DObj; }
+
static bool classof(const DIContext *DICtx) {
return DICtx->getKind() == CK_DWARF;
}
- void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override;
+ /// Dump a textual representation to \p OS. If any \p DumpOffsets are present,
+ /// dump only the record at the specified offset.
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts,
+ std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets);
- bool verify(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override;
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts) override {
+ std::array<Optional<uint64_t>, DIDT_ID_Count> DumpOffsets;
+ dump(OS, DumpOpts, DumpOffsets);
+ }
+
+ bool verify(raw_ostream &OS, DIDumpOptions DumpOpts = {}) override;
using cu_iterator_range = DWARFUnitSection<DWARFCompileUnit>::iterator_range;
using tu_iterator_range = DWARFUnitSection<DWARFTypeUnit>::iterator_range;
@@ -212,9 +242,33 @@ public:
/// Get a pointer to the parsed DebugMacro object.
const DWARFDebugMacro *getDebugMacro();
+ /// Get a reference to the parsed accelerator table object.
+ const DWARFAcceleratorTable &getAppleNames();
+
+ /// Get a reference to the parsed accelerator table object.
+ const DWARFAcceleratorTable &getAppleTypes();
+
+ /// Get a reference to the parsed accelerator table object.
+ const DWARFAcceleratorTable &getAppleNamespaces();
+
+ /// Get a reference to the parsed accelerator table object.
+ const DWARFAcceleratorTable &getAppleObjC();
+
/// Get a pointer to a parsed line table corresponding to a compile unit.
const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu);
+ /// Wraps the returned DIEs for a given address.
+ struct DIEsForAddress {
+ DWARFCompileUnit *CompileUnit = nullptr;
+ DWARFDie FunctionDIE;
+ DWARFDie BlockDIE;
+ explicit operator bool() const { return CompileUnit != nullptr; }
+ };
+
+ /// Get the compilation unit, the function DIE and lexical block DIE for the
+ /// given address where applicable.
+ DIEsForAddress getDIEsForAddress(uint64_t Address);
+
DILineInfo getLineInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
@@ -222,198 +276,39 @@ public:
DIInliningInfo getInliningInfoForAddress(uint64_t Address,
DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override;
- virtual StringRef getFileName() const = 0;
- virtual bool isLittleEndian() const = 0;
- virtual uint8_t getAddressSize() const = 0;
- virtual const DWARFSection &getInfoSection() = 0;
- virtual void forEachTypesSections(function_ref<void(DWARFSection &)> F) = 0;
- virtual StringRef getAbbrevSection() = 0;
- virtual const DWARFSection &getLocSection() = 0;
- virtual StringRef getARangeSection() = 0;
- virtual StringRef getDebugFrameSection() = 0;
- virtual StringRef getEHFrameSection() = 0;
- virtual const DWARFSection &getLineSection() = 0;
- virtual StringRef getStringSection() = 0;
- virtual const DWARFSection& getRangeSection() = 0;
- virtual StringRef getMacinfoSection() = 0;
- virtual StringRef getPubNamesSection() = 0;
- virtual StringRef getPubTypesSection() = 0;
- virtual StringRef getGnuPubNamesSection() = 0;
- virtual StringRef getGnuPubTypesSection() = 0;
-
- /// DWARF v5
- /// @{
- virtual const DWARFSection &getStringOffsetSection() = 0;
- /// @}
-
- // Sections for DWARF5 split dwarf proposal.
- virtual const DWARFSection &getInfoDWOSection() = 0;
- virtual void
- forEachTypesDWOSections(function_ref<void(DWARFSection &)> F) = 0;
- virtual StringRef getAbbrevDWOSection() = 0;
- virtual const DWARFSection &getLineDWOSection() = 0;
- virtual const DWARFSection &getLocDWOSection() = 0;
- virtual StringRef getStringDWOSection() = 0;
- virtual const DWARFSection &getStringOffsetDWOSection() = 0;
- virtual const DWARFSection &getRangeDWOSection() = 0;
- virtual const DWARFSection &getAddrSection() = 0;
- virtual const DWARFSection& getAppleNamesSection() = 0;
- virtual const DWARFSection& getAppleTypesSection() = 0;
- virtual const DWARFSection& getAppleNamespacesSection() = 0;
- virtual const DWARFSection& getAppleObjCSection() = 0;
- virtual StringRef getCUIndexSection() = 0;
- virtual StringRef getGdbIndexSection() = 0;
- virtual StringRef getTUIndexSection() = 0;
-
+ bool isLittleEndian() const { return DObj->isLittleEndian(); }
static bool isSupportedVersion(unsigned version) {
return version == 2 || version == 3 || version == 4 || version == 5;
}
std::shared_ptr<DWARFContext> getDWOContext(StringRef AbsolutePath);
-private:
- /// Return the compile unit that includes an offset (relative to .debug_info).
- DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
-
- /// Return the compile unit which contains instruction with provided
- /// address.
- DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
-};
-
-/// 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 };
-
-/// DWARFContextInMemory is the simplest possible implementation of a
-/// DWARFContext. It assumes all content is available in memory and stores
-/// pointers to it.
-class DWARFContextInMemory : public DWARFContext {
- virtual void anchor();
-
- using TypeSectionMap = MapVector<object::SectionRef, DWARFSection,
- std::map<object::SectionRef, unsigned>>;
-
- StringRef FileName;
- bool IsLittleEndian;
- uint8_t AddressSize;
- DWARFSection InfoSection;
- TypeSectionMap TypesSections;
- StringRef AbbrevSection;
- DWARFSection LocSection;
- StringRef ARangeSection;
- StringRef DebugFrameSection;
- StringRef EHFrameSection;
- DWARFSection LineSection;
- StringRef StringSection;
- DWARFSection RangeSection;
- StringRef MacinfoSection;
- StringRef PubNamesSection;
- StringRef PubTypesSection;
- StringRef GnuPubNamesSection;
- StringRef GnuPubTypesSection;
-
- /// DWARF v5
- /// @{
- DWARFSection StringOffsetSection;
- /// @}
-
- // Sections for DWARF5 split dwarf proposal.
- DWARFSection InfoDWOSection;
- TypeSectionMap TypesDWOSections;
- StringRef AbbrevDWOSection;
- DWARFSection LineDWOSection;
- DWARFSection LocDWOSection;
- StringRef StringDWOSection;
- DWARFSection StringOffsetDWOSection;
- DWARFSection RangeDWOSection;
- DWARFSection AddrSection;
- DWARFSection AppleNamesSection;
- DWARFSection AppleTypesSection;
- DWARFSection AppleNamespacesSection;
- DWARFSection AppleObjCSection;
- StringRef CUIndexSection;
- StringRef GdbIndexSection;
- StringRef TUIndexSection;
-
- SmallVector<SmallString<32>, 4> UncompressedSections;
-
- DWARFSection *mapNameToDWARFSection(StringRef Name);
- StringRef *mapSectionToMember(StringRef Name);
-
- /// If Sec is compressed section, decompresses and updates its contents
- /// provided by Data. Otherwise leaves it unchanged.
- Error maybeDecompress(const object::SectionRef &Sec, StringRef Name,
- StringRef &Data);
+ 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);
+ static std::unique_ptr<DWARFContext>
+ create(const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
+ function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler,
+ std::string DWPName = "");
-public:
- DWARFContextInMemory(
- const object::ObjectFile &Obj, const LoadedObjectInfo *L = nullptr,
- function_ref<ErrorPolicy(Error)> HandleError = defaultErrorHandler);
-
- DWARFContextInMemory(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
- uint8_t AddrSize,
- bool isLittleEndian = sys::IsLittleEndianHost);
-
- StringRef getFileName() const override { return FileName; }
- bool isLittleEndian() const override { return IsLittleEndian; }
- uint8_t getAddressSize() const override { return AddressSize; }
- const DWARFSection &getInfoSection() override { return InfoSection; }
- void forEachTypesSections(function_ref<void(DWARFSection &)> F) override {
- for (auto &P : TypesSections)
- F(P.second);
- }
- StringRef getAbbrevSection() override { return AbbrevSection; }
- const DWARFSection &getLocSection() override { return LocSection; }
- StringRef getARangeSection() override { return ARangeSection; }
- StringRef getDebugFrameSection() override { return DebugFrameSection; }
- StringRef getEHFrameSection() override { return EHFrameSection; }
- const DWARFSection &getLineSection() override { return LineSection; }
- StringRef getStringSection() override { return StringSection; }
- const DWARFSection &getRangeSection() override { return RangeSection; }
- StringRef getMacinfoSection() override { return MacinfoSection; }
- StringRef getPubNamesSection() override { return PubNamesSection; }
- StringRef getPubTypesSection() override { return PubTypesSection; }
- StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; }
- StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; }
- const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; }
- const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; }
- const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; }
- const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; }
-
- // DWARF v5
- const DWARFSection &getStringOffsetSection() override {
- return StringOffsetSection;
- }
-
- // Sections for DWARF5 split dwarf proposal.
- const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; }
-
- void forEachTypesDWOSections(function_ref<void(DWARFSection &)> F) override {
- for (auto &P : TypesDWOSections)
- F(P.second);
- }
-
- StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; }
- const DWARFSection &getLineDWOSection() override { return LineDWOSection; }
- const DWARFSection &getLocDWOSection() override { return LocDWOSection; }
- StringRef getStringDWOSection() override { return StringDWOSection; }
-
- const DWARFSection &getStringOffsetDWOSection() override {
- return StringOffsetDWOSection;
- }
+ static std::unique_ptr<DWARFContext>
+ create(const StringMap<std::unique_ptr<MemoryBuffer>> &Sections,
+ uint8_t AddrSize, bool isLittleEndian = sys::IsLittleEndianHost);
- const DWARFSection &getRangeDWOSection() override { return RangeDWOSection; }
+ /// Loads register info for the architecture of the provided object file.
+ /// Improves readability of dumped DWARF expressions. Requires the caller to
+ /// have initialized the relevant target descriptions.
+ Error loadRegisterInfo(const object::ObjectFile &Obj);
- const DWARFSection &getAddrSection() override { return AddrSection; }
+private:
+ /// Return the compile unit that includes an offset (relative to .debug_info).
+ DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset);
- StringRef getCUIndexSection() override { return CUIndexSection; }
- StringRef getGdbIndexSection() override { return GdbIndexSection; }
- StringRef getTUIndexSection() override { return TUIndexSection; }
+ /// Return the compile unit which contains instruction with provided
+ /// address.
+ DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address);
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
index ef4360f666218..a379d9c85b385 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h
@@ -14,18 +14,21 @@
#include "llvm/Support/DataExtractor.h"
namespace llvm {
+class DWARFObject;
/// A DataExtractor (typically for an in-memory copy of an object-file section)
/// plus a relocation map for that section, if there is one.
class DWARFDataExtractor : public DataExtractor {
- const RelocAddrMap *RelocMap = nullptr;
+ const DWARFObject *Obj = nullptr;
+ const DWARFSection *Section = nullptr;
+
public:
/// Constructor for the normal case of extracting data from a DWARF section.
/// The DWARFSection's lifetime must be at least as long as the extractor's.
- DWARFDataExtractor(const DWARFSection &Section, bool IsLittleEndian,
- uint8_t AddressSize)
- : DataExtractor(Section.Data, IsLittleEndian, AddressSize),
- RelocMap(&Section.Relocs) {}
+ DWARFDataExtractor(const DWARFObject &Obj, const DWARFSection &Section,
+ bool IsLittleEndian, uint8_t AddressSize)
+ : DataExtractor(Section.Data, IsLittleEndian, AddressSize), Obj(&Obj),
+ Section(&Section) {}
/// Constructor for cases when there are no relocations.
DWARFDataExtractor(StringRef Data, bool IsLittleEndian, uint8_t AddressSize)
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
index 65571598d7432..d277ec382ba56 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h
@@ -56,8 +56,9 @@ class DWARFDebugAbbrev {
using DWARFAbbreviationDeclarationSetMap =
std::map<uint64_t, DWARFAbbreviationDeclarationSet>;
- DWARFAbbreviationDeclarationSetMap AbbrDeclSets;
+ mutable DWARFAbbreviationDeclarationSetMap AbbrDeclSets;
mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos;
+ mutable Optional<DataExtractor> Data;
public:
DWARFDebugAbbrev();
@@ -66,9 +67,11 @@ public:
getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const;
void dump(raw_ostream &OS) const;
+ void parse() const;
void extract(DataExtractor Data);
DWARFAbbreviationDeclarationSetMap::const_iterator begin() const {
+ parse();
return AbbrDeclSets.begin();
}
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
index e0a779bb81823..a711fb2954447 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h
@@ -29,13 +29,19 @@ public:
DWARFDebugFrame(bool IsEH);
~DWARFDebugFrame();
- /// \brief Dump the section data into the given stream.
- void dump(raw_ostream &OS) const;
+ /// Dump the section data into the given stream.
+ void dump(raw_ostream &OS, Optional<uint64_t> Offset) const;
/// \brief Parse the section from raw data.
/// data is assumed to be pointing to the beginning of the section.
void parse(DataExtractor Data);
+ /// Return whether the section has any entries.
+ bool empty() const { return Entries.empty(); }
+
+ /// Return the entry at the given offset or nullptr.
+ FrameEntry *getEntryAtOffset(uint64_t Offset) const;
+
private:
std::vector<std::unique_ptr<FrameEntry>> Entries;
};
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
index 0c8f98aa62f9e..de8ad4e5ef3cb 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h
@@ -15,6 +15,7 @@
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/Support/MD5.h"
#include <cstdint>
#include <map>
#include <string>
@@ -22,6 +23,7 @@
namespace llvm {
+class DWARFUnit;
class raw_ostream;
class DWARFDebugLine {
@@ -33,6 +35,7 @@ public:
uint64_t DirIdx = 0;
uint64_t ModTime = 0;
uint64_t Length = 0;
+ MD5::MD5Result Checksum;
};
struct Prologue {
@@ -45,11 +48,11 @@ public:
/// parameters affect interpretation of forms (used in the directory and
/// file tables starting with v5).
DWARFFormParams FormParams;
- /// In v5, size in bytes of a segment selector.
- uint8_t SegSelectorSize;
/// The number of bytes following the prologue_length field to the beginning
/// of the first byte of the statement program itself.
uint64_t PrologueLength;
+ /// In v5, size in bytes of a segment selector.
+ uint8_t SegSelectorSize;
/// The size in bytes of the smallest target machine instruction. Statement
/// program opcodes that alter the address register first multiply their
/// operands by this value.
@@ -65,6 +68,8 @@ public:
uint8_t LineRange;
/// The number assigned to the first special opcode.
uint8_t OpcodeBase;
+ /// For v5, whether filename entries provide an MD5 checksum.
+ bool HasMD5;
std::vector<uint8_t> StandardOpcodeLengths;
std::vector<StringRef> IncludeDirectories;
std::vector<FileNameEntry> FileNames;
@@ -95,7 +100,8 @@ public:
void clear();
void dump(raw_ostream &OS) const;
- bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr);
+ bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
+ const DWARFUnit *U = nullptr);
};
/// Standard .debug_line state machine structure.
@@ -217,7 +223,8 @@ public:
void clear();
/// Parse prologue and all rows.
- bool parse(const DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr);
+ bool parse(DWARFDataExtractor &DebugLineData, uint32_t *OffsetPtr,
+ const DWARFUnit *U, raw_ostream *OS = nullptr);
using RowVector = std::vector<Row>;
using RowIter = RowVector::const_iterator;
@@ -234,8 +241,8 @@ public:
};
const LineTable *getLineTable(uint32_t Offset) const;
- const LineTable *getOrParseLineTable(const DWARFDataExtractor &DebugLineData,
- uint32_t Offset);
+ const LineTable *getOrParseLineTable(DWARFDataExtractor &DebugLineData,
+ uint32_t Offset, const DWARFUnit *U);
private:
struct ParsingState {
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
index c2b8d0cd73d82..a6d319a90457f 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
@@ -10,16 +10,19 @@
#ifndef LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
#define LLVM_DEBUGINFO_DWARF_DWARFDEBUGLOC_H
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
#include <cstdint>
namespace llvm {
-
+class DWARFUnit;
+class MCRegisterInfo;
class raw_ostream;
class DWARFDebugLoc {
+public:
/// A single location within a location list.
struct Entry {
/// The beginning address of the instruction range.
@@ -27,7 +30,7 @@ class DWARFDebugLoc {
/// The ending address of the instruction range.
uint64_t End;
/// The location of the variable within the specified range.
- SmallVector<unsigned char, 4> Loc;
+ SmallVector<char, 4> Loc;
};
/// A list of locations that contain one variable.
@@ -37,42 +40,72 @@ class DWARFDebugLoc {
unsigned 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, unsigned Indent) const;
};
+private:
using LocationLists = SmallVector<LocationList, 4>;
/// A list of all the variables in the debug_loc section, each one describing
/// the locations in which the variable is stored.
LocationLists Locations;
+ unsigned AddressSize;
+
+ bool IsLittleEndian;
+
public:
/// Print the location lists found within the debug_loc section.
- void dump(raw_ostream &OS) const;
+ void dump(raw_ostream &OS, const MCRegisterInfo *RegInfo,
+ 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);
+
+ /// 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);
};
class DWARFDebugLocDWO {
+public:
struct Entry {
uint64_t Start;
uint32_t Length;
- SmallVector<unsigned char, 4> Loc;
+ SmallVector<char, 4> Loc;
};
struct LocationList {
unsigned Offset;
SmallVector<Entry, 2> Entries;
+ void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize,
+ const MCRegisterInfo *RegInfo, unsigned Indent) const;
};
+private:
using LocationLists = SmallVector<LocationList, 4>;
LocationLists Locations;
+ unsigned AddressSize;
+
+ bool IsLittleEndian;
+
public:
void parse(DataExtractor data);
- void dump(raw_ostream &OS) const;
+ void dump(raw_ostream &OS, 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,
+ uint32_t *Offset);
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h b/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
index 135c50761e36a..bfe2fc3ac02d7 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugMacro.h
@@ -53,6 +53,9 @@ public:
/// Parse the debug_macinfo section accessible via the 'data' parameter.
void parse(DataExtractor data);
+
+ /// Return whether the section has any entries.
+ bool empty() const { return Macros.empty(); }
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
index a309fd104f938..761871dc6255d 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugPubTable.h
@@ -69,7 +69,7 @@ private:
public:
DWARFDebugPubTable(StringRef Data, bool LittleEndian, bool GnuStyle);
- void dump(StringRef Name, raw_ostream &OS) const;
+ void dump(raw_ostream &OS) const;
ArrayRef<Set> getData() { return Sets; }
};
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
index bcba14b1630d1..f9ec96366a538 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDebugRangeList.h
@@ -18,14 +18,47 @@
namespace llvm {
+struct BaseAddress;
class raw_ostream;
struct DWARFAddressRange {
uint64_t LowPC;
uint64_t HighPC;
uint64_t SectionIndex;
+
+ DWARFAddressRange() = default;
+
+ /// Used for unit testing.
+ DWARFAddressRange(uint64_t LowPC, uint64_t HighPC, uint64_t SectionIndex = 0)
+ : LowPC(LowPC), HighPC(HighPC), SectionIndex(SectionIndex) {}
+
+ /// Returns true if LowPC is smaller or equal to HighPC. This accounts for
+ /// dead-stripped ranges.
+ bool valid() const { return LowPC <= HighPC; }
+
+ /// Returns true if [LowPC, HighPC) intersects with [RHS.LowPC, RHS.HighPC).
+ bool intersects(const DWARFAddressRange &RHS) const {
+ // Empty ranges can't intersect.
+ if (LowPC == HighPC || RHS.LowPC == RHS.HighPC)
+ return false;
+ return (LowPC < RHS.HighPC) && (HighPC > RHS.LowPC);
+ }
+
+ /// Returns true if [LowPC, HighPC) fully contains [RHS.LowPC, RHS.HighPC).
+ bool contains(const DWARFAddressRange &RHS) const {
+ if (LowPC <= RHS.LowPC && RHS.LowPC <= HighPC)
+ return LowPC <= RHS.HighPC && RHS.HighPC <= HighPC;
+ return false;
+ }
};
+static 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.
using DWARFAddressRangesVector = std::vector<DWARFAddressRange>;
@@ -85,7 +118,8 @@ public:
/// getAbsoluteRanges - Returns absolute address ranges defined by this range
/// list. Has to be passed base address of the compile unit referencing this
/// range list.
- DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const;
+ DWARFAddressRangesVector
+ getAbsoluteRanges(llvm::Optional<BaseAddress> BaseAddr) const;
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFDie.h b/include/llvm/DebugInfo/DWARF/DWARFDie.h
index b216491b615a2..75fc5995c5b22 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFDie.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFDie.h
@@ -108,21 +108,19 @@ public:
///
/// \returns a valid DWARFDie instance if this object has children or an
/// invalid DWARFDie instance if it doesn't.
- DWARFDie getFirstChild() const {
- if (isValid() && Die->hasChildren())
- return DWARFDie(U, Die + 1);
- return DWARFDie();
- }
+ DWARFDie getFirstChild() const;
/// Dump the DIE and all of its attributes to the supplied stream.
///
/// \param OS the stream to use for output.
- /// \param recurseDepth the depth to recurse to when dumping this DIE and its
- /// children.
/// \param indent the number of characters to indent each line that is output.
- void dump(raw_ostream &OS, unsigned recurseDepth, unsigned indent = 0,
+ void dump(raw_ostream &OS, unsigned indent = 0,
DIDumpOptions DumpOpts = DIDumpOptions()) const;
+
+ /// Convenience zero-argument overload for debugging.
+ LLVM_DUMP_METHOD void dump() const;
+
/// Extract the specified attribute from this DIE.
///
/// Extract an attribute value from this DIE only. This call doesn't look
@@ -304,6 +302,10 @@ inline bool operator!=(const DWARFDie &LHS, const DWARFDie &RHS) {
return !(LHS == RHS);
}
+inline bool operator<(const DWARFDie &LHS, const DWARFDie &RHS) {
+ return LHS.getOffset() < RHS.getOffset();
+}
+
class DWARFDie::iterator : public iterator_facade_base<iterator,
std::forward_iterator_tag,
const DWARFDie> {
diff --git a/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/include/llvm/DebugInfo/DWARF/DWARFExpression.h
new file mode 100644
index 0000000000000..dcd486f3fb137
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARF/DWARFExpression.h
@@ -0,0 +1,151 @@
+//===--- DWARFExpression.h - DWARF Expression handling ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_DWARFEXPRESSION_H
+#define LLVM_DEBUGINFO_DWARFEXPRESSION_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Support/DataExtractor.h"
+
+namespace llvm {
+class DWARFUnit;
+class MCRegisterInfo;
+class raw_ostream;
+
+class DWARFExpression {
+public:
+ class iterator;
+
+ /// This class represents an Operation in the Expression. Each operation can
+ /// have up to 2 oprerands.
+ ///
+ /// An Operation can be in Error state (check with isError()). This
+ /// means that it couldn't be decoded successfully and if it is the
+ /// case, all others fields contain undefined values.
+ class Operation {
+ public:
+ /// Size and signedness of expression operations' operands.
+ enum Encoding : uint8_t {
+ Size1 = 0,
+ Size2 = 1,
+ Size4 = 2,
+ Size8 = 3,
+ SizeLEB = 4,
+ SizeAddr = 5,
+ SizeRefAddr = 6,
+ SizeBlock = 7, ///< Preceding operand contains block size
+ SignBit = 0x8,
+ SignedSize1 = SignBit | Size1,
+ SignedSize2 = SignBit | Size2,
+ SignedSize4 = SignBit | Size4,
+ SignedSize8 = SignBit | Size8,
+ SignedSizeLEB = SignBit | SizeLEB,
+ SizeNA = 0xFF ///< Unused operands get this encoding.
+ };
+
+ enum DwarfVersion : uint8_t {
+ DwarfNA, ///< Serves as a marker for unused entries
+ Dwarf2 = 2,
+ Dwarf3,
+ Dwarf4
+ };
+
+ /// Description of the encoding of one expression Op.
+ struct Description {
+ DwarfVersion Version; ///< Dwarf version where the Op was introduced.
+ Encoding Op[2]; ///< Encoding for Op operands, or SizeNA.
+
+ Description(DwarfVersion Version = DwarfNA, Encoding Op1 = SizeNA,
+ Encoding Op2 = SizeNA)
+ : Version(Version) {
+ Op[0] = Op1;
+ Op[1] = Op2;
+ }
+ };
+
+ private:
+ friend class DWARFExpression::iterator;
+ uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>.
+ Description Desc;
+ bool Error;
+ uint32_t EndOffset;
+ uint64_t Operands[2];
+
+ public:
+ Description &getDescription() { return Desc; }
+ uint8_t getCode() { return Opcode; }
+ uint64_t getRawOperand(unsigned Idx) { return Operands[Idx]; }
+ uint32_t getEndOffset() { return EndOffset; }
+ bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize,
+ uint32_t Offset);
+ bool isError() { return Error; }
+ bool print(raw_ostream &OS, const DWARFExpression *U,
+ const MCRegisterInfo *RegInfo, bool isEH);
+ };
+
+ /// An iterator to go through the expression operations.
+ class iterator
+ : public iterator_facade_base<iterator, std::forward_iterator_tag, Operation> {
+ friend class DWARFExpression;
+ DWARFExpression *Expr;
+ uint32_t Offset;
+ Operation Op;
+ iterator(DWARFExpression *Expr, uint32_t Offset)
+ : Expr(Expr), Offset(Offset) {
+ Op.Error =
+ Offset >= Expr->Data.getData().size() ||
+ !Op.extract(Expr->Data, Expr->Version, Expr->AddressSize, Offset);
+ }
+
+ public:
+ class Operation &operator++() {
+ 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);
+ return Op;
+ }
+
+ class Operation &operator*() {
+ return Op;
+ }
+
+ // 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) {
+ assert(AddressSize == 8 || AddressSize == 4);
+ }
+
+ iterator begin() { return iterator(this, 0); }
+ iterator end() { return iterator(this, Data.getData().size()); }
+
+ void print(raw_ostream &OS, const MCRegisterInfo *RegInfo);
+
+private:
+ DataExtractor Data;
+ uint16_t Version;
+ uint8_t AddressSize;
+};
+
+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/include/llvm/DebugInfo/DWARF/DWARFFormValue.h b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
index 008dba9b42acd..d32053519ec48 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFFormValue.h
@@ -14,6 +14,7 @@
#include "llvm/ADT/None.h"
#include "llvm/ADT/Optional.h"
#include "llvm/BinaryFormat/Dwarf.h"
+#include "llvm/DebugInfo/DIContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h"
#include <cstdint>
@@ -101,18 +102,14 @@ public:
bool isFormClass(FormClass FC) const;
const DWARFUnit *getUnit() const { return U; }
- void dump(raw_ostream &OS) const;
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = DIDumpOptions()) const;
- /// Extracts a value in \p Data at offset \p *OffsetPtr.
- ///
- /// The passed DWARFUnit is allowed to be nullptr, in which case some
- /// kind of forms that depend on Unit information are disallowed.
- /// \param Data The DWARFDataExtractor to use.
- /// \param OffsetPtr The offset within \p Data where the data starts.
- /// \param U The optional DWARFUnit supplying information for some forms.
- /// \returns whether the extraction succeeded.
+ /// Extracts a value in \p Data at offset \p *OffsetPtr. The information
+ /// in \p FormParams is needed to interpret some forms. The optional
+ /// \p Unit allows extracting information if the form refers to other
+ /// sections (e.g., .debug_str).
bool extractValue(const DWARFDataExtractor &Data, uint32_t *OffsetPtr,
- const DWARFUnit *U);
+ DWARFFormParams FormParams, const DWARFUnit *U = nullptr);
bool isInlinedCStr() const {
return Value.data != nullptr && Value.data == (const uint8_t *)Value.cstr;
diff --git a/include/llvm/DebugInfo/DWARF/DWARFObject.h b/include/llvm/DebugInfo/DWARF/DWARFObject.h
new file mode 100644
index 0000000000000..167eb2da5ba04
--- /dev/null
+++ b/include/llvm/DebugInfo/DWARF/DWARFObject.h
@@ -0,0 +1,79 @@
+//===- DWARFObject.h --------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===-----------------------------------------------------------------------===/
+
+#ifndef LLVM_DEBUGINFO_DWARF_DWARFOBJECT_H
+#define LLVM_DEBUGINFO_DWARF_DWARFOBJECT_H
+
+#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
+#include "llvm/DebugInfo/DWARF/DWARFSection.h"
+#include "llvm/Object/ObjectFile.h"
+
+namespace llvm {
+// This is responsible for low level access to the object file. It
+// knows how to find the required sections and compute relocated
+// values.
+// The default implementations of the get<Section> methods return dummy values.
+// This is to allow clients that only need some of those to implement just the
+// ones they need. We can't use unreachable for as many cases because the parser
+// implementation is eager and will call some of these methods even if the
+// result is not used.
+class DWARFObject {
+ DWARFSection Dummy;
+
+public:
+ virtual ~DWARFObject() = default;
+ virtual StringRef getFileName() const { llvm_unreachable("unimplemented"); }
+ virtual const object::ObjectFile *getFile() const { return nullptr; }
+ virtual ArrayRef<SectionName> getSectionNames() const { return {}; }
+ virtual bool isLittleEndian() const = 0;
+ virtual uint8_t getAddressSize() const { llvm_unreachable("unimplemented"); }
+ virtual const DWARFSection &getInfoSection() const { return Dummy; }
+ virtual void
+ forEachTypesSections(function_ref<void(const DWARFSection &)> F) const {}
+ virtual StringRef getAbbrevSection() const { return ""; }
+ virtual const DWARFSection &getLocSection() const { return Dummy; }
+ virtual StringRef getARangeSection() const { return ""; }
+ virtual StringRef getDebugFrameSection() const { return ""; }
+ virtual StringRef getEHFrameSection() const { return ""; }
+ virtual const DWARFSection &getLineSection() const { return Dummy; }
+ virtual StringRef getStringSection() const { return ""; }
+ virtual const DWARFSection &getRangeSection() const { return Dummy; }
+ virtual StringRef getMacinfoSection() const { return ""; }
+ virtual StringRef getPubNamesSection() const { return ""; }
+ virtual StringRef getPubTypesSection() const { return ""; }
+ virtual StringRef getGnuPubNamesSection() const { return ""; }
+ virtual StringRef getGnuPubTypesSection() const { return ""; }
+ virtual const DWARFSection &getStringOffsetSection() const { return Dummy; }
+ virtual const DWARFSection &getInfoDWOSection() const { return Dummy; }
+ virtual void
+ forEachTypesDWOSections(function_ref<void(const DWARFSection &)> F) const {}
+ 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 {
+ return Dummy;
+ }
+ virtual const DWARFSection &getRangeDWOSection() const { return Dummy; }
+ virtual const DWARFSection &getAddrSection() const { return Dummy; }
+ virtual const DWARFSection &getAppleNamesSection() const { return Dummy; }
+ virtual const DWARFSection &getAppleTypesSection() const { return Dummy; }
+ virtual const DWARFSection &getAppleNamespacesSection() const {
+ return Dummy;
+ }
+ virtual const DWARFSection &getAppleObjCSection() const { return Dummy; }
+ virtual StringRef getCUIndexSection() const { return ""; }
+ virtual StringRef getGdbIndexSection() const { return ""; }
+ virtual StringRef getTUIndexSection() const { return ""; }
+ virtual Optional<RelocAddrEntry> find(const DWARFSection &Sec,
+ uint64_t Pos) const = 0;
+};
+
+} // namespace llvm
+#endif
diff --git a/include/llvm/DebugInfo/DWARF/DWARFSection.h b/include/llvm/DebugInfo/DWARF/DWARFSection.h
index 2b8a53a4c93ea..77045f0794ae8 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFSection.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFSection.h
@@ -11,13 +11,16 @@
#define LLVM_DEBUGINFO_DWARF_DWARFSECTION_H
#include "llvm/ADT/StringRef.h"
-#include "llvm/DebugInfo/DWARF/DWARFRelocMap.h"
namespace llvm {
struct DWARFSection {
StringRef Data;
- RelocAddrMap Relocs;
+};
+
+struct SectionName {
+ StringRef Name;
+ bool IsNameUnique;
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
index 4a5793ecb8fa6..a7842454f4356 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFTypeUnit.h
@@ -42,7 +42,7 @@ public:
return DWARFUnit::getHeaderSize() + 12;
}
- void dump(raw_ostream &OS, bool Brief = false);
+ void dump(raw_ostream &OS, DIDumpOptions DumpOpts = {});
static const DWARFSectionKind Section = DW_SECT_TYPES;
protected:
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
index 056c1b77c65d1..e9178e03fa8a2 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h
@@ -47,10 +47,11 @@ public:
/// Returns the Unit that contains the given section offset in the
/// same section this Unit originated from.
virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0;
+ virtual DWARFUnit *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) = 0;
void parse(DWARFContext &C, const DWARFSection &Section);
void parseDWO(DWARFContext &C, const DWARFSection &DWOSection,
- DWARFUnitIndex *Index = nullptr);
+ bool Lazy = false);
protected:
~DWARFUnitSectionBase() = default;
@@ -59,7 +60,7 @@ protected:
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, const DWARFSection &SOS,
const DWARFSection *AOS, const DWARFSection &LS,
- bool isLittleEndian, bool isDWO) = 0;
+ bool isLittleEndian, bool isDWO, bool Lazy) = 0;
};
const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
@@ -70,6 +71,7 @@ template<typename UnitType>
class DWARFUnitSection final : public SmallVector<std::unique_ptr<UnitType>, 1>,
public DWARFUnitSectionBase {
bool Parsed = false;
+ std::function<std::unique_ptr<UnitType>(uint32_t)> Parser;
public:
using UnitVector = SmallVectorImpl<std::unique_ptr<UnitType>>;
@@ -82,34 +84,87 @@ public:
[](uint32_t LHS, const std::unique_ptr<UnitType> &RHS) {
return LHS < RHS->getNextUnitOffset();
});
- if (CU != this->end())
+ if (CU != this->end() && (*CU)->getOffset() <= Offset)
return CU->get();
return nullptr;
}
+ UnitType *getUnitForIndexEntry(const DWARFUnitIndex::Entry &E) override {
+ const auto *CUOff = E.getOffset(DW_SECT_INFO);
+ if (!CUOff)
+ return nullptr;
+
+ auto Offset = CUOff->Offset;
+
+ auto *CU = std::upper_bound(
+ this->begin(), this->end(), CUOff->Offset,
+ [](uint32_t LHS, const std::unique_ptr<UnitType> &RHS) {
+ return LHS < RHS->getNextUnitOffset();
+ });
+ if (CU != this->end() && (*CU)->getOffset() <= Offset)
+ return CU->get();
+
+ if (!Parser)
+ return nullptr;
+
+ auto U = Parser(Offset);
+ if (!U)
+ U = nullptr;
+
+ auto *NewCU = U.get();
+ this->insert(CU, std::move(U));
+ return NewCU;
+ }
private:
void parseImpl(DWARFContext &Context, const DWARFSection &Section,
const DWARFDebugAbbrev *DA, const DWARFSection *RS,
StringRef SS, const DWARFSection &SOS, const DWARFSection *AOS,
- const DWARFSection &LS, bool LE, bool IsDWO) override {
+ const DWARFSection &LS, bool LE, bool IsDWO,
+ bool Lazy) override {
if (Parsed)
return;
- const auto &Index = getDWARFUnitIndex(Context, UnitType::Section);
DataExtractor Data(Section.Data, LE, 0);
+ if (!Parser) {
+ const DWARFUnitIndex *Index = nullptr;
+ if (IsDWO)
+ Index = &getDWARFUnitIndex(Context, UnitType::Section);
+ Parser = [=, &Context, &Section, &SOS,
+ &LS](uint32_t Offset) -> std::unique_ptr<UnitType> {
+ if (!Data.isValidOffset(Offset))
+ return nullptr;
+ auto U = llvm::make_unique<UnitType>(
+ Context, Section, DA, RS, SS, SOS, AOS, LS, LE, IsDWO, *this,
+ Index ? Index->getFromOffset(Offset) : nullptr);
+ if (!U->extract(Data, &Offset))
+ return nullptr;
+ return U;
+ };
+ }
+ if (Lazy)
+ return;
+ auto I = this->begin();
uint32_t Offset = 0;
while (Data.isValidOffset(Offset)) {
- auto U = llvm::make_unique<UnitType>(Context, Section, DA, RS, SS, SOS,
- AOS, LS, LE, IsDWO, *this,
- Index.getFromOffset(Offset));
- if (!U->extract(Data, &Offset))
+ if (I != this->end() && (*I)->getOffset() == Offset) {
+ ++I;
+ continue;
+ }
+ auto U = Parser(Offset);
+ if (!U)
break;
- this->push_back(std::move(U));
- Offset = this->back()->getNextUnitOffset();
+ Offset = U->getNextUnitOffset();
+ I = std::next(this->insert(I, std::move(U)));
}
Parsed = true;
}
};
+/// Represents base address of the CU.
+struct BaseAddress {
+ uint64_t Address;
+ uint64_t SectionIndex;
+};
+
class DWARFUnit {
DWARFContext &Context;
/// Section containing this DWARFUnit.
@@ -123,7 +178,7 @@ class DWARFUnit {
const DWARFSection &StringOffsetSection;
uint64_t StringOffsetSectionBase = 0;
const DWARFSection *AddrOffsetSection;
- uint32_t AddrOffsetSectionBase;
+ uint32_t AddrOffsetSectionBase = 0;
bool isLittleEndian;
bool isDWO;
const DWARFUnitSectionBase &UnitSection;
@@ -133,9 +188,10 @@ class DWARFUnit {
uint32_t Offset;
uint32_t Length;
- const DWARFAbbreviationDeclarationSet *Abbrevs;
+ mutable const DWARFAbbreviationDeclarationSet *Abbrevs;
+ uint64_t AbbrOffset;
uint8_t UnitType;
- uint64_t BaseAddr;
+ llvm::Optional<BaseAddress> BaseAddr;
/// The compile unit debug information entry items.
std::vector<DWARFDebugInfoEntry> DieArray;
@@ -197,19 +253,12 @@ public:
bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
bool getStringOffsetSectionItem(uint32_t Index, uint64_t &Result) const;
- DWARFDataExtractor getDebugInfoExtractor() const {
- return DWARFDataExtractor(InfoSection, isLittleEndian,
- getAddressByteSize());
- }
+ DWARFDataExtractor getDebugInfoExtractor() const;
DataExtractor getStringExtractor() const {
return DataExtractor(StringSection, false, 0);
}
- const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; }
- const RelocAddrMap &getStringOffsetsRelocMap() const {
- return StringOffsetSection.Relocs;
- }
bool extract(DataExtractor debug_info, uint32_t* offset_ptr);
@@ -232,18 +281,25 @@ public:
return FormParams.getDwarfOffsetByteSize();
}
- const DWARFAbbreviationDeclarationSet *getAbbreviations() const {
- return Abbrevs;
- }
+ const DWARFAbbreviationDeclarationSet *getAbbreviations() const;
uint8_t getUnitType() const { return UnitType; }
- static bool isValidUnitType(uint8_t UnitType) {
- return UnitType == dwarf::DW_UT_compile || UnitType == dwarf::DW_UT_type ||
- UnitType == dwarf::DW_UT_partial ||
- UnitType == dwarf::DW_UT_skeleton ||
- UnitType == dwarf::DW_UT_split_compile ||
- UnitType == dwarf::DW_UT_split_type;
+ static bool isMatchingUnitTypeAndTag(uint8_t UnitType, dwarf::Tag Tag) {
+ switch (UnitType) {
+ case dwarf::DW_UT_compile:
+ return Tag == dwarf::DW_TAG_compile_unit;
+ case dwarf::DW_UT_type:
+ return Tag == dwarf::DW_TAG_type_unit;
+ case dwarf::DW_UT_partial:
+ return Tag == dwarf::DW_TAG_partial_unit;
+ case dwarf::DW_UT_skeleton:
+ return Tag == dwarf::DW_TAG_skeleton_unit;
+ case dwarf::DW_UT_split_compile:
+ case dwarf::DW_UT_split_type:
+ return dwarf::isUnitType(Tag);
+ }
+ return false;
}
/// \brief Return the number of bytes for the header of a unit of
@@ -266,11 +322,9 @@ public:
llvm_unreachable("Invalid UnitType.");
}
- uint64_t getBaseAddress() const { return BaseAddr; }
+ llvm::Optional<BaseAddress> getBaseAddress() const { return BaseAddr; }
- void setBaseAddress(uint64_t base_addr) {
- BaseAddr = base_addr;
- }
+ void setBaseAddress(BaseAddress BaseAddr) { this->BaseAddr = BaseAddr; }
DWARFDie getUnitDIE(bool ExtractUnitDIEOnly = true) {
extractDIEsIfNeeded(ExtractUnitDIEOnly);
@@ -284,6 +338,11 @@ public:
void collectAddressRanges(DWARFAddressRangesVector &CURanges);
+ /// Returns subprogram DIE with address range encompassing the provided
+ /// address. The pointer is alive as long as parsed compile unit DIEs are not
+ /// cleared.
+ DWARFDie getSubroutineForAddress(uint64_t Address);
+
/// getInlinedChainForAddress - fetches inlined chain for a given address.
/// Returns empty chain if there is no subprogram containing address. The
/// chain is valid as long as parsed compile unit DIEs are not cleared.
@@ -318,6 +377,7 @@ public:
DWARFDie getParent(const DWARFDebugInfoEntry *Die);
DWARFDie getSibling(const DWARFDebugInfoEntry *Die);
+ DWARFDie getFirstChild(const DWARFDebugInfoEntry *Die);
/// \brief Return the DIE object for a given offset inside the
/// unit's DIE vector.
@@ -366,11 +426,6 @@ private:
/// parseDWO - Parses .dwo file for current compile unit. Returns true if
/// it was actually constructed.
bool parseDWO();
-
- /// getSubroutineForAddress - Returns subprogram DIE with address range
- /// encompassing the provided address. The pointer is alive as long as parsed
- /// compile unit DIEs are not cleared.
- DWARFDie getSubroutineForAddress(uint64_t Address);
};
} // end namespace llvm
diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
index 8e2ce023695bf..49ed4bb222f3f 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFUnitIndex.h
@@ -83,9 +83,13 @@ public:
DWARFUnitIndex(DWARFSectionKind InfoColumnKind)
: InfoColumnKind(InfoColumnKind) {}
+ explicit operator bool() const { return Header.NumBuckets; }
+
bool parse(DataExtractor IndexData);
void dump(raw_ostream &OS) const;
+
const Entry *getFromOffset(uint32_t Offset) const;
+ const Entry *getFromHash(uint64_t Offset) const;
ArrayRef<DWARFSectionKind> getColumnKinds() const {
return makeArrayRef(ColumnKinds.get(), Header.NumColumns);
diff --git a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
index c0291a83ed973..0d920abe32315 100644
--- a/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
+++ b/include/llvm/DebugInfo/DWARF/DWARFVerifier.h
@@ -10,6 +10,10 @@
#ifndef LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
#define LLVM_DEBUGINFO_DWARF_DWARFVERIFIER_H
+#include "llvm/DebugInfo/DIContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/DebugInfo/DWARF/DWARFDie.h"
+
#include <cstdint>
#include <map>
#include <set>
@@ -22,17 +26,91 @@ class DWARFDie;
class DWARFUnit;
class DWARFAcceleratorTable;
class DWARFDataExtractor;
+class DWARFDebugAbbrev;
+class DataExtractor;
+struct DWARFSection;
/// A class that verifies DWARF debug information given a DWARF Context.
class DWARFVerifier {
+public:
+ /// A class that keeps the address range information for a single DIE.
+ struct DieRangeInfo {
+ DWARFDie Die;
+
+ /// Sorted DWARFAddressRanges.
+ std::vector<DWARFAddressRange> Ranges;
+
+ /// Sorted DWARFAddressRangeInfo.
+ std::set<DieRangeInfo> Children;
+
+ DieRangeInfo() = default;
+ DieRangeInfo(DWARFDie Die) : Die(Die) {}
+
+ /// Used for unit testing.
+ DieRangeInfo(std::vector<DWARFAddressRange> Ranges)
+ : Ranges(std::move(Ranges)) {}
+
+ typedef std::vector<DWARFAddressRange>::const_iterator
+ address_range_iterator;
+ 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.
+ ///
+ /// This is used for finding overlapping ranges within the same DIE.
+ address_range_iterator insert(const DWARFAddressRange &R);
+
+ /// Finds an address range in the sorted vector of ranges.
+ address_range_iterator findRange(const DWARFAddressRange &R) const {
+ auto Begin = Ranges.begin();
+ auto End = Ranges.end();
+ auto Iter = std::upper_bound(Begin, End, R);
+ if (Iter != Begin)
+ --Iter;
+ return Iter;
+ }
+
+ /// Inserts the address range info. If any of its ranges overlaps with a
+ /// range in an existing range info, the range info is *not* added and an
+ /// iterator to the overlapping range info.
+ ///
+ /// This is used for finding overlapping children of the same DIE.
+ die_range_info_iterator insert(const DieRangeInfo &RI);
+
+ /// Return true if ranges in this object contains all ranges within RHS.
+ bool contains(const DieRangeInfo &RHS) const;
+
+ /// Return true if any range in this object intersects with any range in
+ /// RHS.
+ bool intersects(const DieRangeInfo &RHS) const;
+ };
+
+private:
raw_ostream &OS;
DWARFContext &DCtx;
+ DIDumpOptions DumpOpts;
/// 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;
uint32_t NumDebugLineErrors = 0;
- uint32_t NumAppleNamesErrors = 0;
+
+ raw_ostream &error() const;
+ raw_ostream &warn() const;
+ raw_ostream &note() const;
+
+ /// Verifies the abbreviations section.
+ ///
+ /// This function currently checks that:
+ /// --No abbreviation declaration has more than one attributes with the same
+ /// name.
+ ///
+ /// \param Abbrev Pointer to the abbreviations section we are verifying
+ /// Abbrev can be a pointer to either .debug_abbrev or debug_abbrev.dwo.
+ ///
+ /// \returns The number of errors that occured during verification.
+ unsigned verifyAbbrevSection(const DWARFDebugAbbrev *Abbrev);
/// Verifies the header of a unit in the .debug_info section.
///
@@ -58,8 +136,31 @@ class DWARFVerifier {
uint32_t *Offset, unsigned UnitIndex, uint8_t &UnitType,
bool &isUnitDWARF64);
+ /// Verifies the header of a unit in the .debug_info section.
+ ///
+ /// This function currently verifies:
+ /// - The debug info attributes.
+ /// - The debug info form=s.
+ /// - The presence of a root DIE.
+ /// - That the root DIE is a unit DIE.
+ /// - If a unit type is provided, that the unit DIE matches the unit type.
+ /// - The DIE ranges.
+ ///
+ /// \param Unit The DWARF Unit to verifiy.
+ /// \param UnitType An optional unit type which will be used to verify the
+ /// type of the unit DIE.
+ ///
+ /// \returns true if the content is verified successfully, false otherwise.
+ bool verifyUnitContents(DWARFUnit Unit, uint8_t UnitType = 0);
+
+ /// Verify that all Die ranges are valid.
+ ///
+ /// This function currently checks for:
+ /// - cases in which lowPC >= highPC
+ ///
+ /// \returns Number of errors that occured during verification.
+ unsigned verifyDieRanges(const DWARFDie &Die, DieRangeInfo &ParentRI);
- bool verifyUnitContents(DWARFUnit Unit);
/// Verifies the attribute's DWARF attribute and its value.
///
/// This function currently checks for:
@@ -111,9 +212,40 @@ class DWARFVerifier {
/// - invalid file indexes
void verifyDebugLineRows();
+ /// Verify that an Apple-style accelerator table is valid.
+ ///
+ /// This function currently checks that:
+ /// - The fixed part of the header fits in the section
+ /// - The size of the section is as large as what the header describes
+ /// - There is at least one atom
+ /// - The form for each atom is valid
+ /// - The tag for each DIE in the table is valid
+ /// - The buckets have a valid index, or they are empty
+ /// - Each hashdata offset is valid
+ /// - Each DIE is valid
+ ///
+ /// \param AccelSection pointer to the section containing the acceleration table
+ /// \param StrData pointer to the string section
+ /// \param SectionName the name of the table we're verifying
+ ///
+ /// \returns The number of errors occured during verification
+ unsigned verifyAccelTable(const DWARFSection *AccelSection,
+ DataExtractor *StrData, const char *SectionName);
+
public:
- DWARFVerifier(raw_ostream &S, DWARFContext &D)
- : OS(S), DCtx(D) {}
+ DWARFVerifier(raw_ostream &S, DWARFContext &D,
+ DIDumpOptions DumpOpts = DIDumpOptions::getForSingleDIE())
+ : OS(S), DCtx(D), DumpOpts(std::move(DumpOpts)) {}
+ /// Verify the information in any of the following sections, if available:
+ /// .debug_abbrev, debug_abbrev.dwo
+ ///
+ /// Any errors are reported to the stream that was this object was
+ /// constructed with.
+ ///
+ /// \returns true if .debug_abbrev and .debug_abbrev.dwo verify successfully,
+ /// false otherwise.
+ bool handleDebugAbbrev();
+
/// Verify the information in the .debug_info section.
///
/// Any errors are reported to the stream that was this object was
@@ -130,15 +262,21 @@ public:
/// \returns true if the .debug_line verifies successfully, false otherwise.
bool handleDebugLine();
- /// Verify the information in the .apple_names accelerator table.
+ /// Verify the information in accelerator tables, if they exist.
///
/// Any errors are reported to the stream that was this object was
/// constructed with.
///
- /// \returns true if the .apple_names verifies successfully, false otherwise.
- bool handleAppleNames();
+ /// \returns true if the existing Apple-style accelerator tables verify
+ /// successfully, false otherwise.
+ bool handleAccelTables();
};
+static inline bool operator<(const DWARFVerifier::DieRangeInfo &LHS,
+ const DWARFVerifier::DieRangeInfo &RHS) {
+ return std::tie(LHS.Ranges, LHS.Die) < std::tie(RHS.Ranges, RHS.Die);
+}
+
} // end namespace llvm
#endif // LLVM_DEBUGINFO_DWARF_DWARFCONTEXT_H
diff --git a/include/llvm/DebugInfo/MSF/MSFBuilder.h b/include/llvm/DebugInfo/MSF/MSFBuilder.h
index b2c8f2d1c20da..19e5c31b30764 100644
--- a/include/llvm/DebugInfo/MSF/MSFBuilder.h
+++ b/include/llvm/DebugInfo/MSF/MSFBuilder.h
@@ -128,7 +128,6 @@ private:
uint32_t FreePageMap;
uint32_t Unknown1 = 0;
uint32_t BlockSize;
- uint32_t MininumBlocks;
uint32_t BlockMapAddr;
BitVector FreeBlocks;
std::vector<uint32_t> DirectoryBlocks;
diff --git a/include/llvm/DebugInfo/MSF/MSFCommon.h b/include/llvm/DebugInfo/MSF/MSFCommon.h
index eca1b8b89ebd8..f28415d4e6034 100644
--- a/include/llvm/DebugInfo/MSF/MSFCommon.h
+++ b/include/llvm/DebugInfo/MSF/MSFCommon.h
@@ -59,6 +59,25 @@ struct MSFLayout {
std::vector<ArrayRef<support::ulittle32_t>> StreamMap;
};
+/// \brief Describes the layout of a stream in an MSF layout. A "stream" here
+/// is defined as any logical unit of data which may be arranged inside the MSF
+/// file as a sequence of (possibly discontiguous) blocks. When we want to read
+/// from a particular MSF Stream, we fill out a stream layout structure and the
+/// reader uses it to determine which blocks in the underlying MSF file contain
+/// the data, so that it can be pieced together in the right order.
+class MSFStreamLayout {
+public:
+ uint32_t Length;
+ std::vector<support::ulittle32_t> Blocks;
+};
+
+/// \brief Determine the layout of the FPM stream, given the MSF layout. An FPM
+/// stream spans 1 or more blocks, each at equally spaced intervals throughout
+/// the file.
+MSFStreamLayout getFpmStreamLayout(const MSFLayout &Msf,
+ bool IncludeUnusedFpmData = false,
+ bool AltFpm = false);
+
inline bool isValidBlockSize(uint32_t Size) {
switch (Size) {
case 512:
@@ -78,7 +97,7 @@ inline uint32_t getMinimumBlockCount() { return 4; }
inline uint32_t getFirstUnreservedBlock() { return 3; }
inline uint64_t bytesToBlocks(uint64_t NumBytes, uint64_t BlockSize) {
- return alignTo(NumBytes, BlockSize) / BlockSize;
+ return divideCeil(NumBytes, BlockSize);
}
inline uint64_t blockToOffset(uint64_t BlockNumber, uint64_t BlockSize) {
@@ -89,13 +108,14 @@ inline uint32_t getFpmIntervalLength(const MSFLayout &L) {
return L.SB->BlockSize;
}
-inline uint32_t getNumFpmIntervals(const MSFLayout &L) {
- uint32_t Length = getFpmIntervalLength(L);
- return alignTo(L.SB->NumBlocks, Length) / Length;
-}
+inline uint32_t getNumFpmIntervals(const MSFLayout &L,
+ bool IncludeUnusedFpmData = false) {
+ if (IncludeUnusedFpmData)
+ return divideCeil(L.SB->NumBlocks, L.SB->BlockSize);
-inline uint32_t getFullFpmByteSize(const MSFLayout &L) {
- return alignTo(L.SB->NumBlocks, 8) / 8;
+ // We want the minimum number of intervals required, where each interval can
+ // represent BlockSize * 8 blocks.
+ return divideCeil(L.SB->NumBlocks, 8 * L.SB->BlockSize);
}
Error validateSuperBlock(const SuperBlock &SB);
diff --git a/include/llvm/DebugInfo/MSF/MSFStreamLayout.h b/include/llvm/DebugInfo/MSF/MSFStreamLayout.h
deleted file mode 100644
index bdde98f526629..0000000000000
--- a/include/llvm/DebugInfo/MSF/MSFStreamLayout.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//===- MSFStreamLayout.h - Describes the layout of a stream -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H
-#define LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H
-
-#include "llvm/Support/Endian.h"
-
-#include <cstdint>
-#include <vector>
-
-namespace llvm {
-namespace msf {
-
-/// \brief Describes the layout of a stream in an MSF layout. A "stream" here
-/// is defined as any logical unit of data which may be arranged inside the MSF
-/// file as a sequence of (possibly discontiguous) blocks. When we want to read
-/// from a particular MSF Stream, we fill out a stream layout structure and the
-/// reader uses it to determine which blocks in the underlying MSF file contain
-/// the data, so that it can be pieced together in the right order.
-class MSFStreamLayout {
-public:
- uint32_t Length;
- std::vector<support::ulittle32_t> Blocks;
-};
-} // namespace msf
-} // namespace llvm
-
-#endif // LLVM_DEBUGINFO_MSF_MSFSTREAMLAYOUT_H
diff --git a/include/llvm/DebugInfo/MSF/MappedBlockStream.h b/include/llvm/DebugInfo/MSF/MappedBlockStream.h
index 6d88d2be85c9b..f65e52922da77 100644
--- a/include/llvm/DebugInfo/MSF/MappedBlockStream.h
+++ b/include/llvm/DebugInfo/MSF/MappedBlockStream.h
@@ -12,7 +12,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
-#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
+#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryStream.h"
#include "llvm/Support/BinaryStreamRef.h"
@@ -122,7 +122,7 @@ public:
static std::unique_ptr<WritableMappedBlockStream>
createFpmStream(const MSFLayout &Layout, WritableBinaryStreamRef MsfData,
- BumpPtrAllocator &Allocator);
+ BumpPtrAllocator &Allocator, bool AltFpm = false);
support::endianness getEndian() const override {
return support::little;
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h b/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h
new file mode 100644
index 0000000000000..926fcfe696481
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIAEnumTables.h
@@ -0,0 +1,37 @@
+//===- DIAEnumTables.h - DIA Tables Enumerator Impl -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIAENUMTABLES_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIAENUMTABLES_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBTable.h"
+
+namespace llvm {
+namespace pdb {
+class IPDBTable;
+
+class DIAEnumTables : public IPDBEnumChildren<IPDBTable> {
+public:
+ explicit DIAEnumTables(CComPtr<IDiaEnumTables> DiaEnumerator);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<IPDBTable> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<IPDBTable> getNext() override;
+ void reset() override;
+ DIAEnumTables *clone() const override;
+
+private:
+ CComPtr<IDiaEnumTables> Enumerator;
+};
+}
+}
+
+#endif // LLVM_DEBUGINFO_PDB_DIA_DIAENUMTABLES_H
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
index d37b48540ffa2..2d6c44905ce08 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIARawSymbol.h
@@ -96,6 +96,7 @@ public:
uint32_t getTypeId() const override;
uint32_t getUavSlot() const override;
std::string getUndecoratedName() const override;
+ std::string getUndecoratedNameEx(PDB_UndnameFlags Flags) const override;
uint32_t getUnmodifiedTypeId() const override;
uint32_t getUpperBoundId() const override;
Variant getValue() const override;
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIASession.h b/include/llvm/DebugInfo/PDB/DIA/DIASession.h
index 350442556bef8..66bd7a7e9c4e6 100644
--- a/include/llvm/DebugInfo/PDB/DIA/DIASession.h
+++ b/include/llvm/DebugInfo/PDB/DIA/DIASession.h
@@ -64,6 +64,7 @@ public:
std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override;
+ std::unique_ptr<IPDBEnumTables> getEnumTables() const override;
private:
CComPtr<IDiaSession> Session;
};
diff --git a/include/llvm/DebugInfo/PDB/DIA/DIATable.h b/include/llvm/DebugInfo/PDB/DIA/DIATable.h
new file mode 100644
index 0000000000000..ce93fa0b86c34
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/DIA/DIATable.h
@@ -0,0 +1,32 @@
+//===- DIATable.h - DIA implementation of IPDBTable -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_DIA_DIATABLE_H
+#define LLVM_DEBUGINFO_PDB_DIA_DIATABLE_H
+
+#include "DIASupport.h"
+#include "llvm/DebugInfo/PDB/IPDBTable.h"
+
+namespace llvm {
+namespace pdb {
+class DIATable : public IPDBTable {
+public:
+ explicit DIATable(CComPtr<IDiaTable> DiaTable);
+
+ uint32_t getItemCount() const override;
+ std::string getName() const override;
+ PDB_TableType getTableType() const override;
+
+private:
+ CComPtr<IDiaTable> Table;
+};
+}
+}
+
+#endif // LLVM_DEBUGINFO_PDB_DIA_DIATABLE_H
diff --git a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
index eefc365187288..18b9423378a02 100644
--- a/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
+++ b/include/llvm/DebugInfo/PDB/IPDBRawSymbol.h
@@ -108,6 +108,7 @@ public:
virtual uint32_t getTypeId() const = 0;
virtual uint32_t getUavSlot() const = 0;
virtual std::string getUndecoratedName() const = 0;
+ virtual std::string getUndecoratedNameEx(PDB_UndnameFlags Flags) const = 0;
virtual uint32_t getUnmodifiedTypeId() const = 0;
virtual uint32_t getUpperBoundId() const = 0;
virtual Variant getValue() const = 0;
diff --git a/include/llvm/DebugInfo/PDB/IPDBSession.h b/include/llvm/DebugInfo/PDB/IPDBSession.h
index cf195095c8d22..6291289de5bfb 100644
--- a/include/llvm/DebugInfo/PDB/IPDBSession.h
+++ b/include/llvm/DebugInfo/PDB/IPDBSession.h
@@ -67,6 +67,8 @@ public:
getSourceFileById(uint32_t FileId) const = 0;
virtual std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const = 0;
+
+ virtual std::unique_ptr<IPDBEnumTables> getEnumTables() const = 0;
};
}
}
diff --git a/include/llvm/DebugInfo/PDB/IPDBTable.h b/include/llvm/DebugInfo/PDB/IPDBTable.h
new file mode 100644
index 0000000000000..4561c4e847b2b
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/IPDBTable.h
@@ -0,0 +1,28 @@
+//===- IPDBTable.h - Base Interface for a PDB Symbol Context ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_IPDBTABLE_H
+#define LLVM_DEBUGINFO_PDB_IPDBTABLE_H
+
+#include "PDBTypes.h"
+
+namespace llvm {
+namespace pdb {
+class IPDBTable {
+public:
+ virtual ~IPDBTable();
+
+ virtual std::string getName() const = 0;
+ virtual uint32_t getItemCount() const = 0;
+ virtual PDB_TableType getTableType() const = 0;
+};
+}
+}
+
+#endif // LLVM_DEBUGINFO_PDB_IPDBTABLE_H
diff --git a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
index 63eb34f0326af..ad4a0d1bcb6bf 100644
--- a/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h
@@ -59,11 +59,11 @@ public:
uint32_t calculateSerializedLength() const;
+ void setGlobalsStreamIndex(uint32_t Index);
void setPublicsStreamIndex(uint32_t Index);
void setSymbolRecordStreamIndex(uint32_t Index);
Expected<DbiModuleDescriptorBuilder &> addModuleInfo(StringRef ModuleName);
- Error addModuleSourceFile(StringRef Module, StringRef File);
Error addModuleSourceFile(DbiModuleDescriptorBuilder &Module, StringRef File);
Expected<uint32_t> getSourceFileNameIndex(StringRef FileName);
@@ -71,8 +71,9 @@ public:
Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef MsfBuffer);
- void addSectionContrib(DbiModuleDescriptorBuilder *ModuleDbi,
- const llvm::object::coff_section *SecHdr);
+ void addSectionContrib(const SectionContrib &SC) {
+ SectionContribs.emplace_back(SC);
+ }
// A helper function to create a Section Map from a COFF section header.
static std::vector<SecMapEntry>
@@ -105,13 +106,13 @@ private:
uint16_t PdbDllRbld;
uint16_t Flags;
PDB_Machine MachineType;
+ uint32_t GlobalsStreamIndex = kInvalidStreamIndex;
uint32_t PublicsStreamIndex = kInvalidStreamIndex;
uint32_t SymRecordStreamIndex = kInvalidStreamIndex;
const DbiStreamHeader *Header;
- StringMap<std::unique_ptr<DbiModuleDescriptorBuilder>> ModiMap;
- std::vector<DbiModuleDescriptorBuilder *> ModiList;
+ std::vector<std::unique_ptr<DbiModuleDescriptorBuilder>> ModiList;
StringMap<uint32_t> SourceFileNames;
diff --git a/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h
new file mode 100644
index 0000000000000..1a4f89d607dff
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h
@@ -0,0 +1,82 @@
+//===- GSIStreamBuilder.h - PDB Publics/Globals Stream Creation -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_RAW_GSISTREAMBUILDER_H
+#define LLVM_DEBUGINFO_PDB_RAW_GSISTREAMBUILDER_H
+
+#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
+#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
+#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include "llvm/Support/BinaryByteStream.h"
+#include "llvm/Support/BinaryItemStream.h"
+#include "llvm/Support/BinaryStreamRef.h"
+#include "llvm/Support/BinaryStreamWriter.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+
+template <> struct BinaryItemTraits<codeview::CVSymbol> {
+ static size_t length(const codeview::CVSymbol &Item) {
+ return Item.RecordData.size();
+ }
+ static ArrayRef<uint8_t> bytes(const codeview::CVSymbol &Item) {
+ return Item.RecordData;
+ }
+};
+
+namespace msf {
+class MSFBuilder;
+struct MSFLayout;
+} // namespace msf
+namespace pdb {
+struct GSIHashStreamBuilder;
+
+class GSIStreamBuilder {
+
+public:
+ explicit GSIStreamBuilder(msf::MSFBuilder &Msf);
+ ~GSIStreamBuilder();
+
+ GSIStreamBuilder(const GSIStreamBuilder &) = delete;
+ GSIStreamBuilder &operator=(const GSIStreamBuilder &) = delete;
+
+ Error finalizeMsfLayout();
+
+ Error commit(const msf::MSFLayout &Layout, WritableBinaryStreamRef Buffer);
+
+ uint32_t getPublicsStreamIndex() const;
+ uint32_t getGlobalsStreamIndex() const;
+ uint32_t getRecordStreamIdx() const { return RecordStreamIdx; }
+
+ void addPublicSymbol(const codeview::PublicSym32 &Pub);
+
+ void addGlobalSymbol(const codeview::ProcRefSym &Sym);
+ void addGlobalSymbol(const codeview::DataSym &Sym);
+ void addGlobalSymbol(const codeview::ConstantSym &Sym);
+ void addGlobalSymbol(const codeview::UDTSym &Sym);
+ void addGlobalSymbol(const codeview::CVSymbol &Sym);
+
+private:
+ uint32_t calculatePublicsHashStreamSize() const;
+ uint32_t calculateGlobalsHashStreamSize() const;
+ Error commitSymbolRecordStream(WritableBinaryStreamRef Stream);
+ Error commitPublicsHashStream(WritableBinaryStreamRef Stream);
+ Error commitGlobalsHashStream(WritableBinaryStreamRef Stream);
+
+ uint32_t RecordStreamIdx = kInvalidStreamIndex;
+ msf::MSFBuilder &Msf;
+ std::unique_ptr<GSIHashStreamBuilder> PSH;
+ std::unique_ptr<GSIHashStreamBuilder> GSH;
+};
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h b/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h
index dcea3d3be0ab8..fdc58dc60f7e0 100644
--- a/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/GlobalsStream.h
@@ -1,4 +1,4 @@
-//===- GlobalsStream.h - PDB Index of Symbols by Name ------ ----*- C++ -*-===//
+//===- GlobalsStream.h - PDB Index of Symbols by Name -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -16,27 +16,66 @@
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/Support/BinaryStreamArray.h"
#include "llvm/Support/Error.h"
+#include "llvm/ADT/iterator.h"
namespace llvm {
namespace pdb {
class DbiStream;
class PDBFile;
+/// Iterator over hash records producing symbol record offsets. Abstracts away
+/// the fact that symbol record offsets on disk are off-by-one.
+class GSIHashIterator
+ : public iterator_adaptor_base<
+ GSIHashIterator, FixedStreamArrayIterator<PSHashRecord>,
+ std::random_access_iterator_tag, const uint32_t> {
+public:
+ GSIHashIterator() = default;
+
+ template <typename T>
+ GSIHashIterator(T &&v)
+ : GSIHashIterator::iterator_adaptor_base(std::forward<T &&>(v)) {}
+
+ uint32_t operator*() const {
+ uint32_t Off = this->I->Off;
+ return --Off;
+ }
+};
+
+/// From https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.cpp
+enum : unsigned { IPHR_HASH = 4096 };
+
+/// A readonly view of a hash table used in the globals and publics streams.
+/// Most clients will only want to iterate this to get symbol record offsets
+/// into the PDB symbol stream.
+class GSIHashTable {
+public:
+ const GSIHashHeader *HashHdr;
+ FixedStreamArray<PSHashRecord> HashRecords;
+ ArrayRef<uint8_t> HashBitmap;
+ FixedStreamArray<support::ulittle32_t> HashBuckets;
+
+ Error read(BinaryStreamReader &Reader);
+
+ uint32_t getVerSignature() const { return HashHdr->VerSignature; }
+ uint32_t getVerHeader() const { return HashHdr->VerHdr; }
+ uint32_t getHashRecordSize() const { return HashHdr->HrSize; }
+ uint32_t getNumBuckets() const { return HashHdr->NumBuckets; }
+
+ typedef GSIHashHeader iterator;
+ GSIHashIterator begin() const { return GSIHashIterator(HashRecords.begin()); }
+ GSIHashIterator end() const { return GSIHashIterator(HashRecords.end()); }
+};
+
class GlobalsStream {
public:
explicit GlobalsStream(std::unique_ptr<msf::MappedBlockStream> Stream);
~GlobalsStream();
- Error commit();
- FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
- return HashBuckets;
- }
- uint32_t getNumBuckets() const { return NumBuckets; }
+ const GSIHashTable &getGlobalsTable() const { return GlobalsTable; }
Error reload();
private:
- FixedStreamArray<support::ulittle32_t> HashBuckets;
- FixedStreamArray<PSHashRecord> HashRecords;
- uint32_t NumBuckets;
+ GSIHashTable GlobalsTable;
std::unique_ptr<msf::MappedBlockStream> Stream;
};
}
diff --git a/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h b/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h
index f413fd1b336ec..6602264d1b747 100644
--- a/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/ModuleDebugStream.h
@@ -32,6 +32,7 @@ public:
ModuleDebugStreamRef(const DbiModuleDescriptor &Module,
std::unique_ptr<msf::MappedBlockStream> Stream);
ModuleDebugStreamRef(ModuleDebugStreamRef &&Other) = default;
+ ModuleDebugStreamRef(const ModuleDebugStreamRef &Other) = default;
~ModuleDebugStreamRef();
Error reload();
@@ -51,6 +52,9 @@ public:
ModuleDebugStreamRef &operator=(ModuleDebugStreamRef &&Other) = default;
iterator_range<DebugSubsectionIterator> subsections() const;
+ codeview::DebugSubsectionArray getSubsectionsArray() const {
+ return Subsections;
+ }
bool hasDebugSubsections() const;
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h
new file mode 100644
index 0000000000000..41b7b78b8d80a
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/NativeEnumSymbol.h
@@ -0,0 +1,60 @@
+//===- NativeEnumSymbol.h - info about enum type ----------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H
+
+#include "llvm/DebugInfo/CodeView/CodeView.h"
+#include "llvm/DebugInfo/CodeView/TypeVisitorCallbacks.h"
+#include "llvm/DebugInfo/PDB/Native/NativeRawSymbol.h"
+#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
+
+namespace llvm {
+namespace pdb {
+
+class NativeEnumSymbol : public NativeRawSymbol,
+ public codeview::TypeVisitorCallbacks {
+public:
+ NativeEnumSymbol(NativeSession &Session, SymIndexId Id,
+ const codeview::CVType &CV);
+ ~NativeEnumSymbol() override;
+
+ std::unique_ptr<NativeRawSymbol> clone() const override;
+
+ std::unique_ptr<IPDBEnumSymbols>
+ findChildren(PDB_SymType Type) const override;
+
+ Error visitKnownRecord(codeview::CVType &CVR,
+ codeview::EnumRecord &Record) override;
+ Error visitKnownMember(codeview::CVMemberRecord &CVM,
+ codeview::EnumeratorRecord &Record) override;
+
+ PDB_SymType getSymTag() const override;
+ uint32_t getClassParentId() const override;
+ uint32_t getUnmodifiedTypeId() const override;
+ bool hasConstructor() const override;
+ bool hasAssignmentOperator() const override;
+ bool hasCastOperator() const override;
+ uint64_t getLength() const override;
+ std::string getName() const override;
+ bool isNested() const override;
+ bool hasOverloadedOperator() const override;
+ bool isPacked() const override;
+ bool isScoped() const override;
+ uint32_t getTypeId() const override;
+
+protected:
+ codeview::CVType CV;
+ codeview::EnumRecord Record;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif // LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMSYMBOL_H
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h b/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h
new file mode 100644
index 0000000000000..e0a5c8d9ad814
--- /dev/null
+++ b/include/llvm/DebugInfo/PDB/Native/NativeEnumTypes.h
@@ -0,0 +1,51 @@
+//==- NativeEnumTypes.h - Native Type Enumerator impl ------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMTYPES_H
+#define LLVM_DEBUGINFO_PDB_NATIVE_NATIVEENUMTYPES_H
+
+#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.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 NativeEnumTypes : public IPDBEnumChildren<PDBSymbol> {
+public:
+ NativeEnumTypes(NativeSession &Session,
+ codeview::LazyRandomTypeCollection &TypeCollection,
+ codeview::TypeLeafKind Kind);
+
+ uint32_t getChildCount() const override;
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override;
+ std::unique_ptr<PDBSymbol> getNext() override;
+ void reset() override;
+ NativeEnumTypes *clone() const override;
+
+private:
+ NativeEnumTypes(NativeSession &Session,
+ const std::vector<codeview::TypeIndex> &Matches,
+ codeview::TypeLeafKind Kind);
+
+ std::vector<codeview::TypeIndex> Matches;
+ uint32_t Index;
+ NativeSession &Session;
+ codeview::TypeLeafKind Kind;
+};
+
+} // namespace pdb
+} // namespace llvm
+
+#endif
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
index 2c6548dcce21f..931b93fb7266c 100644
--- a/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
+++ b/include/llvm/DebugInfo/PDB/Native/NativeRawSymbol.h
@@ -101,6 +101,7 @@ public:
uint32_t getTypeId() const override;
uint32_t getUavSlot() const override;
std::string getUndecoratedName() const override;
+ std::string getUndecoratedNameEx(PDB_UndnameFlags Flags) const override;
uint32_t getUnmodifiedTypeId() const override;
uint32_t getUpperBoundId() const override;
Variant getValue() const override;
diff --git a/include/llvm/DebugInfo/PDB/Native/NativeSession.h b/include/llvm/DebugInfo/PDB/Native/NativeSession.h
index b16ce231c349c..2e68ced46bfe8 100644
--- a/include/llvm/DebugInfo/PDB/Native/NativeSession.h
+++ b/include/llvm/DebugInfo/PDB/Native/NativeSession.h
@@ -22,6 +22,7 @@
#include "llvm/Support/Error.h"
namespace llvm {
+class MemoryBuffer;
namespace pdb {
class PDBFile;
@@ -31,7 +32,7 @@ public:
std::unique_ptr<BumpPtrAllocator> Allocator);
~NativeSession() override;
- static Error createFromPdb(StringRef Path,
+ static Error createFromPdb(std::unique_ptr<MemoryBuffer> MB,
std::unique_ptr<IPDBSession> &Session);
static Error createFromExe(StringRef Path,
std::unique_ptr<IPDBSession> &Session);
@@ -39,6 +40,12 @@ public:
std::unique_ptr<PDBSymbolCompiland>
createCompilandSymbol(DbiModuleDescriptor MI);
+ std::unique_ptr<PDBSymbolTypeEnum>
+ createEnumSymbol(codeview::TypeIndex Index);
+
+ std::unique_ptr<IPDBEnumSymbols>
+ createTypeEnumerator(codeview::TypeLeafKind Kind);
+
SymIndexId findSymbolByTypeIndex(codeview::TypeIndex TI);
uint64_t getLoadAddress() const override;
@@ -76,6 +83,8 @@ public:
std::unique_ptr<IPDBEnumDataStreams> getDebugStreams() const override;
+ std::unique_ptr<IPDBEnumTables> getEnumTables() const override;
+
PDBFile &getPDBFile() { return *Pdb; }
const PDBFile &getPDBFile() const { return *Pdb; }
diff --git a/include/llvm/DebugInfo/PDB/Native/PDBFile.h b/include/llvm/DebugInfo/PDB/Native/PDBFile.h
index 4f6ad115e7dfd..5e39ac3e37b72 100644
--- a/include/llvm/DebugInfo/PDB/Native/PDBFile.h
+++ b/include/llvm/DebugInfo/PDB/Native/PDBFile.h
@@ -13,7 +13,6 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/DebugInfo/MSF/IMSFFile.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
-#include "llvm/DebugInfo/MSF/MSFStreamLayout.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/BinaryStreamRef.h"
#include "llvm/Support/Endian.h"
@@ -62,6 +61,7 @@ public:
uint64_t getBlockMapOffset() const;
uint32_t getNumStreams() const override;
+ uint32_t getMaxStreamSize() const;
uint32_t getStreamByteSize(uint32_t StreamIndex) const override;
ArrayRef<support::ulittle32_t>
getStreamBlockList(uint32_t StreamIndex) const override;
@@ -72,8 +72,6 @@ public:
Error setBlockData(uint32_t BlockIndex, uint32_t Offset,
ArrayRef<uint8_t> Data) const override;
- ArrayRef<uint32_t> getFpmPages() const { return FpmPages; }
-
ArrayRef<support::ulittle32_t> getStreamSizes() const {
return ContainerLayout.StreamSizes;
}
@@ -86,7 +84,10 @@ public:
ArrayRef<support::ulittle32_t> getDirectoryBlockArray() const;
+ std::unique_ptr<msf::MappedBlockStream> createIndexedStream(uint16_t SN);
+
msf::MSFStreamLayout getStreamLayout(uint32_t StreamIdx) const;
+ msf::MSFStreamLayout getFpmStreamLayout() const;
Error parseFileHeaders();
Error parseStreamData();
@@ -104,7 +105,7 @@ public:
bool hasPDBDbiStream() const;
bool hasPDBGlobalsStream();
- bool hasPDBInfoStream();
+ bool hasPDBInfoStream() const;
bool hasPDBIpiStream() const;
bool hasPDBPublicsStream();
bool hasPDBSymbolStream();
@@ -124,7 +125,6 @@ private:
std::unique_ptr<BinaryStream> Buffer;
- std::vector<uint32_t> FpmPages;
msf::MSFLayout ContainerLayout;
std::unique_ptr<GlobalsStream> Globals;
diff --git a/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h b/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
index 2dc23f819d3bd..7ed164bee9ee2 100644
--- a/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
+++ b/include/llvm/DebugInfo/PDB/Native/PDBFileBuilder.h
@@ -31,7 +31,7 @@ class MSFBuilder;
namespace pdb {
class DbiStreamBuilder;
class InfoStreamBuilder;
-class PublicsStreamBuilder;
+class GSIStreamBuilder;
class TpiStreamBuilder;
class PDBFileBuilder {
@@ -49,7 +49,7 @@ public:
TpiStreamBuilder &getTpiBuilder();
TpiStreamBuilder &getIpiBuilder();
PDBStringTableBuilder &getStringTableBuilder();
- PublicsStreamBuilder &getPublicsBuilder();
+ GSIStreamBuilder &getGsiBuilder();
Error commit(StringRef Filename);
@@ -59,12 +59,14 @@ public:
private:
Expected<msf::MSFLayout> finalizeMsfLayout();
+ void commitFpm(WritableBinaryStream &MsfBuffer, const msf::MSFLayout &Layout);
+
BumpPtrAllocator &Allocator;
std::unique_ptr<msf::MSFBuilder> Msf;
std::unique_ptr<InfoStreamBuilder> Info;
std::unique_ptr<DbiStreamBuilder> Dbi;
- std::unique_ptr<PublicsStreamBuilder> Publics;
+ std::unique_ptr<GSIStreamBuilder> Gsi;
std::unique_ptr<TpiStreamBuilder> Tpi;
std::unique_ptr<TpiStreamBuilder> Ipi;
diff --git a/include/llvm/DebugInfo/PDB/Native/PublicsStream.h b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h
index 9ace826bd8f71..2d0222a9071a0 100644
--- a/include/llvm/DebugInfo/PDB/Native/PublicsStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/PublicsStream.h
@@ -12,6 +12,7 @@
#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
#include "llvm/DebugInfo/MSF/MappedBlockStream.h"
+#include "llvm/DebugInfo/PDB/Native/GlobalsStream.h"
#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
@@ -26,19 +27,14 @@ class PDBFile;
class PublicsStream {
public:
- PublicsStream(PDBFile &File, std::unique_ptr<msf::MappedBlockStream> Stream);
+ PublicsStream(std::unique_ptr<msf::MappedBlockStream> Stream);
~PublicsStream();
Error reload();
uint32_t getSymHash() const;
- uint32_t getAddrMap() const;
- uint32_t getNumBuckets() const { return NumBuckets; }
- Expected<const codeview::CVSymbolArray &> getSymbolArray() const;
- iterator_range<codeview::CVSymbolArray::Iterator>
- getSymbols(bool *HadError) const;
- FixedStreamArray<support::ulittle32_t> getHashBuckets() const {
- return HashBuckets;
- }
+ uint16_t getThunkTableSection() const;
+ uint32_t getThunkTableOffset() const;
+ const GSIHashTable &getPublicsTable() const { return PublicsTable; }
FixedStreamArray<support::ulittle32_t> getAddressMap() const {
return AddressMap;
}
@@ -49,22 +45,14 @@ public:
return SectionOffsets;
}
- Error commit();
-
private:
- PDBFile &Pdb;
-
std::unique_ptr<msf::MappedBlockStream> Stream;
- uint32_t NumBuckets = 0;
- ArrayRef<uint8_t> Bitmap;
- FixedStreamArray<PSHashRecord> HashRecords;
- FixedStreamArray<support::ulittle32_t> HashBuckets;
+ GSIHashTable PublicsTable;
FixedStreamArray<support::ulittle32_t> AddressMap;
FixedStreamArray<support::ulittle32_t> ThunkMap;
FixedStreamArray<SectionOffset> SectionOffsets;
const PublicsStreamHeader *Header;
- const GSIHashHeader *HashHdr;
};
}
}
diff --git a/include/llvm/DebugInfo/PDB/Native/PublicsStreamBuilder.h b/include/llvm/DebugInfo/PDB/Native/PublicsStreamBuilder.h
deleted file mode 100644
index 5ab57ebef53d4..0000000000000
--- a/include/llvm/DebugInfo/PDB/Native/PublicsStreamBuilder.h
+++ /dev/null
@@ -1,54 +0,0 @@
-//===- PublicsStreamBuilder.h - PDB Publics Stream Creation -----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_DEBUGINFO_PDB_RAW_PDBPUBLICSTREAMBUILDER_H
-#define LLVM_DEBUGINFO_PDB_RAW_PDBPUBLICSTREAMBUILDER_H
-
-#include "llvm/DebugInfo/PDB/Native/RawConstants.h"
-#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
-#include "llvm/Support/BinaryByteStream.h"
-#include "llvm/Support/BinaryStreamRef.h"
-#include "llvm/Support/BinaryStreamWriter.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/Error.h"
-
-namespace llvm {
-namespace msf {
-class MSFBuilder;
-}
-namespace pdb {
-class PublicsStream;
-struct PublicsStreamHeader;
-
-class PublicsStreamBuilder {
-public:
- explicit PublicsStreamBuilder(msf::MSFBuilder &Msf);
- ~PublicsStreamBuilder();
-
- PublicsStreamBuilder(const PublicsStreamBuilder &) = delete;
- PublicsStreamBuilder &operator=(const PublicsStreamBuilder &) = delete;
-
- Error finalizeMsfLayout();
- uint32_t calculateSerializedLength() const;
-
- Error commit(BinaryStreamWriter &PublicsWriter);
-
- uint32_t getStreamIndex() const { return StreamIdx; }
- uint32_t getRecordStreamIdx() const { return RecordStreamIdx; }
-
-private:
- uint32_t StreamIdx = kInvalidStreamIndex;
- uint32_t RecordStreamIdx = kInvalidStreamIndex;
- std::vector<PSHashRecord> HashRecords;
- msf::MSFBuilder &Msf;
-};
-} // namespace pdb
-} // namespace llvm
-
-#endif
diff --git a/include/llvm/DebugInfo/PDB/Native/RawTypes.h b/include/llvm/DebugInfo/PDB/Native/RawTypes.h
index b6321cbf45a82..8cc083685265a 100644
--- a/include/llvm/DebugInfo/PDB/Native/RawTypes.h
+++ b/include/llvm/DebugInfo/PDB/Native/RawTypes.h
@@ -23,6 +23,20 @@ struct SectionOffset {
char Padding[2];
};
+/// Header of the hash tables found in the globals and publics sections.
+/// Based on GSIHashHdr in
+/// https://github.com/Microsoft/microsoft-pdb/blob/master/PDB/dbi/gsi.h
+struct GSIHashHeader {
+ enum : unsigned {
+ HdrSignature = ~0U,
+ HdrVersion = 0xeffe0000 + 19990810,
+ };
+ support::ulittle32_t VerSignature;
+ support::ulittle32_t VerHdr;
+ support::ulittle32_t HrSize;
+ support::ulittle32_t NumBuckets;
+};
+
// This is HRFile.
struct PSHashRecord {
support::ulittle32_t Off; // Offset in the symbol record stream
diff --git a/include/llvm/DebugInfo/PDB/Native/SymbolStream.h b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h
index 17695f587849e..ae9f7d657b701 100644
--- a/include/llvm/DebugInfo/PDB/Native/SymbolStream.h
+++ b/include/llvm/DebugInfo/PDB/Native/SymbolStream.h
@@ -31,6 +31,8 @@ public:
return SymbolRecords;
}
+ codeview::CVSymbol readRecord(uint32_t Offset) const;
+
iterator_range<codeview::CVSymbolArray::Iterator>
getSymbols(bool *HadError) const;
diff --git a/include/llvm/DebugInfo/PDB/PDBSymbol.h b/include/llvm/DebugInfo/PDB/PDBSymbol.h
index 9e883d2f99a7a..04373463212b1 100644
--- a/include/llvm/DebugInfo/PDB/PDBSymbol.h
+++ b/include/llvm/DebugInfo/PDB/PDBSymbol.h
@@ -7,8 +7,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H
-#define LLVM_DEBUGINFO_PDB_IPDBSYMBOL_H
+#ifndef LLVM_DEBUGINFO_PDB_PDBSYMBOL_H
+#define LLVM_DEBUGINFO_PDB_PDBSYMBOL_H
#include "ConcreteSymbolEnumerator.h"
#include "IPDBRawSymbol.h"
diff --git a/include/llvm/DebugInfo/PDB/PDBTypes.h b/include/llvm/DebugInfo/PDB/PDBTypes.h
index 79ec7ce906d57..a6c6da37d1ccc 100644
--- a/include/llvm/DebugInfo/PDB/PDBTypes.h
+++ b/include/llvm/DebugInfo/PDB/PDBTypes.h
@@ -13,6 +13,7 @@
#include "llvm/DebugInfo/CodeView/CodeView.h"
#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
#include "llvm/DebugInfo/PDB/Native/RawTypes.h"
+#include <cctype>
#include <cstddef>
#include <cstdint>
#include <cstring>
@@ -24,6 +25,7 @@ namespace pdb {
class IPDBDataStream;
class IPDBLineNumber;
class IPDBSourceFile;
+class IPDBTable;
class PDBSymDumper;
class PDBSymbol;
class PDBSymbolExe;
@@ -62,6 +64,7 @@ using IPDBEnumSymbols = IPDBEnumChildren<PDBSymbol>;
using IPDBEnumSourceFiles = IPDBEnumChildren<IPDBSourceFile>;
using IPDBEnumDataStreams = IPDBEnumChildren<IPDBDataStream>;
using IPDBEnumLineNumbers = IPDBEnumChildren<IPDBLineNumber>;
+using IPDBEnumTables = IPDBEnumChildren<IPDBTable>;
/// Specifies which PDB reader implementation is to be used. Only a value
/// of PDB_ReaderType::DIA is currently supported, but Native is in the works.
@@ -72,13 +75,16 @@ enum class PDB_ReaderType {
/// An enumeration indicating the type of data contained in this table.
enum class PDB_TableType {
+ TableInvalid = 0,
Symbols,
SourceFiles,
LineNumbers,
SectionContribs,
Segments,
InjectedSources,
- FrameData
+ FrameData,
+ InputAssemblyFiles,
+ Dbg
};
/// Defines flags used for enumerating child symbols. This corresponds to the
@@ -241,6 +247,32 @@ enum class PDB_BuiltinType {
HResult = 31
};
+/// These values correspond to the flags that can be combined to control the
+/// return of an undecorated name for a C++ decorated name, and are documented
+/// here: https://msdn.microsoft.com/en-us/library/kszfk0fs.aspx
+enum PDB_UndnameFlags: uint32_t {
+ Undname_Complete = 0x0,
+ Undname_NoLeadingUnderscores = 0x1,
+ Undname_NoMsKeywords = 0x2,
+ Undname_NoFuncReturns = 0x4,
+ Undname_NoAllocModel = 0x8,
+ Undname_NoAllocLang = 0x10,
+ Undname_Reserved1 = 0x20,
+ Undname_Reserved2 = 0x40,
+ Undname_NoThisType = 0x60,
+ Undname_NoAccessSpec = 0x80,
+ Undname_NoThrowSig = 0x100,
+ Undname_NoMemberType = 0x200,
+ Undname_NoReturnUDTModel = 0x400,
+ Undname_32BitDecode = 0x800,
+ Undname_NameOnly = 0x1000,
+ Undname_TypeOnly = 0x2000,
+ Undname_HaveParams = 0x4000,
+ Undname_NoECSU = 0x8000,
+ Undname_NoIdentCharCheck = 0x10000,
+ Undname_NoPTR64 = 0x20000
+};
+
enum class PDB_MemberAccess { Private = 1, Protected = 2, Public = 3 };
struct VersionInfo {
diff --git a/include/llvm/DebugInfo/Symbolize/Symbolize.h b/include/llvm/DebugInfo/Symbolize/Symbolize.h
index d98d49b24bca2..6480aef109c66 100644
--- a/include/llvm/DebugInfo/Symbolize/Symbolize.h
+++ b/include/llvm/DebugInfo/Symbolize/Symbolize.h
@@ -58,9 +58,11 @@ public:
}
Expected<DILineInfo> symbolizeCode(const std::string &ModuleName,
- uint64_t ModuleOffset);
+ uint64_t ModuleOffset,
+ StringRef DWPName = "");
Expected<DIInliningInfo> symbolizeInlinedCode(const std::string &ModuleName,
- uint64_t ModuleOffset);
+ uint64_t ModuleOffset,
+ StringRef DWPName = "");
Expected<DIGlobal> symbolizeData(const std::string &ModuleName,
uint64_t ModuleOffset);
void flush();
@@ -79,7 +81,7 @@ private:
/// only reported once. Subsequent calls to get module info for a module that
/// failed to load will return nullptr.
Expected<SymbolizableModule *>
- getOrCreateModuleInfo(const std::string &ModuleName);
+ getOrCreateModuleInfo(const std::string &ModuleName, StringRef DWPName = "");
ObjectFile *lookUpDsymFile(const std::string &Path,
const MachOObjectFile *ExeObj,