summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/DebugInfo
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/DebugInfo')
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp165
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/Line.cpp22
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp31
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp35
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp49
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp113
-rw-r--r--contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp217
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp97
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp132
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp33
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp814
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp115
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp104
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp129
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp521
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp460
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp688
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp127
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp103
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp69
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp595
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp40
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp405
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp168
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp38
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.h39
-rw-r--r--contrib/llvm/lib/DebugInfo/DWARF/module.modulemap1
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIADataStream.cpp73
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp53
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp50
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp50
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp54
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIALineNumber.cpp75
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp1095
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp205
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp67
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp32
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDB.cpp39
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp120
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp339
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp28
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp146
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp151
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp24
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp23
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp24
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp31
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp28
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp27
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp22
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp102
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp22
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp22
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp29
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp24
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp26
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp34
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp24
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp90
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp29
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp24
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp22
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp24
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp23
-rw-r--r--contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp25
-rw-r--r--contrib/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp69
-rw-r--r--contrib/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp254
-rw-r--r--contrib/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h82
-rw-r--r--contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp456
78 files changed, 9672 insertions, 0 deletions
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
new file mode 100644
index 0000000..91b71cc
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/FieldListRecordBuilder.cpp
@@ -0,0 +1,165 @@
+//===-- FieldListRecordBuilder.cpp ----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
+
+using namespace llvm;
+using namespace codeview;
+
+FieldListRecordBuilder::FieldListRecordBuilder()
+ : ListRecordBuilder(TypeRecordKind::FieldList) {}
+
+void FieldListRecordBuilder::writeBaseClass(MemberAccess Access, TypeIndex Type,
+ uint64_t Offset) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ Builder.writeTypeRecordKind(TypeRecordKind::BaseClass);
+ Builder.writeUInt16(static_cast<uint16_t>(Access));
+ Builder.writeTypeIndex(Type);
+ Builder.writeEncodedUnsignedInteger(Offset);
+
+ finishSubRecord();
+}
+
+void FieldListRecordBuilder::writeEnumerate(MemberAccess Access, uint64_t Value,
+ StringRef Name) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ Builder.writeTypeRecordKind(TypeRecordKind::Enumerate);
+ Builder.writeUInt16(static_cast<uint16_t>(Access));
+ Builder.writeEncodedUnsignedInteger(Value);
+ Builder.writeNullTerminatedString(Name);
+
+ finishSubRecord();
+}
+
+void FieldListRecordBuilder::writeMember(MemberAccess Access, TypeIndex Type,
+ uint64_t Offset, StringRef Name) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ Builder.writeTypeRecordKind(TypeRecordKind::Member);
+ Builder.writeUInt16(static_cast<uint16_t>(Access));
+ Builder.writeTypeIndex(Type);
+ Builder.writeEncodedUnsignedInteger(Offset);
+ Builder.writeNullTerminatedString(Name);
+
+ finishSubRecord();
+}
+
+void FieldListRecordBuilder::writeMethod(uint16_t OverloadCount,
+ TypeIndex MethodList, StringRef Name) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ Builder.writeTypeRecordKind(TypeRecordKind::Method);
+ Builder.writeUInt16(OverloadCount);
+ Builder.writeTypeIndex(MethodList);
+ Builder.writeNullTerminatedString(Name);
+
+ finishSubRecord();
+}
+
+void FieldListRecordBuilder::writeOneMethod(
+ MemberAccess Access, MethodKind Kind, MethodOptions Options, TypeIndex Type,
+ int32_t VTableSlotOffset, StringRef Name) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ uint16_t Flags = static_cast<uint16_t>(Access);
+ Flags |= static_cast<uint16_t>(Kind) << MethodKindShift;
+ Flags |= static_cast<uint16_t>(Options);
+
+ Builder.writeTypeRecordKind(TypeRecordKind::OneMethod);
+ Builder.writeUInt16(Flags);
+ Builder.writeTypeIndex(Type);
+ switch (Kind) {
+ case MethodKind::IntroducingVirtual:
+ case MethodKind::PureIntroducingVirtual:
+ assert(VTableSlotOffset >= 0);
+ Builder.writeInt32(VTableSlotOffset);
+ break;
+
+ default:
+ assert(VTableSlotOffset == -1);
+ break;
+ }
+
+ Builder.writeNullTerminatedString(Name);
+
+ finishSubRecord();
+}
+
+void FieldListRecordBuilder::writeOneMethod(const MethodInfo &Method,
+ StringRef Name) {
+ writeOneMethod(Method.getAccess(), Method.getKind(), Method.getOptions(),
+ Method.getType(), Method.getVTableSlotOffset(), Name);
+}
+
+void FieldListRecordBuilder::writeNestedType(TypeIndex Type, StringRef Name) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ Builder.writeTypeRecordKind(TypeRecordKind::NestedType);
+ Builder.writeUInt16(0);
+ Builder.writeTypeIndex(Type);
+ Builder.writeNullTerminatedString(Name);
+
+ finishSubRecord();
+}
+
+void FieldListRecordBuilder::writeStaticMember(MemberAccess Access,
+ TypeIndex Type, StringRef Name) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ Builder.writeTypeRecordKind(TypeRecordKind::StaticMember);
+ Builder.writeUInt16(static_cast<uint16_t>(Access));
+ Builder.writeTypeIndex(Type);
+ Builder.writeNullTerminatedString(Name);
+
+ finishSubRecord();
+}
+
+void FieldListRecordBuilder::writeIndirectVirtualBaseClass(
+ MemberAccess Access, TypeIndex Type, TypeIndex VirtualBasePointerType,
+ int64_t VirtualBasePointerOffset, uint64_t SlotIndex) {
+ writeVirtualBaseClass(TypeRecordKind::IndirectVirtualBaseClass, Access, Type,
+ VirtualBasePointerType, VirtualBasePointerOffset,
+ SlotIndex);
+}
+
+void FieldListRecordBuilder::writeVirtualBaseClass(
+ MemberAccess Access, TypeIndex Type, TypeIndex VirtualBasePointerType,
+ int64_t VirtualBasePointerOffset, uint64_t SlotIndex) {
+ writeVirtualBaseClass(TypeRecordKind::VirtualBaseClass, Access, Type,
+ VirtualBasePointerType, VirtualBasePointerOffset,
+ SlotIndex);
+}
+
+void FieldListRecordBuilder::writeVirtualBaseClass(
+ TypeRecordKind Kind, MemberAccess Access, TypeIndex Type,
+ TypeIndex VirtualBasePointerType, int64_t VirtualBasePointerOffset,
+ uint64_t SlotIndex) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ Builder.writeTypeRecordKind(Kind);
+ Builder.writeUInt16(static_cast<uint16_t>(Access));
+ Builder.writeTypeIndex(Type);
+ Builder.writeTypeIndex(VirtualBasePointerType);
+ Builder.writeEncodedInteger(VirtualBasePointerOffset);
+ Builder.writeEncodedUnsignedInteger(SlotIndex);
+
+ finishSubRecord();
+}
+
+void FieldListRecordBuilder::writeVirtualFunctionTablePointer(TypeIndex Type) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ Builder.writeTypeRecordKind(TypeRecordKind::VirtualFunctionTablePointer);
+ Builder.writeUInt16(0);
+ Builder.writeTypeIndex(Type);
+
+ finishSubRecord();
+} \ No newline at end of file
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/Line.cpp b/contrib/llvm/lib/DebugInfo/CodeView/Line.cpp
new file mode 100644
index 0000000..4cb766b
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/Line.cpp
@@ -0,0 +1,22 @@
+//===-- Line.cpp ----------------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/Line.h"
+
+using namespace llvm;
+using namespace codeview;
+
+LineInfo::LineInfo(uint32_t StartLine, uint32_t EndLine, bool IsStatement) {
+ LineData = StartLine & StartLineMask;
+ uint32_t LineDelta = EndLine - StartLine;
+ LineData |= (LineDelta << EndLineDeltaShift) & EndLineDeltaMask;
+ if (IsStatement) {
+ LineData |= StatementFlag;
+ }
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
new file mode 100644
index 0000000..69c7e87
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/ListRecordBuilder.cpp
@@ -0,0 +1,31 @@
+//===-- ListRecordBuilder.cpp ---------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/ListRecordBuilder.h"
+
+using namespace llvm;
+using namespace codeview;
+
+ListRecordBuilder::ListRecordBuilder(TypeRecordKind Kind) : Builder(Kind) {}
+
+void ListRecordBuilder::finishSubRecord() {
+ // The builder starts at offset 2 in the actual CodeView buffer, so add an
+ // additional offset of 2 before computing the alignment.
+ uint32_t Remainder = (Builder.size() + 2) % 4;
+ if (Remainder != 0) {
+ for (int32_t PaddingBytesLeft = 4 - Remainder; PaddingBytesLeft > 0;
+ --PaddingBytesLeft) {
+ Builder.writeUInt8(0xf0 + PaddingBytesLeft);
+ }
+ }
+
+ // TODO: Split the list into multiple records if it's longer than 64KB, using
+ // a subrecord of TypeRecordKind::Index to chain the records together.
+ assert(Builder.size() < 65536);
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
new file mode 100644
index 0000000..9afce92
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/MemoryTypeTableBuilder.cpp
@@ -0,0 +1,35 @@
+//===-- MemoryTypeTableBuilder.cpp ----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/MemoryTypeTableBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+
+using namespace llvm;
+using namespace codeview;
+
+MemoryTypeTableBuilder::Record::Record(StringRef RData)
+ : Size(RData.size()), Data(new char[RData.size()]) {
+ memcpy(Data.get(), RData.data(), RData.size());
+}
+
+TypeIndex MemoryTypeTableBuilder::writeRecord(StringRef Data) {
+ auto I = HashedRecords.find(Data);
+ if (I != HashedRecords.end()) {
+ return I->second;
+ }
+
+ std::unique_ptr<Record> R(new Record(Data));
+
+ TypeIndex TI(static_cast<uint32_t>(Records.size()) +
+ TypeIndex::FirstNonSimpleIndex);
+ HashedRecords.insert(std::make_pair(StringRef(R->data(), R->size()), TI));
+ Records.push_back(std::move(R));
+
+ return TI;
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
new file mode 100644
index 0000000..8893025
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/MethodListRecordBuilder.cpp
@@ -0,0 +1,49 @@
+//===-- MethodListRecordBuilder.cpp ---------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/MethodListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
+
+using namespace llvm;
+using namespace codeview;
+
+MethodListRecordBuilder::MethodListRecordBuilder()
+ : ListRecordBuilder(TypeRecordKind::MethodList) {}
+
+void MethodListRecordBuilder::writeMethod(MemberAccess Access, MethodKind Kind,
+ MethodOptions Options, TypeIndex Type,
+ int32_t VTableSlotOffset) {
+ TypeRecordBuilder &Builder = getBuilder();
+
+ uint16_t Flags = static_cast<uint16_t>(Access);
+ Flags |= static_cast<uint16_t>(Kind) << MethodKindShift;
+ Flags |= static_cast<uint16_t>(Options);
+
+ Builder.writeUInt16(Flags);
+ Builder.writeUInt16(0);
+ Builder.writeTypeIndex(Type);
+ switch (Kind) {
+ case MethodKind::IntroducingVirtual:
+ case MethodKind::PureIntroducingVirtual:
+ assert(VTableSlotOffset >= 0);
+ Builder.writeInt32(VTableSlotOffset);
+ break;
+
+ default:
+ assert(VTableSlotOffset == -1);
+ break;
+ }
+
+ // TODO: Fail if too big?
+}
+
+void MethodListRecordBuilder::writeMethod(const MethodInfo &Method) {
+ writeMethod(Method.getAccess(), Method.getKind(), Method.getOptions(),
+ Method.getType(), Method.getVTableSlotOffset());
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
new file mode 100644
index 0000000..cbf464f
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeRecordBuilder.cpp
@@ -0,0 +1,113 @@
+//===-- TypeRecordBuilder.cpp ---------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"
+
+using namespace llvm;
+using namespace codeview;
+
+TypeRecordBuilder::TypeRecordBuilder(TypeRecordKind Kind) : Stream(Buffer),
+ Writer(Stream) {
+ writeTypeRecordKind(Kind);
+}
+
+StringRef TypeRecordBuilder::str() {
+ return StringRef(Buffer.data(), Buffer.size());
+}
+
+void TypeRecordBuilder::writeUInt8(uint8_t Value) {
+ Writer.write(Value);
+}
+
+void TypeRecordBuilder::writeInt16(int16_t Value) {
+ Writer.write(Value);
+}
+
+void TypeRecordBuilder::writeUInt16(uint16_t Value) {
+ Writer.write(Value);
+}
+
+void TypeRecordBuilder::writeInt32(int32_t Value) {
+ Writer.write(Value);
+}
+
+void TypeRecordBuilder::writeUInt32(uint32_t Value) {
+ Writer.write(Value);
+}
+
+void TypeRecordBuilder::writeInt64(int64_t Value) {
+ Writer.write(Value);
+}
+
+void TypeRecordBuilder::writeUInt64(uint64_t Value) {
+ Writer.write(Value);
+}
+
+void TypeRecordBuilder::writeEncodedInteger(int64_t Value) {
+ if (Value >= 0) {
+ writeEncodedUnsignedInteger(static_cast<uint64_t>(Value));
+ } else {
+ writeEncodedSignedInteger(Value);
+ }
+}
+
+void TypeRecordBuilder::writeEncodedSignedInteger(int64_t Value) {
+ if (Value >= std::numeric_limits<int8_t>::min() &&
+ Value <= std::numeric_limits<int8_t>::max()) {
+ writeUInt16(static_cast<uint16_t>(TypeRecordKind::SByte));
+ writeInt16(static_cast<int8_t>(Value));
+ } else if (Value >= std::numeric_limits<int16_t>::min() &&
+ Value <= std::numeric_limits<int16_t>::max()) {
+ writeUInt16(static_cast<uint16_t>(TypeRecordKind::Int16));
+ writeInt16(static_cast<int16_t>(Value));
+ } else if (Value >= std::numeric_limits<int32_t>::min() &&
+ Value <= std::numeric_limits<int32_t>::max()) {
+ writeUInt16(static_cast<uint32_t>(TypeRecordKind::Int32));
+ writeInt32(static_cast<int32_t>(Value));
+ } else {
+ writeUInt16(static_cast<uint16_t>(TypeRecordKind::Int64));
+ writeInt64(Value);
+ }
+}
+
+void TypeRecordBuilder::writeEncodedUnsignedInteger(uint64_t Value) {
+ if (Value < static_cast<uint16_t>(TypeRecordKind::SByte)) {
+ writeUInt16(static_cast<uint16_t>(Value));
+ } else if (Value <= std::numeric_limits<uint16_t>::max()) {
+ writeUInt16(static_cast<uint16_t>(TypeRecordKind::UInt16));
+ writeUInt16(static_cast<uint16_t>(Value));
+ } else if (Value <= std::numeric_limits<uint32_t>::max()) {
+ writeUInt16(static_cast<uint16_t>(TypeRecordKind::UInt32));
+ writeUInt32(static_cast<uint32_t>(Value));
+ } else {
+ writeUInt16(static_cast<uint16_t>(TypeRecordKind::UInt64));
+ writeUInt64(Value);
+ }
+}
+
+void TypeRecordBuilder::writeNullTerminatedString(const char *Value) {
+ assert(Value != nullptr);
+
+ size_t Length = strlen(Value);
+ Stream.write(Value, Length);
+ writeUInt8(0);
+}
+
+void TypeRecordBuilder::writeNullTerminatedString(StringRef Value) {
+ Stream.write(Value.data(), Value.size());
+ writeUInt8(0);
+}
+
+void TypeRecordBuilder::writeTypeIndex(TypeIndex TypeInd) {
+ writeUInt32(TypeInd.getIndex());
+}
+
+void TypeRecordBuilder::writeTypeRecordKind(TypeRecordKind Kind) {
+ writeUInt16(static_cast<uint16_t>(Kind));
+}
diff --git a/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp b/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
new file mode 100644
index 0000000..4af5dca
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/CodeView/TypeTableBuilder.cpp
@@ -0,0 +1,217 @@
+//===-- TypeTableBuilder.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/DebugInfo/CodeView/FieldListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/MethodListRecordBuilder.h"
+#include "llvm/DebugInfo/CodeView/TypeIndex.h"
+#include "llvm/DebugInfo/CodeView/TypeRecordBuilder.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace codeview;
+
+namespace {
+
+const int PointerKindShift = 0;
+const int PointerModeShift = 5;
+const int PointerSizeShift = 13;
+
+const int ClassHfaKindShift = 11;
+const int ClassWindowsRTClassKindShift = 14;
+
+void writePointerBase(TypeRecordBuilder &Builder,
+ const PointerRecordBase &Record) {
+ Builder.writeTypeIndex(Record.getReferentType());
+ uint32_t flags =
+ static_cast<uint32_t>(Record.getOptions()) |
+ (Record.getSize() << PointerSizeShift) |
+ (static_cast<uint32_t>(Record.getMode()) << PointerModeShift) |
+ (static_cast<uint32_t>(Record.getPointerKind()) << PointerKindShift);
+ Builder.writeUInt32(flags);
+}
+}
+
+TypeTableBuilder::TypeTableBuilder() {}
+
+TypeTableBuilder::~TypeTableBuilder() {}
+
+TypeIndex TypeTableBuilder::writeModifier(const ModifierRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::Modifier);
+
+ Builder.writeTypeIndex(Record.getModifiedType());
+ Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
+
+ return writeRecord(Builder);
+}
+
+TypeIndex TypeTableBuilder::writeProcedure(const ProcedureRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::Procedure);
+
+ Builder.writeTypeIndex(Record.getReturnType());
+ Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
+ Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
+ Builder.writeUInt16(Record.getParameterCount());
+ Builder.writeTypeIndex(Record.getArgumentList());
+
+ return writeRecord(Builder);
+}
+
+TypeIndex
+TypeTableBuilder::writeMemberFunction(const MemberFunctionRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::MemberFunction);
+
+ Builder.writeTypeIndex(Record.getReturnType());
+ Builder.writeTypeIndex(Record.getClassType());
+ Builder.writeTypeIndex(Record.getThisType());
+ Builder.writeUInt8(static_cast<uint8_t>(Record.getCallConv()));
+ Builder.writeUInt8(static_cast<uint8_t>(Record.getOptions()));
+ Builder.writeUInt16(Record.getParameterCount());
+ Builder.writeTypeIndex(Record.getArgumentList());
+ Builder.writeInt32(Record.getThisPointerAdjustment());
+
+ return writeRecord(Builder);
+}
+
+TypeIndex
+TypeTableBuilder::writeArgumentList(const ArgumentListRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::ArgumentList);
+
+ Builder.writeUInt32(Record.getArgumentTypes().size());
+ for (TypeIndex TI : Record.getArgumentTypes()) {
+ Builder.writeTypeIndex(TI);
+ }
+
+ return writeRecord(Builder);
+}
+
+TypeIndex TypeTableBuilder::writePointer(const PointerRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::Pointer);
+
+ writePointerBase(Builder, Record);
+
+ return writeRecord(Builder);
+}
+
+TypeIndex
+TypeTableBuilder::writePointerToMember(const PointerToMemberRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::Pointer);
+
+ writePointerBase(Builder, Record);
+
+ Builder.writeTypeIndex(Record.getContainingType());
+ Builder.writeUInt16(static_cast<uint16_t>(Record.getRepresentation()));
+
+ return writeRecord(Builder);
+}
+
+TypeIndex TypeTableBuilder::writeArray(const ArrayRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::Array);
+
+ Builder.writeTypeIndex(Record.getElementType());
+ Builder.writeTypeIndex(Record.getIndexType());
+ Builder.writeEncodedUnsignedInteger(Record.getSize());
+ Builder.writeNullTerminatedString(Record.getName());
+
+ return writeRecord(Builder);
+}
+
+TypeIndex TypeTableBuilder::writeAggregate(const AggregateRecord &Record) {
+ assert((Record.getKind() == TypeRecordKind::Structure) ||
+ (Record.getKind() == TypeRecordKind::Class) ||
+ (Record.getKind() == TypeRecordKind::Union));
+
+ TypeRecordBuilder Builder(Record.getKind());
+
+ Builder.writeUInt16(Record.getMemberCount());
+ uint16_t Flags =
+ static_cast<uint16_t>(Record.getOptions()) |
+ (static_cast<uint16_t>(Record.getHfa()) << ClassHfaKindShift) |
+ (static_cast<uint16_t>(Record.getWinRTKind())
+ << ClassWindowsRTClassKindShift);
+ Builder.writeUInt16(Flags);
+ Builder.writeTypeIndex(Record.getFieldList());
+ if (Record.getKind() != TypeRecordKind::Union) {
+ Builder.writeTypeIndex(Record.getDerivationList());
+ Builder.writeTypeIndex(Record.getVTableShape());
+ } else {
+ assert(Record.getDerivationList() == TypeIndex());
+ assert(Record.getVTableShape() == TypeIndex());
+ }
+ Builder.writeEncodedUnsignedInteger(Record.getSize());
+ Builder.writeNullTerminatedString(Record.getName());
+ if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
+ ClassOptions::None) {
+ Builder.writeNullTerminatedString(Record.getUniqueName());
+ }
+
+ return writeRecord(Builder);
+}
+
+TypeIndex TypeTableBuilder::writeEnum(const EnumRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::Enum);
+
+ Builder.writeUInt16(Record.getMemberCount());
+ Builder.writeUInt16(static_cast<uint16_t>(Record.getOptions()));
+ Builder.writeTypeIndex(Record.getUnderlyingType());
+ Builder.writeTypeIndex(Record.getFieldList());
+ Builder.writeNullTerminatedString(Record.getName());
+ if ((Record.getOptions() & ClassOptions::HasUniqueName) !=
+ ClassOptions::None) {
+ Builder.writeNullTerminatedString(Record.getUniqueName());
+ }
+
+ return writeRecord(Builder);
+}
+
+TypeIndex TypeTableBuilder::writeBitField(const BitFieldRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::BitField);
+
+ Builder.writeTypeIndex(Record.getType());
+ Builder.writeUInt8(Record.getBitSize());
+ Builder.writeUInt8(Record.getBitOffset());
+
+ return writeRecord(Builder);
+}
+
+TypeIndex TypeTableBuilder::writeVirtualTableShape(
+ const VirtualTableShapeRecord &Record) {
+ TypeRecordBuilder Builder(TypeRecordKind::VirtualTableShape);
+
+ ArrayRef<VirtualTableSlotKind> Slots = Record.getSlots();
+
+ Builder.writeUInt16(Slots.size());
+ for (size_t SlotIndex = 0; SlotIndex < Slots.size(); SlotIndex += 2) {
+ uint8_t Byte = static_cast<uint8_t>(Slots[SlotIndex]) << 4;
+ if ((SlotIndex + 1) < Slots.size()) {
+ Byte |= static_cast<uint8_t>(Slots[SlotIndex + 1]);
+ }
+ Builder.writeUInt8(Byte);
+ }
+
+ return writeRecord(Builder);
+}
+
+TypeIndex TypeTableBuilder::writeRecord(TypeRecordBuilder &Builder) {
+ return writeRecord(Builder.str());
+}
+
+TypeIndex TypeTableBuilder::writeFieldList(FieldListRecordBuilder &FieldList) {
+ // TODO: Split the list into multiple records if it's longer than 64KB, using
+ // a subrecord of TypeRecordKind::Index to chain the records together.
+ return writeRecord(FieldList.str());
+}
+
+TypeIndex
+TypeTableBuilder::writeMethodList(MethodListRecordBuilder &MethodList) {
+ // TODO: Split the list into multiple records if it's longer than 64KB, using
+ // a subrecord of TypeRecordKind::Index to chain the records together.
+ return writeRecord(MethodList.str());
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
new file mode 100644
index 0000000..9314c9e
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp
@@ -0,0 +1,97 @@
+//===-- DWARFAbbreviationDeclaration.cpp ----------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+using namespace dwarf;
+
+void DWARFAbbreviationDeclaration::clear() {
+ Code = 0;
+ Tag = 0;
+ HasChildren = false;
+ AttributeSpecs.clear();
+}
+
+DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() {
+ clear();
+}
+
+bool
+DWARFAbbreviationDeclaration::extract(DataExtractor Data, uint32_t* OffsetPtr) {
+ clear();
+ Code = Data.getULEB128(OffsetPtr);
+ if (Code == 0) {
+ return false;
+ }
+ Tag = Data.getULEB128(OffsetPtr);
+ uint8_t ChildrenByte = Data.getU8(OffsetPtr);
+ HasChildren = (ChildrenByte == DW_CHILDREN_yes);
+
+ while (true) {
+ uint32_t CurOffset = *OffsetPtr;
+ uint16_t Attr = Data.getULEB128(OffsetPtr);
+ if (CurOffset == *OffsetPtr) {
+ clear();
+ return false;
+ }
+ CurOffset = *OffsetPtr;
+ uint16_t Form = Data.getULEB128(OffsetPtr);
+ if (CurOffset == *OffsetPtr) {
+ clear();
+ return false;
+ }
+ if (Attr == 0 && Form == 0)
+ break;
+ AttributeSpecs.push_back(AttributeSpec(Attr, Form));
+ }
+
+ if (Tag == 0) {
+ clear();
+ return false;
+ }
+ return true;
+}
+
+void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const {
+ const char *tagString = TagString(getTag());
+ OS << '[' << getCode() << "] ";
+ if (tagString)
+ OS << tagString;
+ else
+ OS << format("DW_TAG_Unknown_%x", getTag());
+ OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n';
+ for (const AttributeSpec &Spec : AttributeSpecs) {
+ OS << '\t';
+ const char *attrString = AttributeString(Spec.Attr);
+ if (attrString)
+ OS << attrString;
+ else
+ OS << format("DW_AT_Unknown_%x", Spec.Attr);
+ OS << '\t';
+ const char *formString = FormEncodingString(Spec.Form);
+ if (formString)
+ OS << formString;
+ else
+ OS << format("DW_FORM_Unknown_%x", Spec.Form);
+ OS << '\n';
+ }
+ OS << '\n';
+}
+
+uint32_t
+DWARFAbbreviationDeclaration::findAttributeIndex(uint16_t attr) const {
+ for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) {
+ if (AttributeSpecs[i].Attr == attr)
+ return i;
+ }
+ return -1U;
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
new file mode 100644
index 0000000..8ae0543
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp
@@ -0,0 +1,132 @@
+//===--- DWARFAcceleratorTable.cpp ----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+bool DWARFAcceleratorTable::extract() {
+ uint32_t Offset = 0;
+
+ // Check that we can at least read the header.
+ if (!AccelSection.isValidOffset(offsetof(Header, HeaderDataLength)+4))
+ return false;
+
+ Hdr.Magic = AccelSection.getU32(&Offset);
+ Hdr.Version = AccelSection.getU16(&Offset);
+ Hdr.HashFunction = AccelSection.getU16(&Offset);
+ Hdr.NumBuckets = AccelSection.getU32(&Offset);
+ Hdr.NumHashes = AccelSection.getU32(&Offset);
+ Hdr.HeaderDataLength = AccelSection.getU32(&Offset);
+
+ // Check that we can read all the hashes and offsets from the
+ // section (see SourceLevelDebugging.rst for the structure of the index).
+ if (!AccelSection.isValidOffset(sizeof(Hdr) + Hdr.HeaderDataLength +
+ Hdr.NumBuckets*4 + Hdr.NumHashes*8))
+ return false;
+
+ HdrData.DIEOffsetBase = AccelSection.getU32(&Offset);
+ uint32_t NumAtoms = AccelSection.getU32(&Offset);
+
+ for (unsigned i = 0; i < NumAtoms; ++i) {
+ uint16_t AtomType = AccelSection.getU16(&Offset);
+ uint16_t AtomForm = AccelSection.getU16(&Offset);
+ HdrData.Atoms.push_back(std::make_pair(AtomType, AtomForm));
+ }
+
+ return true;
+}
+
+void DWARFAcceleratorTable::dump(raw_ostream &OS) const {
+ // Dump the header.
+ OS << "Magic = " << format("0x%08x", Hdr.Magic) << '\n'
+ << "Version = " << format("0x%04x", Hdr.Version) << '\n'
+ << "Hash function = " << format("0x%08x", Hdr.HashFunction) << '\n'
+ << "Bucket count = " << Hdr.NumBuckets << '\n'
+ << "Hashes count = " << Hdr.NumHashes << '\n'
+ << "HeaderData length = " << Hdr.HeaderDataLength << '\n'
+ << "DIE offset base = " << HdrData.DIEOffsetBase << '\n'
+ << "Number of atoms = " << HdrData.Atoms.size() << '\n';
+
+ unsigned i = 0;
+ SmallVector<DWARFFormValue, 3> AtomForms;
+ for (const auto &Atom: HdrData.Atoms) {
+ OS << format("Atom[%d] Type: ", i++);
+ if (const char *TypeString = dwarf::AtomTypeString(Atom.first))
+ OS << TypeString;
+ else
+ OS << format("DW_ATOM_Unknown_0x%x", Atom.first);
+ OS << " Form: ";
+ if (const char *FormString = dwarf::FormEncodingString(Atom.second))
+ OS << FormString;
+ else
+ OS << format("DW_FORM_Unknown_0x%x", Atom.second);
+ OS << '\n';
+ AtomForms.push_back(DWARFFormValue(Atom.second));
+ }
+
+ // Now go through the actual tables and dump them.
+ uint32_t Offset = sizeof(Hdr) + Hdr.HeaderDataLength;
+ unsigned HashesBase = Offset + Hdr.NumBuckets * 4;
+ unsigned OffsetsBase = HashesBase + Hdr.NumHashes * 4;
+
+ for (unsigned Bucket = 0; Bucket < Hdr.NumBuckets; ++Bucket) {
+ unsigned Index = AccelSection.getU32(&Offset);
+
+ OS << format("Bucket[%d]\n", Bucket);
+ if (Index == UINT32_MAX) {
+ OS << " EMPTY\n";
+ continue;
+ }
+
+ for (unsigned HashIdx = Index; HashIdx < Hdr.NumHashes; ++HashIdx) {
+ unsigned HashOffset = HashesBase + HashIdx*4;
+ unsigned OffsetsOffset = OffsetsBase + HashIdx*4;
+ uint32_t Hash = AccelSection.getU32(&HashOffset);
+
+ if (Hash % Hdr.NumBuckets != Bucket)
+ break;
+
+ unsigned DataOffset = AccelSection.getU32(&OffsetsOffset);
+ OS << format(" Hash = 0x%08x Offset = 0x%08x\n", Hash, DataOffset);
+ if (!AccelSection.isValidOffset(DataOffset)) {
+ OS << " Invalid section offset\n";
+ continue;
+ }
+ while (AccelSection.isValidOffsetForDataOfSize(DataOffset, 4)) {
+ unsigned StringOffset = AccelSection.getU32(&DataOffset);
+ RelocAddrMap::const_iterator Reloc = Relocs.find(DataOffset-4);
+ if (Reloc != Relocs.end())
+ StringOffset += Reloc->second.second;
+ if (!StringOffset)
+ break;
+ OS << format(" Name: %08x \"%s\"\n", StringOffset,
+ StringSection.getCStr(&StringOffset));
+ unsigned NumData = AccelSection.getU32(&DataOffset);
+ for (unsigned Data = 0; Data < NumData; ++Data) {
+ OS << format(" Data[%d] => ", Data);
+ unsigned i = 0;
+ for (auto &Atom : AtomForms) {
+ OS << format("{Atom[%d]: ", i++);
+ if (Atom.extractValue(AccelSection, &DataOffset, nullptr))
+ Atom.dump(OS, nullptr);
+ else
+ OS << "Error extracting the value";
+ OS << "} ";
+ }
+ OS << '\n';
+ }
+ }
+ }
+ }
+}
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
new file mode 100644
index 0000000..39a7c77
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp
@@ -0,0 +1,33 @@
+//===-- DWARFCompileUnit.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void DWARFCompileUnit::dump(raw_ostream &OS) {
+ OS << format("0x%08x", getOffset()) << ": Compile Unit:"
+ << " length = " << format("0x%08x", getLength())
+ << " version = " << format("0x%04x", getVersion())
+ << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset())
+ << " addr_size = " << format("0x%02x", getAddressByteSize())
+ << " (next unit at " << format("0x%08x", getNextUnitOffset())
+ << ")\n";
+
+ if (const DWARFDebugInfoEntryMinimal *CU = getUnitDIE(false))
+ CU->dump(OS, this, -1U);
+ else
+ OS << "<compile unit can't be parsed!>\n\n";
+}
+
+// VTable anchor.
+DWARFCompileUnit::~DWARFCompileUnit() {
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
new file mode 100644
index 0000000..a4195b7
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFContext.cpp
@@ -0,0 +1,814 @@
+//===-- DWARFContext.cpp --------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+#include "llvm/Support/Compression.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+using namespace llvm;
+using namespace dwarf;
+using namespace object;
+
+#define DEBUG_TYPE "dwarf"
+
+typedef DWARFDebugLine::LineTable DWARFLineTable;
+typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind;
+typedef DILineInfoSpecifier::FunctionNameKind FunctionNameKind;
+
+static void dumpPubSection(raw_ostream &OS, StringRef Name, StringRef Data,
+ bool LittleEndian, bool GnuStyle) {
+ OS << "\n." << Name << " contents:\n";
+ DataExtractor pubNames(Data, LittleEndian, 0);
+ uint32_t offset = 0;
+ while (pubNames.isValidOffset(offset)) {
+ OS << "length = " << format("0x%08x", pubNames.getU32(&offset));
+ OS << " version = " << format("0x%04x", pubNames.getU16(&offset));
+ OS << " unit_offset = " << format("0x%08x", pubNames.getU32(&offset));
+ OS << " unit_size = " << format("0x%08x", pubNames.getU32(&offset)) << '\n';
+ if (GnuStyle)
+ OS << "Offset Linkage Kind Name\n";
+ else
+ OS << "Offset Name\n";
+
+ while (offset < Data.size()) {
+ uint32_t dieRef = pubNames.getU32(&offset);
+ if (dieRef == 0)
+ break;
+ OS << format("0x%8.8x ", dieRef);
+ if (GnuStyle) {
+ PubIndexEntryDescriptor desc(pubNames.getU8(&offset));
+ OS << format("%-8s", dwarf::GDBIndexEntryLinkageString(desc.Linkage))
+ << ' ' << format("%-8s", dwarf::GDBIndexEntryKindString(desc.Kind))
+ << ' ';
+ }
+ OS << '\"' << pubNames.getCStr(&offset) << "\"\n";
+ }
+ }
+}
+
+static void dumpAccelSection(raw_ostream &OS, StringRef Name,
+ const DWARFSection& Section, StringRef StringSection,
+ bool LittleEndian) {
+ DataExtractor AccelSection(Section.Data, LittleEndian, 0);
+ DataExtractor StrData(StringSection, LittleEndian, 0);
+ OS << "\n." << Name << " contents:\n";
+ DWARFAcceleratorTable Accel(AccelSection, StrData, Section.Relocs);
+ if (!Accel.extract())
+ return;
+ Accel.dump(OS);
+}
+
+void DWARFContext::dump(raw_ostream &OS, DIDumpType DumpType) {
+ if (DumpType == DIDT_All || DumpType == DIDT_Abbrev) {
+ OS << ".debug_abbrev contents:\n";
+ getDebugAbbrev()->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_AbbrevDwo)
+ if (const DWARFDebugAbbrev *D = getDebugAbbrevDWO()) {
+ OS << "\n.debug_abbrev.dwo contents:\n";
+ D->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Info) {
+ OS << "\n.debug_info contents:\n";
+ for (const auto &CU : compile_units())
+ CU->dump(OS);
+ }
+
+ if ((DumpType == DIDT_All || DumpType == DIDT_InfoDwo) &&
+ getNumDWOCompileUnits()) {
+ OS << "\n.debug_info.dwo contents:\n";
+ for (const auto &DWOCU : dwo_compile_units())
+ DWOCU->dump(OS);
+ }
+
+ if ((DumpType == DIDT_All || DumpType == DIDT_Types) && getNumTypeUnits()) {
+ OS << "\n.debug_types contents:\n";
+ for (const auto &TUS : type_unit_sections())
+ for (const auto &TU : TUS)
+ TU->dump(OS);
+ }
+
+ if ((DumpType == DIDT_All || DumpType == DIDT_TypesDwo) &&
+ getNumDWOTypeUnits()) {
+ OS << "\n.debug_types.dwo contents:\n";
+ for (const auto &DWOTUS : dwo_type_unit_sections())
+ for (const auto &DWOTU : DWOTUS)
+ DWOTU->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Loc) {
+ OS << "\n.debug_loc contents:\n";
+ getDebugLoc()->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_LocDwo) {
+ OS << "\n.debug_loc.dwo contents:\n";
+ getDebugLocDWO()->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Frames) {
+ OS << "\n.debug_frame contents:\n";
+ getDebugFrame()->dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Macro) {
+ OS << "\n.debug_macinfo contents:\n";
+ getDebugMacro()->dump(OS);
+ }
+
+ uint32_t offset = 0;
+ if (DumpType == DIDT_All || DumpType == DIDT_Aranges) {
+ OS << "\n.debug_aranges contents:\n";
+ DataExtractor arangesData(getARangeSection(), isLittleEndian(), 0);
+ DWARFDebugArangeSet set;
+ while (set.extract(arangesData, &offset))
+ set.dump(OS);
+ }
+
+ uint8_t savedAddressByteSize = 0;
+ if (DumpType == DIDT_All || DumpType == DIDT_Line) {
+ OS << "\n.debug_line contents:\n";
+ for (const auto &CU : compile_units()) {
+ savedAddressByteSize = CU->getAddressByteSize();
+ const auto *CUDIE = CU->getUnitDIE();
+ if (CUDIE == nullptr)
+ continue;
+ unsigned stmtOffset = CUDIE->getAttributeValueAsSectionOffset(
+ CU.get(), DW_AT_stmt_list, -1U);
+ if (stmtOffset != -1U) {
+ DataExtractor lineData(getLineSection().Data, isLittleEndian(),
+ savedAddressByteSize);
+ DWARFDebugLine::LineTable LineTable;
+ LineTable.parse(lineData, &getLineSection().Relocs, &stmtOffset);
+ LineTable.dump(OS);
+ }
+ }
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_CUIndex) {
+ OS << "\n.debug_cu_index contents:\n";
+ getCUIndex().dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_TUIndex) {
+ OS << "\n.debug_tu_index contents:\n";
+ getTUIndex().dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_LineDwo) {
+ OS << "\n.debug_line.dwo contents:\n";
+ unsigned stmtOffset = 0;
+ DataExtractor lineData(getLineDWOSection().Data, isLittleEndian(),
+ savedAddressByteSize);
+ DWARFDebugLine::LineTable LineTable;
+ while (LineTable.Prologue.parse(lineData, &stmtOffset)) {
+ LineTable.dump(OS);
+ LineTable.clear();
+ }
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Str) {
+ OS << "\n.debug_str contents:\n";
+ DataExtractor strData(getStringSection(), isLittleEndian(), 0);
+ offset = 0;
+ uint32_t strOffset = 0;
+ while (const char *s = strData.getCStr(&offset)) {
+ OS << format("0x%8.8x: \"%s\"\n", strOffset, s);
+ strOffset = offset;
+ }
+ }
+
+ if ((DumpType == DIDT_All || DumpType == DIDT_StrDwo) &&
+ !getStringDWOSection().empty()) {
+ OS << "\n.debug_str.dwo contents:\n";
+ DataExtractor strDWOData(getStringDWOSection(), isLittleEndian(), 0);
+ offset = 0;
+ uint32_t strDWOOffset = 0;
+ while (const char *s = strDWOData.getCStr(&offset)) {
+ OS << format("0x%8.8x: \"%s\"\n", strDWOOffset, s);
+ strDWOOffset = offset;
+ }
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Ranges) {
+ OS << "\n.debug_ranges contents:\n";
+ // In fact, different compile units may have different address byte
+ // sizes, but for simplicity we just use the address byte size of the last
+ // compile unit (there is no easy and fast way to associate address range
+ // list and the compile unit it describes).
+ DataExtractor rangesData(getRangeSection(), isLittleEndian(),
+ savedAddressByteSize);
+ offset = 0;
+ DWARFDebugRangeList rangeList;
+ while (rangeList.extract(rangesData, &offset))
+ rangeList.dump(OS);
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Pubnames)
+ dumpPubSection(OS, "debug_pubnames", getPubNamesSection(),
+ isLittleEndian(), false);
+
+ if (DumpType == DIDT_All || DumpType == DIDT_Pubtypes)
+ dumpPubSection(OS, "debug_pubtypes", getPubTypesSection(),
+ isLittleEndian(), false);
+
+ if (DumpType == DIDT_All || DumpType == DIDT_GnuPubnames)
+ dumpPubSection(OS, "debug_gnu_pubnames", getGnuPubNamesSection(),
+ isLittleEndian(), true /* GnuStyle */);
+
+ if (DumpType == DIDT_All || DumpType == DIDT_GnuPubtypes)
+ dumpPubSection(OS, "debug_gnu_pubtypes", getGnuPubTypesSection(),
+ isLittleEndian(), true /* GnuStyle */);
+
+ if ((DumpType == DIDT_All || DumpType == DIDT_StrOffsetsDwo) &&
+ !getStringOffsetDWOSection().empty()) {
+ OS << "\n.debug_str_offsets.dwo contents:\n";
+ DataExtractor strOffsetExt(getStringOffsetDWOSection(), isLittleEndian(),
+ 0);
+ offset = 0;
+ uint64_t size = getStringOffsetDWOSection().size();
+ while (offset < size) {
+ OS << format("0x%8.8x: ", offset);
+ OS << format("%8.8x\n", strOffsetExt.getU32(&offset));
+ }
+ }
+
+ if (DumpType == DIDT_All || DumpType == DIDT_AppleNames)
+ dumpAccelSection(OS, "apple_names", getAppleNamesSection(),
+ getStringSection(), isLittleEndian());
+
+ if (DumpType == DIDT_All || DumpType == DIDT_AppleTypes)
+ dumpAccelSection(OS, "apple_types", getAppleTypesSection(),
+ getStringSection(), isLittleEndian());
+
+ if (DumpType == DIDT_All || DumpType == DIDT_AppleNamespaces)
+ dumpAccelSection(OS, "apple_namespaces", getAppleNamespacesSection(),
+ getStringSection(), isLittleEndian());
+
+ if (DumpType == DIDT_All || DumpType == DIDT_AppleObjC)
+ dumpAccelSection(OS, "apple_objc", getAppleObjCSection(),
+ getStringSection(), isLittleEndian());
+}
+
+const DWARFUnitIndex &DWARFContext::getCUIndex() {
+ if (CUIndex)
+ return *CUIndex;
+
+ DataExtractor CUIndexData(getCUIndexSection(), isLittleEndian(), 0);
+
+ CUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_INFO);
+ CUIndex->parse(CUIndexData);
+ return *CUIndex;
+}
+
+const DWARFUnitIndex &DWARFContext::getTUIndex() {
+ if (TUIndex)
+ return *TUIndex;
+
+ DataExtractor TUIndexData(getTUIndexSection(), isLittleEndian(), 0);
+
+ TUIndex = llvm::make_unique<DWARFUnitIndex>(DW_SECT_TYPES);
+ TUIndex->parse(TUIndexData);
+ return *TUIndex;
+}
+
+const DWARFDebugAbbrev *DWARFContext::getDebugAbbrev() {
+ if (Abbrev)
+ return Abbrev.get();
+
+ DataExtractor abbrData(getAbbrevSection(), isLittleEndian(), 0);
+
+ Abbrev.reset(new DWARFDebugAbbrev());
+ Abbrev->extract(abbrData);
+ return Abbrev.get();
+}
+
+const DWARFDebugAbbrev *DWARFContext::getDebugAbbrevDWO() {
+ if (AbbrevDWO)
+ return AbbrevDWO.get();
+
+ DataExtractor abbrData(getAbbrevDWOSection(), isLittleEndian(), 0);
+ AbbrevDWO.reset(new DWARFDebugAbbrev());
+ AbbrevDWO->extract(abbrData);
+ return AbbrevDWO.get();
+}
+
+const DWARFDebugLoc *DWARFContext::getDebugLoc() {
+ if (Loc)
+ return Loc.get();
+
+ DataExtractor LocData(getLocSection().Data, isLittleEndian(), 0);
+ Loc.reset(new DWARFDebugLoc(getLocSection().Relocs));
+ // assume all compile units have the same address byte size
+ if (getNumCompileUnits())
+ Loc->parse(LocData, getCompileUnitAtIndex(0)->getAddressByteSize());
+ return Loc.get();
+}
+
+const DWARFDebugLocDWO *DWARFContext::getDebugLocDWO() {
+ if (LocDWO)
+ return LocDWO.get();
+
+ DataExtractor LocData(getLocDWOSection().Data, isLittleEndian(), 0);
+ LocDWO.reset(new DWARFDebugLocDWO());
+ LocDWO->parse(LocData);
+ return LocDWO.get();
+}
+
+const DWARFDebugAranges *DWARFContext::getDebugAranges() {
+ if (Aranges)
+ return Aranges.get();
+
+ Aranges.reset(new DWARFDebugAranges());
+ Aranges->generate(this);
+ return Aranges.get();
+}
+
+const DWARFDebugFrame *DWARFContext::getDebugFrame() {
+ if (DebugFrame)
+ return DebugFrame.get();
+
+ // There's a "bug" in the DWARFv3 standard with respect to the target address
+ // size within debug frame sections. While DWARF is supposed to be independent
+ // of its container, FDEs have fields with size being "target address size",
+ // which isn't specified in DWARF in general. It's only specified for CUs, but
+ // .eh_frame can appear without a .debug_info section. Follow the example of
+ // other tools (libdwarf) and extract this from the container (ObjectFile
+ // provides this information). This problem is fixed in DWARFv4
+ // See this dwarf-discuss discussion for more details:
+ // http://lists.dwarfstd.org/htdig.cgi/dwarf-discuss-dwarfstd.org/2011-December/001173.html
+ DataExtractor debugFrameData(getDebugFrameSection(), isLittleEndian(),
+ getAddressSize());
+ DebugFrame.reset(new DWARFDebugFrame());
+ DebugFrame->parse(debugFrameData);
+ return DebugFrame.get();
+}
+
+const DWARFDebugMacro *DWARFContext::getDebugMacro() {
+ if (Macro)
+ return Macro.get();
+
+ DataExtractor MacinfoData(getMacinfoSection(), isLittleEndian(), 0);
+ Macro.reset(new DWARFDebugMacro());
+ Macro->parse(MacinfoData);
+ return Macro.get();
+}
+
+const DWARFLineTable *
+DWARFContext::getLineTableForUnit(DWARFUnit *U) {
+ if (!Line)
+ Line.reset(new DWARFDebugLine(&getLineSection().Relocs));
+
+ const auto *UnitDIE = U->getUnitDIE();
+ if (UnitDIE == nullptr)
+ return nullptr;
+
+ unsigned stmtOffset =
+ UnitDIE->getAttributeValueAsSectionOffset(U, DW_AT_stmt_list, -1U);
+ if (stmtOffset == -1U)
+ return nullptr; // No line table for this compile unit.
+
+ stmtOffset += U->getLineTableOffset();
+ // See if the line table is cached.
+ if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset))
+ return lt;
+
+ // We have to parse it first.
+ DataExtractor lineData(U->getLineSection(), isLittleEndian(),
+ U->getAddressByteSize());
+ return Line->getOrParseLineTable(lineData, stmtOffset);
+}
+
+void DWARFContext::parseCompileUnits() {
+ CUs.parse(*this, getInfoSection());
+}
+
+void DWARFContext::parseTypeUnits() {
+ if (!TUs.empty())
+ return;
+ for (const auto &I : getTypesSections()) {
+ TUs.emplace_back();
+ TUs.back().parse(*this, I.second);
+ }
+}
+
+void DWARFContext::parseDWOCompileUnits() {
+ DWOCUs.parseDWO(*this, getInfoDWOSection());
+}
+
+void DWARFContext::parseDWOTypeUnits() {
+ if (!DWOTUs.empty())
+ return;
+ for (const auto &I : getTypesDWOSections()) {
+ DWOTUs.emplace_back();
+ DWOTUs.back().parseDWO(*this, I.second);
+ }
+}
+
+DWARFCompileUnit *DWARFContext::getCompileUnitForOffset(uint32_t Offset) {
+ parseCompileUnits();
+ return CUs.getUnitForOffset(Offset);
+}
+
+DWARFCompileUnit *DWARFContext::getCompileUnitForAddress(uint64_t Address) {
+ // First, get the offset of the compile unit.
+ uint32_t CUOffset = getDebugAranges()->findAddress(Address);
+ // Retrieve the compile unit.
+ return getCompileUnitForOffset(CUOffset);
+}
+
+static bool getFunctionNameForAddress(DWARFCompileUnit *CU, uint64_t Address,
+ FunctionNameKind Kind,
+ std::string &FunctionName) {
+ if (Kind == FunctionNameKind::None)
+ return false;
+ // The address may correspond to instruction in some inlined function,
+ // so we have to build the chain of inlined functions and take the
+ // name of the topmost function in it.
+ const DWARFDebugInfoEntryInlinedChain &InlinedChain =
+ CU->getInlinedChainForAddress(Address);
+ if (InlinedChain.DIEs.size() == 0)
+ return false;
+ const DWARFDebugInfoEntryMinimal &TopFunctionDIE = InlinedChain.DIEs[0];
+ if (const char *Name =
+ TopFunctionDIE.getSubroutineName(InlinedChain.U, Kind)) {
+ FunctionName = Name;
+ return true;
+ }
+ return false;
+}
+
+DILineInfo DWARFContext::getLineInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Spec) {
+ DILineInfo Result;
+
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ if (!CU)
+ return Result;
+ getFunctionNameForAddress(CU, Address, Spec.FNKind, Result.FunctionName);
+ if (Spec.FLIKind != FileLineInfoKind::None) {
+ if (const DWARFLineTable *LineTable = getLineTableForUnit(CU))
+ LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
+ Spec.FLIKind, Result);
+ }
+ return Result;
+}
+
+DILineInfoTable
+DWARFContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
+ DILineInfoSpecifier Spec) {
+ DILineInfoTable Lines;
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ if (!CU)
+ return Lines;
+
+ std::string FunctionName = "<invalid>";
+ getFunctionNameForAddress(CU, Address, Spec.FNKind, FunctionName);
+
+ // If the Specifier says we don't need FileLineInfo, just
+ // return the top-most function at the starting address.
+ if (Spec.FLIKind == FileLineInfoKind::None) {
+ DILineInfo Result;
+ Result.FunctionName = FunctionName;
+ Lines.push_back(std::make_pair(Address, Result));
+ return Lines;
+ }
+
+ const DWARFLineTable *LineTable = getLineTableForUnit(CU);
+
+ // Get the index of row we're looking for in the line table.
+ std::vector<uint32_t> RowVector;
+ if (!LineTable->lookupAddressRange(Address, Size, RowVector))
+ return Lines;
+
+ for (uint32_t RowIndex : RowVector) {
+ // Take file number and line/column from the row.
+ const DWARFDebugLine::Row &Row = LineTable->Rows[RowIndex];
+ DILineInfo Result;
+ LineTable->getFileNameByIndex(Row.File, CU->getCompilationDir(),
+ Spec.FLIKind, Result.FileName);
+ Result.FunctionName = FunctionName;
+ Result.Line = Row.Line;
+ Result.Column = Row.Column;
+ Lines.push_back(std::make_pair(Row.Address, Result));
+ }
+
+ return Lines;
+}
+
+DIInliningInfo
+DWARFContext::getInliningInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Spec) {
+ DIInliningInfo InliningInfo;
+
+ DWARFCompileUnit *CU = getCompileUnitForAddress(Address);
+ if (!CU)
+ return InliningInfo;
+
+ const DWARFLineTable *LineTable = nullptr;
+ const DWARFDebugInfoEntryInlinedChain &InlinedChain =
+ CU->getInlinedChainForAddress(Address);
+ if (InlinedChain.DIEs.size() == 0) {
+ // If there is no DIE for address (e.g. it is in unavailable .dwo file),
+ // try to at least get file/line info from symbol table.
+ if (Spec.FLIKind != FileLineInfoKind::None) {
+ DILineInfo Frame;
+ LineTable = getLineTableForUnit(CU);
+ if (LineTable &&
+ LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
+ Spec.FLIKind, Frame))
+ InliningInfo.addFrame(Frame);
+ }
+ return InliningInfo;
+ }
+
+ uint32_t CallFile = 0, CallLine = 0, CallColumn = 0;
+ for (uint32_t i = 0, n = InlinedChain.DIEs.size(); i != n; i++) {
+ const DWARFDebugInfoEntryMinimal &FunctionDIE = InlinedChain.DIEs[i];
+ DILineInfo Frame;
+ // Get function name if necessary.
+ if (const char *Name =
+ FunctionDIE.getSubroutineName(InlinedChain.U, Spec.FNKind))
+ Frame.FunctionName = Name;
+ if (Spec.FLIKind != FileLineInfoKind::None) {
+ if (i == 0) {
+ // For the topmost frame, initialize the line table of this
+ // compile unit and fetch file/line info from it.
+ LineTable = getLineTableForUnit(CU);
+ // For the topmost routine, get file/line info from line table.
+ if (LineTable)
+ LineTable->getFileLineInfoForAddress(Address, CU->getCompilationDir(),
+ Spec.FLIKind, Frame);
+ } else {
+ // Otherwise, use call file, call line and call column from
+ // previous DIE in inlined chain.
+ if (LineTable)
+ LineTable->getFileNameByIndex(CallFile, CU->getCompilationDir(),
+ Spec.FLIKind, Frame.FileName);
+ Frame.Line = CallLine;
+ Frame.Column = CallColumn;
+ }
+ // Get call file/line/column of a current DIE.
+ if (i + 1 < n) {
+ FunctionDIE.getCallerFrame(InlinedChain.U, CallFile, CallLine,
+ CallColumn);
+ }
+ }
+ InliningInfo.addFrame(Frame);
+ }
+ return InliningInfo;
+}
+
+static bool consumeCompressedDebugSectionHeader(StringRef &data,
+ uint64_t &OriginalSize) {
+ // Consume "ZLIB" prefix.
+ if (!data.startswith("ZLIB"))
+ return false;
+ data = data.substr(4);
+ // Consume uncompressed section size (big-endian 8 bytes).
+ DataExtractor extractor(data, false, 8);
+ uint32_t Offset = 0;
+ OriginalSize = extractor.getU64(&Offset);
+ if (Offset == 0)
+ return false;
+ data = data.substr(Offset);
+ return true;
+}
+
+DWARFContextInMemory::DWARFContextInMemory(const object::ObjectFile &Obj,
+ const LoadedObjectInfo *L)
+ : IsLittleEndian(Obj.isLittleEndian()),
+ AddressSize(Obj.getBytesInAddress()) {
+ for (const SectionRef &Section : Obj.sections()) {
+ StringRef name;
+ Section.getName(name);
+ // Skip BSS and Virtual sections, they aren't interesting.
+ bool IsBSS = Section.isBSS();
+ if (IsBSS)
+ continue;
+ bool IsVirtual = Section.isVirtual();
+ if (IsVirtual)
+ continue;
+ StringRef data;
+
+ section_iterator RelocatedSection = Section.getRelocatedSection();
+ // Try to obtain an already relocated version of this section.
+ // Else use the unrelocated section from the object file. We'll have to
+ // apply relocations ourselves later.
+ if (!L || !L->getLoadedSectionContents(*RelocatedSection,data))
+ Section.getContents(data);
+
+ name = name.substr(name.find_first_not_of("._")); // Skip . and _ prefixes.
+
+ // Check if debug info section is compressed with zlib.
+ if (name.startswith("zdebug_")) {
+ uint64_t OriginalSize;
+ if (!zlib::isAvailable() ||
+ !consumeCompressedDebugSectionHeader(data, OriginalSize))
+ continue;
+ UncompressedSections.resize(UncompressedSections.size() + 1);
+ if (zlib::uncompress(data, UncompressedSections.back(), OriginalSize) !=
+ zlib::StatusOK) {
+ UncompressedSections.pop_back();
+ continue;
+ }
+ // Make data point to uncompressed section contents and save its contents.
+ name = name.substr(1);
+ data = UncompressedSections.back();
+ }
+
+ StringRef *SectionData =
+ StringSwitch<StringRef *>(name)
+ .Case("debug_info", &InfoSection.Data)
+ .Case("debug_abbrev", &AbbrevSection)
+ .Case("debug_loc", &LocSection.Data)
+ .Case("debug_line", &LineSection.Data)
+ .Case("debug_aranges", &ARangeSection)
+ .Case("debug_frame", &DebugFrameSection)
+ .Case("debug_str", &StringSection)
+ .Case("debug_ranges", &RangeSection)
+ .Case("debug_macinfo", &MacinfoSection)
+ .Case("debug_pubnames", &PubNamesSection)
+ .Case("debug_pubtypes", &PubTypesSection)
+ .Case("debug_gnu_pubnames", &GnuPubNamesSection)
+ .Case("debug_gnu_pubtypes", &GnuPubTypesSection)
+ .Case("debug_info.dwo", &InfoDWOSection.Data)
+ .Case("debug_abbrev.dwo", &AbbrevDWOSection)
+ .Case("debug_loc.dwo", &LocDWOSection.Data)
+ .Case("debug_line.dwo", &LineDWOSection.Data)
+ .Case("debug_str.dwo", &StringDWOSection)
+ .Case("debug_str_offsets.dwo", &StringOffsetDWOSection)
+ .Case("debug_addr", &AddrSection)
+ .Case("apple_names", &AppleNamesSection.Data)
+ .Case("apple_types", &AppleTypesSection.Data)
+ .Case("apple_namespaces", &AppleNamespacesSection.Data)
+ .Case("apple_namespac", &AppleNamespacesSection.Data)
+ .Case("apple_objc", &AppleObjCSection.Data)
+ .Case("debug_cu_index", &CUIndexSection)
+ .Case("debug_tu_index", &TUIndexSection)
+ // Any more debug info sections go here.
+ .Default(nullptr);
+ if (SectionData) {
+ *SectionData = data;
+ if (name == "debug_ranges") {
+ // FIXME: Use the other dwo range section when we emit it.
+ RangeDWOSection = data;
+ }
+ } else if (name == "debug_types") {
+ // Find debug_types data by section rather than name as there are
+ // multiple, comdat grouped, debug_types sections.
+ TypesSections[Section].Data = data;
+ } else if (name == "debug_types.dwo") {
+ TypesDWOSections[Section].Data = data;
+ }
+
+ if (RelocatedSection == Obj.section_end())
+ continue;
+
+ StringRef RelSecName;
+ StringRef RelSecData;
+ RelocatedSection->getName(RelSecName);
+
+ // If the section we're relocating was relocated already by the JIT,
+ // then we used the relocated version above, so we do not need to process
+ // relocations for it now.
+ if (L && L->getLoadedSectionContents(*RelocatedSection,RelSecData))
+ continue;
+
+ // In Mach-o files, the relocations do not need to be applied if
+ // there is no load offset to apply. The value read at the
+ // relocation point already factors in the section address
+ // (actually applying the relocations will produce wrong results
+ // as the section address will be added twice).
+ if (!L && isa<MachOObjectFile>(&Obj))
+ continue;
+
+ RelSecName = RelSecName.substr(
+ RelSecName.find_first_not_of("._")); // Skip . and _ prefixes.
+
+ // TODO: Add support for relocations in other sections as needed.
+ // Record relocations for the debug_info and debug_line sections.
+ RelocAddrMap *Map = StringSwitch<RelocAddrMap*>(RelSecName)
+ .Case("debug_info", &InfoSection.Relocs)
+ .Case("debug_loc", &LocSection.Relocs)
+ .Case("debug_info.dwo", &InfoDWOSection.Relocs)
+ .Case("debug_line", &LineSection.Relocs)
+ .Case("apple_names", &AppleNamesSection.Relocs)
+ .Case("apple_types", &AppleTypesSection.Relocs)
+ .Case("apple_namespaces", &AppleNamespacesSection.Relocs)
+ .Case("apple_namespac", &AppleNamespacesSection.Relocs)
+ .Case("apple_objc", &AppleObjCSection.Relocs)
+ .Default(nullptr);
+ if (!Map) {
+ // Find debug_types relocs by section rather than name as there are
+ // multiple, comdat grouped, debug_types sections.
+ if (RelSecName == "debug_types")
+ Map = &TypesSections[*RelocatedSection].Relocs;
+ else if (RelSecName == "debug_types.dwo")
+ Map = &TypesDWOSections[*RelocatedSection].Relocs;
+ else
+ continue;
+ }
+
+ if (Section.relocation_begin() != Section.relocation_end()) {
+ uint64_t SectionSize = RelocatedSection->getSize();
+ for (const RelocationRef &Reloc : Section.relocations()) {
+ uint64_t Address = Reloc.getOffset();
+ uint64_t Type = Reloc.getType();
+ uint64_t SymAddr = 0;
+ uint64_t SectionLoadAddress = 0;
+ object::symbol_iterator Sym = Reloc.getSymbol();
+ object::section_iterator RSec = Obj.section_end();
+
+ // First calculate the address of the symbol or section as it appears
+ // in the objct file
+ if (Sym != Obj.symbol_end()) {
+ ErrorOr<uint64_t> SymAddrOrErr = Sym->getAddress();
+ if (std::error_code EC = SymAddrOrErr.getError()) {
+ errs() << "error: failed to compute symbol address: "
+ << EC.message() << '\n';
+ continue;
+ }
+ SymAddr = *SymAddrOrErr;
+ // Also remember what section this symbol is in for later
+ RSec = *Sym->getSection();
+ } else if (auto *MObj = dyn_cast<MachOObjectFile>(&Obj)) {
+ // MachO also has relocations that point to sections and
+ // scattered relocations.
+ auto RelocInfo = MObj->getRelocation(Reloc.getRawDataRefImpl());
+ if (MObj->isRelocationScattered(RelocInfo)) {
+ // FIXME: it's not clear how to correctly handle scattered
+ // relocations.
+ continue;
+ } else {
+ RSec = MObj->getRelocationSection(Reloc.getRawDataRefImpl());
+ SymAddr = RSec->getAddress();
+ }
+ }
+
+ // If we are given load addresses for the sections, we need to adjust:
+ // SymAddr = (Address of Symbol Or Section in File) -
+ // (Address of Section in File) +
+ // (Load Address of Section)
+ if (L != nullptr && RSec != Obj.section_end()) {
+ // RSec is now either the section being targeted or the section
+ // containing the symbol being targeted. In either case,
+ // we need to perform the same computation.
+ StringRef SecName;
+ RSec->getName(SecName);
+// llvm::dbgs() << "Name: '" << SecName
+// << "', RSec: " << RSec->getRawDataRefImpl()
+// << ", Section: " << Section.getRawDataRefImpl() << "\n";
+ SectionLoadAddress = L->getSectionLoadAddress(*RSec);
+ if (SectionLoadAddress != 0)
+ SymAddr += SectionLoadAddress - RSec->getAddress();
+ }
+
+ object::RelocVisitor V(Obj);
+ object::RelocToApply R(V.visit(Type, Reloc, SymAddr));
+ if (V.error()) {
+ SmallString<32> Name;
+ Reloc.getTypeName(Name);
+ errs() << "error: failed to compute relocation: "
+ << Name << "\n";
+ continue;
+ }
+
+ if (Address + R.Width > SectionSize) {
+ errs() << "error: " << R.Width << "-byte relocation starting "
+ << Address << " bytes into section " << name << " which is "
+ << SectionSize << " bytes long.\n";
+ continue;
+ }
+ if (R.Width > 8) {
+ errs() << "error: can't handle a relocation of more than 8 bytes at "
+ "a time.\n";
+ continue;
+ }
+ DEBUG(dbgs() << "Writing " << format("%p", R.Value)
+ << " at " << format("%p", Address)
+ << " with width " << format("%d", R.Width)
+ << "\n");
+ Map->insert(std::make_pair(Address, std::make_pair(R.Width, R.Value)));
+ }
+ }
+ }
+}
+
+void DWARFContextInMemory::anchor() { }
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
new file mode 100644
index 0000000..e63e289
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp
@@ -0,0 +1,115 @@
+//===-- DWARFDebugAbbrev.cpp ----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+DWARFAbbreviationDeclarationSet::DWARFAbbreviationDeclarationSet() {
+ clear();
+}
+
+void DWARFAbbreviationDeclarationSet::clear() {
+ Offset = 0;
+ FirstAbbrCode = 0;
+ Decls.clear();
+}
+
+bool DWARFAbbreviationDeclarationSet::extract(DataExtractor Data,
+ uint32_t *OffsetPtr) {
+ clear();
+ const uint32_t BeginOffset = *OffsetPtr;
+ Offset = BeginOffset;
+ DWARFAbbreviationDeclaration AbbrDecl;
+ uint32_t PrevAbbrCode = 0;
+ while (AbbrDecl.extract(Data, OffsetPtr)) {
+ if (FirstAbbrCode == 0) {
+ FirstAbbrCode = AbbrDecl.getCode();
+ } else {
+ if (PrevAbbrCode + 1 != AbbrDecl.getCode()) {
+ // Codes are not consecutive, can't do O(1) lookups.
+ FirstAbbrCode = UINT32_MAX;
+ }
+ }
+ PrevAbbrCode = AbbrDecl.getCode();
+ Decls.push_back(std::move(AbbrDecl));
+ }
+ return BeginOffset != *OffsetPtr;
+}
+
+void DWARFAbbreviationDeclarationSet::dump(raw_ostream &OS) const {
+ for (const auto &Decl : Decls)
+ Decl.dump(OS);
+}
+
+const DWARFAbbreviationDeclaration *
+DWARFAbbreviationDeclarationSet::getAbbreviationDeclaration(
+ uint32_t AbbrCode) const {
+ if (FirstAbbrCode == UINT32_MAX) {
+ for (const auto &Decl : Decls) {
+ if (Decl.getCode() == AbbrCode)
+ return &Decl;
+ }
+ return nullptr;
+ }
+ if (AbbrCode < FirstAbbrCode || AbbrCode >= FirstAbbrCode + Decls.size())
+ return nullptr;
+ return &Decls[AbbrCode - FirstAbbrCode];
+}
+
+DWARFDebugAbbrev::DWARFDebugAbbrev() {
+ clear();
+}
+
+void DWARFDebugAbbrev::clear() {
+ AbbrDeclSets.clear();
+ PrevAbbrOffsetPos = AbbrDeclSets.end();
+}
+
+void DWARFDebugAbbrev::extract(DataExtractor Data) {
+ clear();
+
+ uint32_t Offset = 0;
+ DWARFAbbreviationDeclarationSet AbbrDecls;
+ while (Data.isValidOffset(Offset)) {
+ uint32_t CUAbbrOffset = Offset;
+ if (!AbbrDecls.extract(Data, &Offset))
+ break;
+ AbbrDeclSets[CUAbbrOffset] = std::move(AbbrDecls);
+ }
+}
+
+void DWARFDebugAbbrev::dump(raw_ostream &OS) const {
+ if (AbbrDeclSets.empty()) {
+ OS << "< EMPTY >\n";
+ return;
+ }
+
+ for (const auto &I : AbbrDeclSets) {
+ OS << format("Abbrev table for offset: 0x%8.8" PRIx64 "\n", I.first);
+ I.second.dump(OS);
+ }
+}
+
+const DWARFAbbreviationDeclarationSet*
+DWARFDebugAbbrev::getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const {
+ const auto End = AbbrDeclSets.end();
+ if (PrevAbbrOffsetPos != End && PrevAbbrOffsetPos->first == CUAbbrOffset) {
+ return &(PrevAbbrOffsetPos->second);
+ }
+
+ const auto Pos = AbbrDeclSets.find(CUAbbrOffset);
+ if (Pos != End) {
+ PrevAbbrOffsetPos = Pos;
+ return &(Pos->second);
+ }
+
+ return nullptr;
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
new file mode 100644
index 0000000..67589cd
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp
@@ -0,0 +1,104 @@
+//===-- DWARFDebugArangeSet.cpp -------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+using namespace llvm;
+
+void DWARFDebugArangeSet::clear() {
+ Offset = -1U;
+ std::memset(&HeaderData, 0, sizeof(Header));
+ ArangeDescriptors.clear();
+}
+
+bool
+DWARFDebugArangeSet::extract(DataExtractor data, uint32_t *offset_ptr) {
+ if (data.isValidOffset(*offset_ptr)) {
+ ArangeDescriptors.clear();
+ Offset = *offset_ptr;
+
+ // 7.20 Address Range Table
+ //
+ // Each set of entries in the table of address ranges contained in
+ // the .debug_aranges section begins with a header consisting of: a
+ // 4-byte length containing the length of the set of entries for this
+ // compilation unit, not including the length field itself; a 2-byte
+ // version identifier containing the value 2 for DWARF Version 2; a
+ // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer
+ // containing the size in bytes of an address (or the offset portion of
+ // an address for segmented addressing) on the target system; and a
+ // 1-byte unsigned integer containing the size in bytes of a segment
+ // descriptor on the target system. This header is followed by a series
+ // of tuples. Each tuple consists of an address and a length, each in
+ // the size appropriate for an address on the target architecture.
+ HeaderData.Length = data.getU32(offset_ptr);
+ HeaderData.Version = data.getU16(offset_ptr);
+ HeaderData.CuOffset = data.getU32(offset_ptr);
+ HeaderData.AddrSize = data.getU8(offset_ptr);
+ HeaderData.SegSize = data.getU8(offset_ptr);
+
+ // Perform basic validation of the header fields.
+ if (!data.isValidOffsetForDataOfSize(Offset, HeaderData.Length) ||
+ (HeaderData.AddrSize != 4 && HeaderData.AddrSize != 8)) {
+ clear();
+ return false;
+ }
+
+ // The first tuple following the header in each set begins at an offset
+ // that is a multiple of the size of a single tuple (that is, twice the
+ // size of an address). The header is padded, if necessary, to the
+ // appropriate boundary.
+ const uint32_t header_size = *offset_ptr - Offset;
+ const uint32_t tuple_size = HeaderData.AddrSize * 2;
+ uint32_t first_tuple_offset = 0;
+ while (first_tuple_offset < header_size)
+ first_tuple_offset += tuple_size;
+
+ *offset_ptr = Offset + first_tuple_offset;
+
+ Descriptor arangeDescriptor;
+
+ static_assert(sizeof(arangeDescriptor.Address) ==
+ sizeof(arangeDescriptor.Length),
+ "Different datatypes for addresses and sizes!");
+ assert(sizeof(arangeDescriptor.Address) >= HeaderData.AddrSize);
+
+ while (data.isValidOffset(*offset_ptr)) {
+ arangeDescriptor.Address = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
+ arangeDescriptor.Length = data.getUnsigned(offset_ptr, HeaderData.AddrSize);
+
+ // Each set of tuples is terminated by a 0 for the address and 0
+ // for the length.
+ if (arangeDescriptor.Address || arangeDescriptor.Length)
+ ArangeDescriptors.push_back(arangeDescriptor);
+ else
+ break; // We are done if we get a zero address and length
+ }
+
+ return !ArangeDescriptors.empty();
+ }
+ return false;
+}
+
+void DWARFDebugArangeSet::dump(raw_ostream &OS) const {
+ OS << format("Address Range Header: length = 0x%8.8x, version = 0x%4.4x, ",
+ HeaderData.Length, HeaderData.Version)
+ << format("cu_offset = 0x%8.8x, addr_size = 0x%2.2x, seg_size = 0x%2.2x\n",
+ HeaderData.CuOffset, HeaderData.AddrSize, HeaderData.SegSize);
+
+ const uint32_t hex_width = HeaderData.AddrSize * 2;
+ for (const auto &Desc : ArangeDescriptors) {
+ OS << format("[0x%*.*" PRIx64 " -", hex_width, hex_width, Desc.Address)
+ << format(" 0x%*.*" PRIx64 ")\n",
+ hex_width, hex_width, Desc.getEndAddress());
+ }
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
new file mode 100644
index 0000000..27a02c4
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp
@@ -0,0 +1,129 @@
+//===-- DWARFDebugAranges.cpp -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugAranges.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cassert>
+#include <set>
+using namespace llvm;
+
+void DWARFDebugAranges::extract(DataExtractor DebugArangesData) {
+ if (!DebugArangesData.isValidOffset(0))
+ return;
+ uint32_t Offset = 0;
+ DWARFDebugArangeSet Set;
+
+ while (Set.extract(DebugArangesData, &Offset)) {
+ uint32_t CUOffset = Set.getCompileUnitDIEOffset();
+ for (const auto &Desc : Set.descriptors()) {
+ uint64_t LowPC = Desc.Address;
+ uint64_t HighPC = Desc.getEndAddress();
+ appendRange(CUOffset, LowPC, HighPC);
+ }
+ ParsedCUOffsets.insert(CUOffset);
+ }
+}
+
+void DWARFDebugAranges::generate(DWARFContext *CTX) {
+ clear();
+ if (!CTX)
+ return;
+
+ // Extract aranges from .debug_aranges section.
+ DataExtractor ArangesData(CTX->getARangeSection(), CTX->isLittleEndian(), 0);
+ extract(ArangesData);
+
+ // Generate aranges from DIEs: even if .debug_aranges section is present,
+ // it may describe only a small subset of compilation units, so we need to
+ // manually build aranges for the rest of them.
+ for (const auto &CU : CTX->compile_units()) {
+ uint32_t CUOffset = CU->getOffset();
+ if (ParsedCUOffsets.insert(CUOffset).second) {
+ DWARFAddressRangesVector CURanges;
+ CU->collectAddressRanges(CURanges);
+ for (const auto &R : CURanges) {
+ appendRange(CUOffset, R.first, R.second);
+ }
+ }
+ }
+
+ construct();
+}
+
+void DWARFDebugAranges::clear() {
+ Endpoints.clear();
+ Aranges.clear();
+ ParsedCUOffsets.clear();
+}
+
+void DWARFDebugAranges::appendRange(uint32_t CUOffset, uint64_t LowPC,
+ uint64_t HighPC) {
+ if (LowPC >= HighPC)
+ return;
+ Endpoints.emplace_back(LowPC, CUOffset, true);
+ Endpoints.emplace_back(HighPC, CUOffset, false);
+}
+
+void DWARFDebugAranges::construct() {
+ std::multiset<uint32_t> ValidCUs; // Maintain the set of CUs describing
+ // a current address range.
+ std::sort(Endpoints.begin(), Endpoints.end());
+ uint64_t PrevAddress = -1ULL;
+ for (const auto &E : Endpoints) {
+ if (PrevAddress < E.Address && ValidCUs.size() > 0) {
+ // If the address range between two endpoints is described by some
+ // CU, first try to extend the last range in Aranges. If we can't
+ // do it, start a new range.
+ if (!Aranges.empty() && Aranges.back().HighPC() == PrevAddress &&
+ ValidCUs.find(Aranges.back().CUOffset) != ValidCUs.end()) {
+ Aranges.back().setHighPC(E.Address);
+ } else {
+ Aranges.emplace_back(PrevAddress, E.Address, *ValidCUs.begin());
+ }
+ }
+ // Update the set of valid CUs.
+ if (E.IsRangeStart) {
+ ValidCUs.insert(E.CUOffset);
+ } else {
+ auto CUPos = ValidCUs.find(E.CUOffset);
+ assert(CUPos != ValidCUs.end());
+ ValidCUs.erase(CUPos);
+ }
+ PrevAddress = E.Address;
+ }
+ assert(ValidCUs.empty());
+
+ // Endpoints are not needed now.
+ std::vector<RangeEndpoint> EmptyEndpoints;
+ EmptyEndpoints.swap(Endpoints);
+}
+
+uint32_t DWARFDebugAranges::findAddress(uint64_t Address) const {
+ if (!Aranges.empty()) {
+ Range range(Address);
+ RangeCollIterator begin = Aranges.begin();
+ RangeCollIterator end = Aranges.end();
+ RangeCollIterator pos =
+ std::lower_bound(begin, end, range);
+
+ if (pos != end && pos->containsAddress(Address)) {
+ return pos->CUOffset;
+ } else if (pos != begin) {
+ --pos;
+ if (pos->containsAddress(Address))
+ return pos->CUOffset;
+ }
+ }
+ return -1U;
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
new file mode 100644
index 0000000..1aa31be
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
@@ -0,0 +1,521 @@
+//===-- DWARFDebugFrame.h - Parsing of .debug_frame -------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+#include <vector>
+
+using namespace llvm;
+using namespace dwarf;
+
+
+/// \brief Abstract frame entry defining the common interface concrete
+/// entries implement.
+class llvm::FrameEntry {
+public:
+ enum FrameKind {FK_CIE, FK_FDE};
+ FrameEntry(FrameKind K, uint64_t Offset, uint64_t Length)
+ : Kind(K), Offset(Offset), Length(Length) {}
+
+ virtual ~FrameEntry() {
+ }
+
+ FrameKind getKind() const { return Kind; }
+ virtual uint64_t getOffset() const { return Offset; }
+
+ /// \brief Parse and store a sequence of CFI instructions from Data,
+ /// starting at *Offset and ending at EndOffset. If everything
+ /// goes well, *Offset should be equal to EndOffset when this method
+ /// returns. Otherwise, an error occurred.
+ virtual void parseInstructions(DataExtractor Data, uint32_t *Offset,
+ uint32_t EndOffset);
+
+ /// \brief Dump the entry header to the given output stream.
+ virtual void dumpHeader(raw_ostream &OS) const = 0;
+
+ /// \brief Dump the entry's instructions to the given output stream.
+ virtual void dumpInstructions(raw_ostream &OS) const;
+
+protected:
+ const FrameKind Kind;
+
+ /// \brief Offset of this entry in the section.
+ uint64_t Offset;
+
+ /// \brief Entry length as specified in DWARF.
+ uint64_t Length;
+
+ /// An entry may contain CFI instructions. An instruction consists of an
+ /// opcode and an optional sequence of operands.
+ typedef std::vector<uint64_t> Operands;
+ struct Instruction {
+ Instruction(uint8_t Opcode)
+ : Opcode(Opcode)
+ {}
+
+ uint8_t Opcode;
+ Operands Ops;
+ };
+
+ std::vector<Instruction> Instructions;
+
+ /// Convenience methods to add a new instruction with the given opcode and
+ /// operands to the Instructions vector.
+ void addInstruction(uint8_t Opcode) {
+ Instructions.push_back(Instruction(Opcode));
+ }
+
+ void addInstruction(uint8_t Opcode, uint64_t Operand1) {
+ Instructions.push_back(Instruction(Opcode));
+ Instructions.back().Ops.push_back(Operand1);
+ }
+
+ void addInstruction(uint8_t Opcode, uint64_t Operand1, uint64_t Operand2) {
+ Instructions.push_back(Instruction(Opcode));
+ Instructions.back().Ops.push_back(Operand1);
+ Instructions.back().Ops.push_back(Operand2);
+ }
+};
+
+
+// See DWARF standard v3, section 7.23
+const uint8_t DWARF_CFI_PRIMARY_OPCODE_MASK = 0xc0;
+const uint8_t DWARF_CFI_PRIMARY_OPERAND_MASK = 0x3f;
+
+void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
+ uint32_t EndOffset) {
+ while (*Offset < EndOffset) {
+ uint8_t Opcode = Data.getU8(Offset);
+ // Some instructions have a primary opcode encoded in the top bits.
+ uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;
+
+ if (Primary) {
+ // If it's a primary opcode, the first operand is encoded in the bottom
+ // bits of the opcode itself.
+ uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
+ switch (Primary) {
+ default: llvm_unreachable("Impossible primary CFI opcode");
+ case DW_CFA_advance_loc:
+ case DW_CFA_restore:
+ addInstruction(Primary, Op1);
+ break;
+ case DW_CFA_offset:
+ addInstruction(Primary, Op1, Data.getULEB128(Offset));
+ break;
+ }
+ } else {
+ // Extended opcode - its value is Opcode itself.
+ switch (Opcode) {
+ default: llvm_unreachable("Invalid extended CFI opcode");
+ case DW_CFA_nop:
+ case DW_CFA_remember_state:
+ case DW_CFA_restore_state:
+ case DW_CFA_GNU_window_save:
+ // No operands
+ addInstruction(Opcode);
+ break;
+ case DW_CFA_set_loc:
+ // Operands: Address
+ addInstruction(Opcode, Data.getAddress(Offset));
+ break;
+ case DW_CFA_advance_loc1:
+ // Operands: 1-byte delta
+ addInstruction(Opcode, Data.getU8(Offset));
+ break;
+ case DW_CFA_advance_loc2:
+ // Operands: 2-byte delta
+ addInstruction(Opcode, Data.getU16(Offset));
+ break;
+ case DW_CFA_advance_loc4:
+ // Operands: 4-byte delta
+ addInstruction(Opcode, Data.getU32(Offset));
+ break;
+ case DW_CFA_restore_extended:
+ case DW_CFA_undefined:
+ case DW_CFA_same_value:
+ case DW_CFA_def_cfa_register:
+ case DW_CFA_def_cfa_offset:
+ // Operands: ULEB128
+ addInstruction(Opcode, Data.getULEB128(Offset));
+ break;
+ case DW_CFA_def_cfa_offset_sf:
+ // Operands: SLEB128
+ addInstruction(Opcode, Data.getSLEB128(Offset));
+ break;
+ case DW_CFA_offset_extended:
+ case DW_CFA_register:
+ case DW_CFA_def_cfa:
+ case DW_CFA_val_offset:
+ // Operands: ULEB128, ULEB128
+ addInstruction(Opcode, Data.getULEB128(Offset),
+ Data.getULEB128(Offset));
+ break;
+ case DW_CFA_offset_extended_sf:
+ case DW_CFA_def_cfa_sf:
+ case DW_CFA_val_offset_sf:
+ // Operands: ULEB128, SLEB128
+ addInstruction(Opcode, Data.getULEB128(Offset),
+ Data.getSLEB128(Offset));
+ break;
+ case DW_CFA_def_cfa_expression:
+ case DW_CFA_expression:
+ case DW_CFA_val_expression:
+ // TODO: implement this
+ report_fatal_error("Values with expressions not implemented yet!");
+ }
+ }
+ }
+}
+
+namespace {
+/// \brief DWARF Common Information Entry (CIE)
+class CIE : public FrameEntry {
+public:
+ // CIEs (and FDEs) are simply container classes, so the only sensible way to
+ // create them is by providing the full parsed contents in the constructor.
+ CIE(uint64_t Offset, uint64_t Length, uint8_t Version,
+ SmallString<8> Augmentation, uint8_t AddressSize,
+ uint8_t SegmentDescriptorSize, uint64_t CodeAlignmentFactor,
+ int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister)
+ : FrameEntry(FK_CIE, Offset, Length), Version(Version),
+ Augmentation(std::move(Augmentation)),
+ AddressSize(AddressSize),
+ SegmentDescriptorSize(SegmentDescriptorSize),
+ CodeAlignmentFactor(CodeAlignmentFactor),
+ DataAlignmentFactor(DataAlignmentFactor),
+ ReturnAddressRegister(ReturnAddressRegister) {}
+
+ ~CIE() override {}
+
+ uint64_t getCodeAlignmentFactor() const { return CodeAlignmentFactor; }
+ int64_t getDataAlignmentFactor() const { return DataAlignmentFactor; }
+
+ void dumpHeader(raw_ostream &OS) const override {
+ OS << format("%08x %08x %08x CIE",
+ (uint32_t)Offset, (uint32_t)Length, DW_CIE_ID)
+ << "\n";
+ OS << format(" Version: %d\n", Version);
+ OS << " Augmentation: \"" << Augmentation << "\"\n";
+ if (Version >= 4) {
+ OS << format(" Address size: %u\n",
+ (uint32_t)AddressSize);
+ OS << format(" Segment desc size: %u\n",
+ (uint32_t)SegmentDescriptorSize);
+ }
+ OS << format(" Code alignment factor: %u\n",
+ (uint32_t)CodeAlignmentFactor);
+ OS << format(" Data alignment factor: %d\n",
+ (int32_t)DataAlignmentFactor);
+ OS << format(" Return address column: %d\n",
+ (int32_t)ReturnAddressRegister);
+ OS << "\n";
+ }
+
+ static bool classof(const FrameEntry *FE) {
+ return FE->getKind() == FK_CIE;
+ }
+
+private:
+ /// The following fields are defined in section 6.4.1 of the DWARF standard v4
+ uint8_t Version;
+ SmallString<8> Augmentation;
+ uint8_t AddressSize;
+ uint8_t SegmentDescriptorSize;
+ uint64_t CodeAlignmentFactor;
+ int64_t DataAlignmentFactor;
+ uint64_t ReturnAddressRegister;
+};
+
+
+/// \brief DWARF Frame Description Entry (FDE)
+class FDE : public FrameEntry {
+public:
+ // Each FDE has a CIE it's "linked to". Our FDE contains is constructed with
+ // an offset to the CIE (provided by parsing the FDE header). The CIE itself
+ // is obtained lazily once it's actually required.
+ FDE(uint64_t Offset, uint64_t Length, int64_t LinkedCIEOffset,
+ uint64_t InitialLocation, uint64_t AddressRange,
+ CIE *Cie)
+ : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset),
+ InitialLocation(InitialLocation), AddressRange(AddressRange),
+ LinkedCIE(Cie) {}
+
+ ~FDE() override {}
+
+ CIE *getLinkedCIE() const { return LinkedCIE; }
+
+ void dumpHeader(raw_ostream &OS) const override {
+ OS << format("%08x %08x %08x FDE ",
+ (uint32_t)Offset, (uint32_t)Length, (int32_t)LinkedCIEOffset);
+ OS << format("cie=%08x pc=%08x...%08x\n",
+ (int32_t)LinkedCIEOffset,
+ (uint32_t)InitialLocation,
+ (uint32_t)InitialLocation + (uint32_t)AddressRange);
+ }
+
+ static bool classof(const FrameEntry *FE) {
+ return FE->getKind() == FK_FDE;
+ }
+
+private:
+ /// The following fields are defined in section 6.4.1 of the DWARF standard v3
+ uint64_t LinkedCIEOffset;
+ uint64_t InitialLocation;
+ uint64_t AddressRange;
+ CIE *LinkedCIE;
+};
+
+/// \brief Types of operands to CF instructions.
+enum OperandType {
+ OT_Unset,
+ OT_None,
+ OT_Address,
+ OT_Offset,
+ OT_FactoredCodeOffset,
+ OT_SignedFactDataOffset,
+ OT_UnsignedFactDataOffset,
+ OT_Register,
+ OT_Expression
+};
+
+} // end anonymous namespace
+
+/// \brief Initialize the array describing the types of operands.
+static ArrayRef<OperandType[2]> getOperandTypes() {
+ static OperandType OpTypes[DW_CFA_restore+1][2];
+
+#define DECLARE_OP2(OP, OPTYPE0, OPTYPE1) \
+ do { \
+ OpTypes[OP][0] = OPTYPE0; \
+ OpTypes[OP][1] = OPTYPE1; \
+ } while (0)
+#define DECLARE_OP1(OP, OPTYPE0) DECLARE_OP2(OP, OPTYPE0, OT_None)
+#define DECLARE_OP0(OP) DECLARE_OP1(OP, OT_None)
+
+ DECLARE_OP1(DW_CFA_set_loc, OT_Address);
+ DECLARE_OP1(DW_CFA_advance_loc, OT_FactoredCodeOffset);
+ DECLARE_OP1(DW_CFA_advance_loc1, OT_FactoredCodeOffset);
+ DECLARE_OP1(DW_CFA_advance_loc2, OT_FactoredCodeOffset);
+ DECLARE_OP1(DW_CFA_advance_loc4, OT_FactoredCodeOffset);
+ DECLARE_OP1(DW_CFA_MIPS_advance_loc8, OT_FactoredCodeOffset);
+ DECLARE_OP2(DW_CFA_def_cfa, OT_Register, OT_Offset);
+ DECLARE_OP2(DW_CFA_def_cfa_sf, OT_Register, OT_SignedFactDataOffset);
+ DECLARE_OP1(DW_CFA_def_cfa_register, OT_Register);
+ DECLARE_OP1(DW_CFA_def_cfa_offset, OT_Offset);
+ DECLARE_OP1(DW_CFA_def_cfa_offset_sf, OT_SignedFactDataOffset);
+ DECLARE_OP1(DW_CFA_def_cfa_expression, OT_Expression);
+ DECLARE_OP1(DW_CFA_undefined, OT_Register);
+ DECLARE_OP1(DW_CFA_same_value, OT_Register);
+ DECLARE_OP2(DW_CFA_offset, OT_Register, OT_UnsignedFactDataOffset);
+ DECLARE_OP2(DW_CFA_offset_extended, OT_Register, OT_UnsignedFactDataOffset);
+ DECLARE_OP2(DW_CFA_offset_extended_sf, OT_Register, OT_SignedFactDataOffset);
+ DECLARE_OP2(DW_CFA_val_offset, OT_Register, OT_UnsignedFactDataOffset);
+ DECLARE_OP2(DW_CFA_val_offset_sf, OT_Register, OT_SignedFactDataOffset);
+ DECLARE_OP2(DW_CFA_register, OT_Register, OT_Register);
+ DECLARE_OP2(DW_CFA_expression, OT_Register, OT_Expression);
+ DECLARE_OP2(DW_CFA_val_expression, OT_Register, OT_Expression);
+ DECLARE_OP1(DW_CFA_restore, OT_Register);
+ DECLARE_OP1(DW_CFA_restore_extended, OT_Register);
+ DECLARE_OP0(DW_CFA_remember_state);
+ DECLARE_OP0(DW_CFA_restore_state);
+ DECLARE_OP0(DW_CFA_GNU_window_save);
+ DECLARE_OP1(DW_CFA_GNU_args_size, OT_Offset);
+ DECLARE_OP0(DW_CFA_nop);
+
+#undef DECLARE_OP0
+#undef DECLARE_OP1
+#undef DECLARE_OP2
+ return ArrayRef<OperandType[2]>(&OpTypes[0], DW_CFA_restore+1);
+}
+
+static ArrayRef<OperandType[2]> OpTypes = getOperandTypes();
+
+/// \brief Print \p Opcode's operand number \p OperandIdx which has
+/// value \p Operand.
+static void printOperand(raw_ostream &OS, uint8_t Opcode, unsigned OperandIdx,
+ uint64_t Operand, uint64_t CodeAlignmentFactor,
+ int64_t DataAlignmentFactor) {
+ assert(OperandIdx < 2);
+ OperandType Type = OpTypes[Opcode][OperandIdx];
+
+ switch (Type) {
+ case OT_Unset:
+ OS << " Unsupported " << (OperandIdx ? "second" : "first") << " operand to";
+ if (const char *OpcodeName = CallFrameString(Opcode))
+ OS << " " << OpcodeName;
+ else
+ OS << format(" Opcode %x", Opcode);
+ break;
+ case OT_None:
+ break;
+ case OT_Address:
+ OS << format(" %" PRIx64, Operand);
+ break;
+ case OT_Offset:
+ // The offsets are all encoded in a unsigned form, but in practice
+ // consumers use them signed. It's most certainly legacy due to
+ // the lack of signed variants in the first Dwarf standards.
+ OS << format(" %+" PRId64, int64_t(Operand));
+ break;
+ case OT_FactoredCodeOffset: // Always Unsigned
+ if (CodeAlignmentFactor)
+ OS << format(" %" PRId64, Operand * CodeAlignmentFactor);
+ else
+ OS << format(" %" PRId64 "*code_alignment_factor" , Operand);
+ break;
+ case OT_SignedFactDataOffset:
+ if (DataAlignmentFactor)
+ OS << format(" %" PRId64, int64_t(Operand) * DataAlignmentFactor);
+ else
+ OS << format(" %" PRId64 "*data_alignment_factor" , int64_t(Operand));
+ break;
+ case OT_UnsignedFactDataOffset:
+ if (DataAlignmentFactor)
+ OS << format(" %" PRId64, Operand * DataAlignmentFactor);
+ else
+ OS << format(" %" PRId64 "*data_alignment_factor" , Operand);
+ break;
+ case OT_Register:
+ OS << format(" reg%" PRId64, Operand);
+ break;
+ case OT_Expression:
+ OS << " expression";
+ break;
+ }
+}
+
+void FrameEntry::dumpInstructions(raw_ostream &OS) const {
+ uint64_t CodeAlignmentFactor = 0;
+ int64_t DataAlignmentFactor = 0;
+ const CIE *Cie = dyn_cast<CIE>(this);
+
+ if (!Cie)
+ Cie = cast<FDE>(this)->getLinkedCIE();
+ if (Cie) {
+ CodeAlignmentFactor = Cie->getCodeAlignmentFactor();
+ DataAlignmentFactor = Cie->getDataAlignmentFactor();
+ }
+
+ for (const auto &Instr : Instructions) {
+ uint8_t Opcode = Instr.Opcode;
+ if (Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK)
+ Opcode &= DWARF_CFI_PRIMARY_OPCODE_MASK;
+ OS << " " << CallFrameString(Opcode) << ":";
+ for (unsigned i = 0; i < Instr.Ops.size(); ++i)
+ printOperand(OS, Opcode, i, Instr.Ops[i], CodeAlignmentFactor,
+ DataAlignmentFactor);
+ OS << '\n';
+ }
+}
+
+DWARFDebugFrame::DWARFDebugFrame() {
+}
+
+DWARFDebugFrame::~DWARFDebugFrame() {
+}
+
+static void LLVM_ATTRIBUTE_UNUSED dumpDataAux(DataExtractor Data,
+ uint32_t Offset, int Length) {
+ errs() << "DUMP: ";
+ for (int i = 0; i < Length; ++i) {
+ uint8_t c = Data.getU8(&Offset);
+ errs().write_hex(c); errs() << " ";
+ }
+ errs() << "\n";
+}
+
+
+void DWARFDebugFrame::parse(DataExtractor Data) {
+ uint32_t Offset = 0;
+ DenseMap<uint32_t, CIE *> CIEs;
+
+ while (Data.isValidOffset(Offset)) {
+ uint32_t StartOffset = Offset;
+
+ bool IsDWARF64 = false;
+ uint64_t Length = Data.getU32(&Offset);
+ uint64_t Id;
+
+ if (Length == UINT32_MAX) {
+ // DWARF-64 is distinguished by the first 32 bits of the initial length
+ // field being 0xffffffff. Then, the next 64 bits are the actual entry
+ // length.
+ IsDWARF64 = true;
+ Length = Data.getU64(&Offset);
+ }
+
+ // At this point, Offset points to the next field after Length.
+ // Length is the structure size excluding itself. Compute an offset one
+ // past the end of the structure (needed to know how many instructions to
+ // read).
+ // TODO: For honest DWARF64 support, DataExtractor will have to treat
+ // offset_ptr as uint64_t*
+ uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);
+
+ // The Id field's size depends on the DWARF format
+ Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
+ bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);
+
+ if (IsCIE) {
+ uint8_t Version = Data.getU8(&Offset);
+ const char *Augmentation = Data.getCStr(&Offset);
+ uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : Data.getU8(&Offset);
+ Data.setAddressSize(AddressSize);
+ uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
+ uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
+ int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
+ uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);
+
+ auto Cie = make_unique<CIE>(StartOffset, Length, Version,
+ StringRef(Augmentation), AddressSize,
+ SegmentDescriptorSize, CodeAlignmentFactor,
+ DataAlignmentFactor, ReturnAddressRegister);
+ CIEs[StartOffset] = Cie.get();
+ Entries.emplace_back(std::move(Cie));
+ } else {
+ // FDE
+ uint64_t CIEPointer = Id;
+ uint64_t InitialLocation = Data.getAddress(&Offset);
+ uint64_t AddressRange = Data.getAddress(&Offset);
+
+ Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
+ InitialLocation, AddressRange,
+ CIEs[CIEPointer]));
+ }
+
+ Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);
+
+ if (Offset != EndStructureOffset) {
+ std::string Str;
+ raw_string_ostream OS(Str);
+ OS << format("Parsing entry instructions at %lx failed", StartOffset);
+ report_fatal_error(Str);
+ }
+ }
+}
+
+
+void DWARFDebugFrame::dump(raw_ostream &OS) const {
+ OS << "\n";
+ for (const auto &Entry : Entries) {
+ Entry->dumpHeader(OS);
+ Entry->dumpInstructions(OS);
+ OS << "\n";
+ }
+}
+
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
new file mode 100644
index 0000000..62d5e66
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp
@@ -0,0 +1,460 @@
+//===-- DWARFDebugInfoEntry.cpp -------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SyntaxHighlighting.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugInfoEntry.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+using namespace dwarf;
+using namespace syntax;
+
+// Small helper to extract a DIE pointed by a reference
+// attribute. It looks up the Unit containing the DIE and calls
+// DIE.extractFast with the right unit. Returns new unit on success,
+// nullptr otherwise.
+static const DWARFUnit *findUnitAndExtractFast(DWARFDebugInfoEntryMinimal &DIE,
+ const DWARFUnit *Unit,
+ uint32_t *Offset) {
+ Unit = Unit->getUnitSection().getUnitForOffset(*Offset);
+ return (Unit && DIE.extractFast(Unit, Offset)) ? Unit : nullptr;
+}
+
+void DWARFDebugInfoEntryMinimal::dump(raw_ostream &OS, DWARFUnit *u,
+ unsigned recurseDepth,
+ unsigned indent) const {
+ DataExtractor debug_info_data = u->getDebugInfoExtractor();
+ uint32_t offset = Offset;
+
+ if (debug_info_data.isValidOffset(offset)) {
+ uint32_t abbrCode = debug_info_data.getULEB128(&offset);
+ WithColor(OS, syntax::Address).get() << format("\n0x%8.8x: ", Offset);
+
+ if (abbrCode) {
+ if (AbbrevDecl) {
+ const char *tagString = TagString(getTag());
+ if (tagString)
+ WithColor(OS, syntax::Tag).get().indent(indent) << tagString;
+ else
+ WithColor(OS, syntax::Tag).get().indent(indent) <<
+ format("DW_TAG_Unknown_%x", getTag());
+
+ OS << format(" [%u] %c\n", abbrCode,
+ AbbrevDecl->hasChildren() ? '*' : ' ');
+
+ // Dump all data in the DIE for the attributes.
+ for (const auto &AttrSpec : AbbrevDecl->attributes()) {
+ dumpAttribute(OS, u, &offset, AttrSpec.Attr, AttrSpec.Form, indent);
+ }
+
+ const DWARFDebugInfoEntryMinimal *child = getFirstChild();
+ if (recurseDepth > 0 && child) {
+ while (child) {
+ child->dump(OS, u, recurseDepth-1, indent+2);
+ child = child->getSibling();
+ }
+ }
+ } else {
+ OS << "Abbreviation code not found in 'debug_abbrev' class for code: "
+ << abbrCode << '\n';
+ }
+ } else {
+ OS.indent(indent) << "NULL\n";
+ }
+ }
+}
+
+static void dumpApplePropertyAttribute(raw_ostream &OS, uint64_t Val) {
+ OS << " (";
+ do {
+ uint64_t Shift = countTrailingZeros(Val);
+ assert(Shift < 64 && "undefined behavior");
+ uint64_t Bit = 1ULL << Shift;
+ if (const char *PropName = ApplePropertyString(Bit))
+ OS << PropName;
+ else
+ OS << format("DW_APPLE_PROPERTY_0x%" PRIx64, Bit);
+ if (!(Val ^= Bit))
+ break;
+ OS << ", ";
+ } while (true);
+ OS << ")";
+}
+
+static void dumpRanges(raw_ostream &OS, const DWARFAddressRangesVector& Ranges,
+ unsigned AddressSize, unsigned Indent) {
+ if (Ranges.empty())
+ return;
+
+ for (const auto &Range: Ranges) {
+ OS << '\n';
+ OS.indent(Indent);
+ OS << format("[0x%0*" PRIx64 " - 0x%0*" PRIx64 ")",
+ AddressSize*2, Range.first,
+ AddressSize*2, Range.second);
+ }
+}
+
+void DWARFDebugInfoEntryMinimal::dumpAttribute(raw_ostream &OS,
+ DWARFUnit *u,
+ uint32_t *offset_ptr,
+ uint16_t attr, uint16_t form,
+ unsigned indent) const {
+ const char BaseIndent[] = " ";
+ OS << BaseIndent;
+ OS.indent(indent+2);
+ const char *attrString = AttributeString(attr);
+ if (attrString)
+ WithColor(OS, syntax::Attribute) << attrString;
+ else
+ WithColor(OS, syntax::Attribute).get() << format("DW_AT_Unknown_%x", attr);
+
+ const char *formString = FormEncodingString(form);
+ if (formString)
+ OS << " [" << formString << ']';
+ else
+ OS << format(" [DW_FORM_Unknown_%x]", form);
+
+ DWARFFormValue formValue(form);
+
+ if (!formValue.extractValue(u->getDebugInfoExtractor(), offset_ptr, u))
+ return;
+
+ OS << "\t(";
+
+ const char *Name = nullptr;
+ std::string File;
+ auto Color = syntax::Enumerator;
+ if (attr == DW_AT_decl_file || attr == DW_AT_call_file) {
+ Color = syntax::String;
+ if (const auto *LT = u->getContext().getLineTableForUnit(u))
+ if (LT->getFileNameByIndex(
+ formValue.getAsUnsignedConstant().getValue(),
+ u->getCompilationDir(),
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File)) {
+ File = '"' + File + '"';
+ Name = File.c_str();
+ }
+ } else if (Optional<uint64_t> Val = formValue.getAsUnsignedConstant())
+ Name = AttributeValueString(attr, *Val);
+
+ if (Name)
+ WithColor(OS, Color) << Name;
+ else if (attr == DW_AT_decl_line || attr == DW_AT_call_line)
+ OS << *formValue.getAsUnsignedConstant();
+ else
+ formValue.dump(OS, u);
+
+ // We have dumped the attribute raw value. For some attributes
+ // having both the raw value and the pretty-printed value is
+ // interesting. These attributes are handled below.
+ if (attr == DW_AT_specification || attr == DW_AT_abstract_origin) {
+ Optional<uint64_t> Ref = formValue.getAsReference(u);
+ if (Ref.hasValue()) {
+ uint32_t RefOffset = Ref.getValue();
+ DWARFDebugInfoEntryMinimal DIE;
+ if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &RefOffset))
+ if (const char *Name = DIE.getName(RefU, DINameKind::LinkageName))
+ OS << " \"" << Name << '\"';
+ }
+ } else if (attr == DW_AT_APPLE_property_attribute) {
+ if (Optional<uint64_t> OptVal = formValue.getAsUnsignedConstant())
+ dumpApplePropertyAttribute(OS, *OptVal);
+ } else if (attr == DW_AT_ranges) {
+ dumpRanges(OS, getAddressRanges(u), u->getAddressByteSize(),
+ sizeof(BaseIndent)+indent+4);
+ }
+
+ OS << ")\n";
+}
+
+bool DWARFDebugInfoEntryMinimal::extractFast(const DWARFUnit *U,
+ uint32_t *OffsetPtr) {
+ Offset = *OffsetPtr;
+ DataExtractor DebugInfoData = U->getDebugInfoExtractor();
+ uint32_t UEndOffset = U->getNextUnitOffset();
+ if (Offset >= UEndOffset || !DebugInfoData.isValidOffset(Offset))
+ return false;
+ uint64_t AbbrCode = DebugInfoData.getULEB128(OffsetPtr);
+ if (0 == AbbrCode) {
+ // NULL debug tag entry.
+ AbbrevDecl = nullptr;
+ return true;
+ }
+ AbbrevDecl = U->getAbbreviations()->getAbbreviationDeclaration(AbbrCode);
+ if (nullptr == AbbrevDecl) {
+ // Restore the original offset.
+ *OffsetPtr = Offset;
+ return false;
+ }
+ ArrayRef<uint8_t> FixedFormSizes = DWARFFormValue::getFixedFormSizes(
+ U->getAddressByteSize(), U->getVersion());
+ assert(FixedFormSizes.size() > 0);
+
+ // Skip all data in the .debug_info for the attributes
+ for (const auto &AttrSpec : AbbrevDecl->attributes()) {
+ uint16_t Form = AttrSpec.Form;
+
+ uint8_t FixedFormSize =
+ (Form < FixedFormSizes.size()) ? FixedFormSizes[Form] : 0;
+ if (FixedFormSize)
+ *OffsetPtr += FixedFormSize;
+ else if (!DWARFFormValue::skipValue(Form, DebugInfoData, OffsetPtr, U)) {
+ // Restore the original offset.
+ *OffsetPtr = Offset;
+ return false;
+ }
+ }
+ return true;
+}
+
+bool DWARFDebugInfoEntryMinimal::isSubprogramDIE() const {
+ return getTag() == DW_TAG_subprogram;
+}
+
+bool DWARFDebugInfoEntryMinimal::isSubroutineDIE() const {
+ uint32_t Tag = getTag();
+ return Tag == DW_TAG_subprogram ||
+ Tag == DW_TAG_inlined_subroutine;
+}
+
+bool DWARFDebugInfoEntryMinimal::getAttributeValue(
+ const DWARFUnit *U, const uint16_t Attr, DWARFFormValue &FormValue) const {
+ if (!AbbrevDecl)
+ return false;
+
+ uint32_t AttrIdx = AbbrevDecl->findAttributeIndex(Attr);
+ if (AttrIdx == -1U)
+ return false;
+
+ DataExtractor DebugInfoData = U->getDebugInfoExtractor();
+ uint32_t DebugInfoOffset = getOffset();
+
+ // Skip the abbreviation code so we are at the data for the attributes
+ DebugInfoData.getULEB128(&DebugInfoOffset);
+
+ // Skip preceding attribute values.
+ for (uint32_t i = 0; i < AttrIdx; ++i) {
+ DWARFFormValue::skipValue(AbbrevDecl->getFormByIndex(i),
+ DebugInfoData, &DebugInfoOffset, U);
+ }
+
+ FormValue = DWARFFormValue(AbbrevDecl->getFormByIndex(AttrIdx));
+ return FormValue.extractValue(DebugInfoData, &DebugInfoOffset, U);
+}
+
+const char *DWARFDebugInfoEntryMinimal::getAttributeValueAsString(
+ const DWARFUnit *U, const uint16_t Attr, const char *FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<const char *> Result = FormValue.getAsCString(U);
+ return Result.hasValue() ? Result.getValue() : FailValue;
+}
+
+uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsAddress(
+ const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<uint64_t> Result = FormValue.getAsAddress(U);
+ return Result.hasValue() ? Result.getValue() : FailValue;
+}
+
+uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsUnsignedConstant(
+ const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<uint64_t> Result = FormValue.getAsUnsignedConstant();
+ return Result.hasValue() ? Result.getValue() : FailValue;
+}
+
+uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsReference(
+ const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<uint64_t> Result = FormValue.getAsReference(U);
+ return Result.hasValue() ? Result.getValue() : FailValue;
+}
+
+uint64_t DWARFDebugInfoEntryMinimal::getAttributeValueAsSectionOffset(
+ const DWARFUnit *U, const uint16_t Attr, uint64_t FailValue) const {
+ DWARFFormValue FormValue;
+ if (!getAttributeValue(U, Attr, FormValue))
+ return FailValue;
+ Optional<uint64_t> Result = FormValue.getAsSectionOffset();
+ return Result.hasValue() ? Result.getValue() : FailValue;
+}
+
+uint64_t
+DWARFDebugInfoEntryMinimal::getRangesBaseAttribute(const DWARFUnit *U,
+ uint64_t FailValue) const {
+ uint64_t Result =
+ getAttributeValueAsSectionOffset(U, DW_AT_ranges_base, -1ULL);
+ if (Result != -1ULL)
+ return Result;
+ return getAttributeValueAsSectionOffset(U, DW_AT_GNU_ranges_base, FailValue);
+}
+
+bool DWARFDebugInfoEntryMinimal::getLowAndHighPC(const DWARFUnit *U,
+ uint64_t &LowPC,
+ uint64_t &HighPC) const {
+ LowPC = getAttributeValueAsAddress(U, DW_AT_low_pc, -1ULL);
+ if (LowPC == -1ULL)
+ return false;
+ HighPC = getAttributeValueAsAddress(U, DW_AT_high_pc, -1ULL);
+ if (HighPC == -1ULL) {
+ // Since DWARF4, DW_AT_high_pc may also be of class constant, in which case
+ // it represents function size.
+ HighPC = getAttributeValueAsUnsignedConstant(U, DW_AT_high_pc, -1ULL);
+ if (HighPC != -1ULL)
+ HighPC += LowPC;
+ }
+ return (HighPC != -1ULL);
+}
+
+DWARFAddressRangesVector
+DWARFDebugInfoEntryMinimal::getAddressRanges(const DWARFUnit *U) const {
+ if (isNULL())
+ return DWARFAddressRangesVector();
+ // Single range specified by low/high PC.
+ uint64_t LowPC, HighPC;
+ if (getLowAndHighPC(U, LowPC, HighPC)) {
+ return DWARFAddressRangesVector(1, std::make_pair(LowPC, HighPC));
+ }
+ // Multiple ranges from .debug_ranges section.
+ uint32_t RangesOffset =
+ getAttributeValueAsSectionOffset(U, DW_AT_ranges, -1U);
+ if (RangesOffset != -1U) {
+ DWARFDebugRangeList RangeList;
+ if (U->extractRangeList(RangesOffset, RangeList))
+ return RangeList.getAbsoluteRanges(U->getBaseAddress());
+ }
+ return DWARFAddressRangesVector();
+}
+
+void DWARFDebugInfoEntryMinimal::collectChildrenAddressRanges(
+ const DWARFUnit *U, DWARFAddressRangesVector& Ranges) const {
+ if (isNULL())
+ return;
+ if (isSubprogramDIE()) {
+ const auto &DIERanges = getAddressRanges(U);
+ Ranges.insert(Ranges.end(), DIERanges.begin(), DIERanges.end());
+ }
+
+ const DWARFDebugInfoEntryMinimal *Child = getFirstChild();
+ while (Child) {
+ Child->collectChildrenAddressRanges(U, Ranges);
+ Child = Child->getSibling();
+ }
+}
+
+bool DWARFDebugInfoEntryMinimal::addressRangeContainsAddress(
+ const DWARFUnit *U, const uint64_t Address) const {
+ for (const auto& R : getAddressRanges(U)) {
+ if (R.first <= Address && Address < R.second)
+ return true;
+ }
+ return false;
+}
+
+const char *
+DWARFDebugInfoEntryMinimal::getSubroutineName(const DWARFUnit *U,
+ DINameKind Kind) const {
+ if (!isSubroutineDIE())
+ return nullptr;
+ return getName(U, Kind);
+}
+
+const char *
+DWARFDebugInfoEntryMinimal::getName(const DWARFUnit *U,
+ DINameKind Kind) const {
+ if (Kind == DINameKind::None)
+ return nullptr;
+ // Try to get mangled name only if it was asked for.
+ if (Kind == DINameKind::LinkageName) {
+ if (const char *name =
+ getAttributeValueAsString(U, DW_AT_MIPS_linkage_name, nullptr))
+ return name;
+ if (const char *name =
+ getAttributeValueAsString(U, DW_AT_linkage_name, nullptr))
+ return name;
+ }
+ if (const char *name = getAttributeValueAsString(U, DW_AT_name, nullptr))
+ return name;
+ // Try to get name from specification DIE.
+ uint32_t spec_ref =
+ getAttributeValueAsReference(U, DW_AT_specification, -1U);
+ if (spec_ref != -1U) {
+ DWARFDebugInfoEntryMinimal spec_die;
+ if (const DWARFUnit *RefU = findUnitAndExtractFast(spec_die, U, &spec_ref)) {
+ if (const char *name = spec_die.getName(RefU, Kind))
+ return name;
+ }
+ }
+ // Try to get name from abstract origin DIE.
+ uint32_t abs_origin_ref =
+ getAttributeValueAsReference(U, DW_AT_abstract_origin, -1U);
+ if (abs_origin_ref != -1U) {
+ DWARFDebugInfoEntryMinimal abs_origin_die;
+ if (const DWARFUnit *RefU = findUnitAndExtractFast(abs_origin_die, U,
+ &abs_origin_ref)) {
+ if (const char *name = abs_origin_die.getName(RefU, Kind))
+ return name;
+ }
+ }
+ return nullptr;
+}
+
+void DWARFDebugInfoEntryMinimal::getCallerFrame(const DWARFUnit *U,
+ uint32_t &CallFile,
+ uint32_t &CallLine,
+ uint32_t &CallColumn) const {
+ CallFile = getAttributeValueAsUnsignedConstant(U, DW_AT_call_file, 0);
+ CallLine = getAttributeValueAsUnsignedConstant(U, DW_AT_call_line, 0);
+ CallColumn = getAttributeValueAsUnsignedConstant(U, DW_AT_call_column, 0);
+}
+
+DWARFDebugInfoEntryInlinedChain
+DWARFDebugInfoEntryMinimal::getInlinedChainForAddress(
+ const DWARFUnit *U, const uint64_t Address) const {
+ DWARFDebugInfoEntryInlinedChain InlinedChain;
+ InlinedChain.U = U;
+ if (isNULL())
+ return InlinedChain;
+ for (const DWARFDebugInfoEntryMinimal *DIE = this; DIE; ) {
+ // Append current DIE to inlined chain only if it has correct tag
+ // (e.g. it is not a lexical block).
+ if (DIE->isSubroutineDIE()) {
+ InlinedChain.DIEs.push_back(*DIE);
+ }
+ // Try to get child which also contains provided address.
+ const DWARFDebugInfoEntryMinimal *Child = DIE->getFirstChild();
+ while (Child) {
+ if (Child->addressRangeContainsAddress(U, Address)) {
+ // Assume there is only one such child.
+ break;
+ }
+ Child = Child->getSibling();
+ }
+ DIE = Child;
+ }
+ // Reverse the obtained chain to make the root of inlined chain last.
+ std::reverse(InlinedChain.DIEs.begin(), InlinedChain.DIEs.end());
+ return InlinedChain;
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
new file mode 100644
index 0000000..a0bee0d
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp
@@ -0,0 +1,688 @@
+//===-- DWARFDebugLine.cpp ------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+using namespace llvm;
+using namespace dwarf;
+typedef DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind;
+
+DWARFDebugLine::Prologue::Prologue() {
+ clear();
+}
+
+void DWARFDebugLine::Prologue::clear() {
+ TotalLength = Version = PrologueLength = 0;
+ MinInstLength = MaxOpsPerInst = DefaultIsStmt = LineBase = LineRange = 0;
+ OpcodeBase = 0;
+ IsDWARF64 = false;
+ StandardOpcodeLengths.clear();
+ IncludeDirectories.clear();
+ FileNames.clear();
+}
+
+void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const {
+ OS << "Line table prologue:\n"
+ << format(" total_length: 0x%8.8" PRIx64 "\n", TotalLength)
+ << format(" version: %u\n", Version)
+ << format(" prologue_length: 0x%8.8" PRIx64 "\n", PrologueLength)
+ << format(" min_inst_length: %u\n", MinInstLength)
+ << format(Version >= 4 ? "max_ops_per_inst: %u\n" : "", MaxOpsPerInst)
+ << format(" default_is_stmt: %u\n", DefaultIsStmt)
+ << format(" line_base: %i\n", LineBase)
+ << format(" line_range: %u\n", LineRange)
+ << format(" opcode_base: %u\n", OpcodeBase);
+
+ for (uint32_t i = 0; i < StandardOpcodeLengths.size(); ++i)
+ OS << format("standard_opcode_lengths[%s] = %u\n", LNStandardString(i+1),
+ StandardOpcodeLengths[i]);
+
+ if (!IncludeDirectories.empty())
+ for (uint32_t i = 0; i < IncludeDirectories.size(); ++i)
+ OS << format("include_directories[%3u] = '", i+1)
+ << IncludeDirectories[i] << "'\n";
+
+ if (!FileNames.empty()) {
+ OS << " Dir Mod Time File Len File Name\n"
+ << " ---- ---------- ---------- -----------"
+ "----------------\n";
+ for (uint32_t i = 0; i < FileNames.size(); ++i) {
+ const FileNameEntry& fileEntry = FileNames[i];
+ OS << format("file_names[%3u] %4" PRIu64 " ", i+1, fileEntry.DirIdx)
+ << format("0x%8.8" PRIx64 " 0x%8.8" PRIx64 " ",
+ fileEntry.ModTime, fileEntry.Length)
+ << fileEntry.Name << '\n';
+ }
+ }
+}
+
+bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data,
+ uint32_t *offset_ptr) {
+ const uint64_t prologue_offset = *offset_ptr;
+
+ clear();
+ TotalLength = debug_line_data.getU32(offset_ptr);
+ if (TotalLength == UINT32_MAX) {
+ IsDWARF64 = true;
+ TotalLength = debug_line_data.getU64(offset_ptr);
+ } else if (TotalLength > 0xffffff00) {
+ return false;
+ }
+ Version = debug_line_data.getU16(offset_ptr);
+ if (Version < 2)
+ return false;
+
+ PrologueLength = debug_line_data.getUnsigned(offset_ptr,
+ sizeofPrologueLength());
+ const uint64_t end_prologue_offset = PrologueLength + *offset_ptr;
+ MinInstLength = debug_line_data.getU8(offset_ptr);
+ if (Version >= 4)
+ MaxOpsPerInst = debug_line_data.getU8(offset_ptr);
+ DefaultIsStmt = debug_line_data.getU8(offset_ptr);
+ LineBase = debug_line_data.getU8(offset_ptr);
+ LineRange = debug_line_data.getU8(offset_ptr);
+ OpcodeBase = debug_line_data.getU8(offset_ptr);
+
+ StandardOpcodeLengths.reserve(OpcodeBase - 1);
+ for (uint32_t i = 1; i < OpcodeBase; ++i) {
+ uint8_t op_len = debug_line_data.getU8(offset_ptr);
+ StandardOpcodeLengths.push_back(op_len);
+ }
+
+ while (*offset_ptr < end_prologue_offset) {
+ const char *s = debug_line_data.getCStr(offset_ptr);
+ if (s && s[0])
+ IncludeDirectories.push_back(s);
+ else
+ break;
+ }
+
+ while (*offset_ptr < end_prologue_offset) {
+ const char *name = debug_line_data.getCStr(offset_ptr);
+ if (name && name[0]) {
+ FileNameEntry fileEntry;
+ fileEntry.Name = name;
+ fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr);
+ fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr);
+ fileEntry.Length = debug_line_data.getULEB128(offset_ptr);
+ FileNames.push_back(fileEntry);
+ } else {
+ break;
+ }
+ }
+
+ if (*offset_ptr != end_prologue_offset) {
+ fprintf(stderr, "warning: parsing line table prologue at 0x%8.8" PRIx64
+ " should have ended at 0x%8.8" PRIx64
+ " but it ended at 0x%8.8" PRIx64 "\n",
+ prologue_offset, end_prologue_offset, (uint64_t)*offset_ptr);
+ return false;
+ }
+ return true;
+}
+
+DWARFDebugLine::Row::Row(bool default_is_stmt) {
+ reset(default_is_stmt);
+}
+
+void DWARFDebugLine::Row::postAppend() {
+ BasicBlock = false;
+ PrologueEnd = false;
+ EpilogueBegin = false;
+}
+
+void DWARFDebugLine::Row::reset(bool default_is_stmt) {
+ Address = 0;
+ Line = 1;
+ Column = 0;
+ File = 1;
+ Isa = 0;
+ Discriminator = 0;
+ IsStmt = default_is_stmt;
+ BasicBlock = false;
+ EndSequence = false;
+ PrologueEnd = false;
+ EpilogueBegin = false;
+}
+
+void DWARFDebugLine::Row::dump(raw_ostream &OS) const {
+ OS << format("0x%16.16" PRIx64 " %6u %6u", Address, Line, Column)
+ << format(" %6u %3u %13u ", File, Isa, Discriminator)
+ << (IsStmt ? " is_stmt" : "")
+ << (BasicBlock ? " basic_block" : "")
+ << (PrologueEnd ? " prologue_end" : "")
+ << (EpilogueBegin ? " epilogue_begin" : "")
+ << (EndSequence ? " end_sequence" : "")
+ << '\n';
+}
+
+DWARFDebugLine::Sequence::Sequence() {
+ reset();
+}
+
+void DWARFDebugLine::Sequence::reset() {
+ LowPC = 0;
+ HighPC = 0;
+ FirstRowIndex = 0;
+ LastRowIndex = 0;
+ Empty = true;
+}
+
+DWARFDebugLine::LineTable::LineTable() {
+ clear();
+}
+
+void DWARFDebugLine::LineTable::dump(raw_ostream &OS) const {
+ Prologue.dump(OS);
+ OS << '\n';
+
+ if (!Rows.empty()) {
+ OS << "Address Line Column File ISA Discriminator Flags\n"
+ << "------------------ ------ ------ ------ --- ------------- "
+ "-------------\n";
+ for (const Row &R : Rows) {
+ R.dump(OS);
+ }
+ }
+}
+
+void DWARFDebugLine::LineTable::clear() {
+ Prologue.clear();
+ Rows.clear();
+ Sequences.clear();
+}
+
+DWARFDebugLine::ParsingState::ParsingState(struct LineTable *LT)
+ : LineTable(LT), RowNumber(0) {
+ resetRowAndSequence();
+}
+
+void DWARFDebugLine::ParsingState::resetRowAndSequence() {
+ Row.reset(LineTable->Prologue.DefaultIsStmt);
+ Sequence.reset();
+}
+
+void DWARFDebugLine::ParsingState::appendRowToMatrix(uint32_t offset) {
+ if (Sequence.Empty) {
+ // Record the beginning of instruction sequence.
+ Sequence.Empty = false;
+ Sequence.LowPC = Row.Address;
+ Sequence.FirstRowIndex = RowNumber;
+ }
+ ++RowNumber;
+ LineTable->appendRow(Row);
+ if (Row.EndSequence) {
+ // Record the end of instruction sequence.
+ Sequence.HighPC = Row.Address;
+ Sequence.LastRowIndex = RowNumber;
+ if (Sequence.isValid())
+ LineTable->appendSequence(Sequence);
+ Sequence.reset();
+ }
+ Row.postAppend();
+}
+
+const DWARFDebugLine::LineTable *
+DWARFDebugLine::getLineTable(uint32_t offset) const {
+ LineTableConstIter pos = LineTableMap.find(offset);
+ if (pos != LineTableMap.end())
+ return &pos->second;
+ return nullptr;
+}
+
+const DWARFDebugLine::LineTable *
+DWARFDebugLine::getOrParseLineTable(DataExtractor debug_line_data,
+ uint32_t offset) {
+ std::pair<LineTableIter, bool> pos =
+ LineTableMap.insert(LineTableMapTy::value_type(offset, LineTable()));
+ LineTable *LT = &pos.first->second;
+ if (pos.second) {
+ if (!LT->parse(debug_line_data, RelocMap, &offset))
+ return nullptr;
+ }
+ return LT;
+}
+
+bool DWARFDebugLine::LineTable::parse(DataExtractor debug_line_data,
+ const RelocAddrMap *RMap,
+ uint32_t *offset_ptr) {
+ const uint32_t debug_line_offset = *offset_ptr;
+
+ clear();
+
+ if (!Prologue.parse(debug_line_data, offset_ptr)) {
+ // Restore our offset and return false to indicate failure!
+ *offset_ptr = debug_line_offset;
+ return false;
+ }
+
+ const uint32_t end_offset = debug_line_offset + Prologue.TotalLength +
+ Prologue.sizeofTotalLength();
+
+ ParsingState State(this);
+
+ while (*offset_ptr < end_offset) {
+ uint8_t opcode = debug_line_data.getU8(offset_ptr);
+
+ if (opcode == 0) {
+ // Extended Opcodes always start with a zero opcode followed by
+ // a uleb128 length so you can skip ones you don't know about
+ uint32_t ext_offset = *offset_ptr;
+ uint64_t len = debug_line_data.getULEB128(offset_ptr);
+ uint32_t arg_size = len - (*offset_ptr - ext_offset);
+
+ uint8_t sub_opcode = debug_line_data.getU8(offset_ptr);
+ switch (sub_opcode) {
+ case DW_LNE_end_sequence:
+ // Set the end_sequence register of the state machine to true and
+ // append a row to the matrix using the current values of the
+ // state-machine registers. Then reset the registers to the initial
+ // values specified above. Every statement program sequence must end
+ // with a DW_LNE_end_sequence instruction which creates a row whose
+ // address is that of the byte after the last target machine instruction
+ // of the sequence.
+ State.Row.EndSequence = true;
+ State.appendRowToMatrix(*offset_ptr);
+ State.resetRowAndSequence();
+ break;
+
+ case DW_LNE_set_address:
+ // Takes a single relocatable address as an operand. The size of the
+ // operand is the size appropriate to hold an address on the target
+ // machine. Set the address register to the value given by the
+ // relocatable address. All of the other statement program opcodes
+ // that affect the address register add a delta to it. This instruction
+ // stores a relocatable value into it instead.
+ {
+ // If this address is in our relocation map, apply the relocation.
+ RelocAddrMap::const_iterator AI = RMap->find(*offset_ptr);
+ if (AI != RMap->end()) {
+ const std::pair<uint8_t, int64_t> &R = AI->second;
+ State.Row.Address =
+ debug_line_data.getAddress(offset_ptr) + R.second;
+ } else
+ State.Row.Address = debug_line_data.getAddress(offset_ptr);
+ }
+ break;
+
+ case DW_LNE_define_file:
+ // Takes 4 arguments. The first is a null terminated string containing
+ // a source file name. The second is an unsigned LEB128 number
+ // representing the directory index of the directory in which the file
+ // was found. The third is an unsigned LEB128 number representing the
+ // time of last modification of the file. The fourth is an unsigned
+ // LEB128 number representing the length in bytes of the file. The time
+ // and length fields may contain LEB128(0) if the information is not
+ // available.
+ //
+ // The directory index represents an entry in the include_directories
+ // section of the statement program prologue. The index is LEB128(0)
+ // if the file was found in the current directory of the compilation,
+ // LEB128(1) if it was found in the first directory in the
+ // include_directories section, and so on. The directory index is
+ // ignored for file names that represent full path names.
+ //
+ // The files are numbered, starting at 1, in the order in which they
+ // appear; the names in the prologue come before names defined by
+ // the DW_LNE_define_file instruction. These numbers are used in the
+ // the file register of the state machine.
+ {
+ FileNameEntry fileEntry;
+ fileEntry.Name = debug_line_data.getCStr(offset_ptr);
+ fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr);
+ fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr);
+ fileEntry.Length = debug_line_data.getULEB128(offset_ptr);
+ Prologue.FileNames.push_back(fileEntry);
+ }
+ break;
+
+ case DW_LNE_set_discriminator:
+ State.Row.Discriminator = debug_line_data.getULEB128(offset_ptr);
+ break;
+
+ default:
+ // Length doesn't include the zero opcode byte or the length itself, but
+ // it does include the sub_opcode, so we have to adjust for that below
+ (*offset_ptr) += arg_size;
+ break;
+ }
+ } else if (opcode < Prologue.OpcodeBase) {
+ switch (opcode) {
+ // Standard Opcodes
+ case DW_LNS_copy:
+ // Takes no arguments. Append a row to the matrix using the
+ // current values of the state-machine registers. Then set
+ // the basic_block register to false.
+ State.appendRowToMatrix(*offset_ptr);
+ break;
+
+ case DW_LNS_advance_pc:
+ // Takes a single unsigned LEB128 operand, multiplies it by the
+ // min_inst_length field of the prologue, and adds the
+ // result to the address register of the state machine.
+ State.Row.Address +=
+ debug_line_data.getULEB128(offset_ptr) * Prologue.MinInstLength;
+ break;
+
+ case DW_LNS_advance_line:
+ // Takes a single signed LEB128 operand and adds that value to
+ // the line register of the state machine.
+ State.Row.Line += debug_line_data.getSLEB128(offset_ptr);
+ break;
+
+ case DW_LNS_set_file:
+ // Takes a single unsigned LEB128 operand and stores it in the file
+ // register of the state machine.
+ State.Row.File = debug_line_data.getULEB128(offset_ptr);
+ break;
+
+ case DW_LNS_set_column:
+ // Takes a single unsigned LEB128 operand and stores it in the
+ // column register of the state machine.
+ State.Row.Column = debug_line_data.getULEB128(offset_ptr);
+ break;
+
+ case DW_LNS_negate_stmt:
+ // Takes no arguments. Set the is_stmt register of the state
+ // machine to the logical negation of its current value.
+ State.Row.IsStmt = !State.Row.IsStmt;
+ break;
+
+ case DW_LNS_set_basic_block:
+ // Takes no arguments. Set the basic_block register of the
+ // state machine to true
+ State.Row.BasicBlock = true;
+ break;
+
+ case DW_LNS_const_add_pc:
+ // Takes no arguments. Add to the address register of the state
+ // machine the address increment value corresponding to special
+ // opcode 255. The motivation for DW_LNS_const_add_pc is this:
+ // when the statement program needs to advance the address by a
+ // small amount, it can use a single special opcode, which occupies
+ // a single byte. When it needs to advance the address by up to
+ // twice the range of the last special opcode, it can use
+ // DW_LNS_const_add_pc followed by a special opcode, for a total
+ // of two bytes. Only if it needs to advance the address by more
+ // than twice that range will it need to use both DW_LNS_advance_pc
+ // and a special opcode, requiring three or more bytes.
+ {
+ uint8_t adjust_opcode = 255 - Prologue.OpcodeBase;
+ uint64_t addr_offset =
+ (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength;
+ State.Row.Address += addr_offset;
+ }
+ break;
+
+ case DW_LNS_fixed_advance_pc:
+ // Takes a single uhalf operand. Add to the address register of
+ // the state machine the value of the (unencoded) operand. This
+ // is the only extended opcode that takes an argument that is not
+ // a variable length number. The motivation for DW_LNS_fixed_advance_pc
+ // is this: existing assemblers cannot emit DW_LNS_advance_pc or
+ // special opcodes because they cannot encode LEB128 numbers or
+ // judge when the computation of a special opcode overflows and
+ // requires the use of DW_LNS_advance_pc. Such assemblers, however,
+ // can use DW_LNS_fixed_advance_pc instead, sacrificing compression.
+ State.Row.Address += debug_line_data.getU16(offset_ptr);
+ break;
+
+ case DW_LNS_set_prologue_end:
+ // Takes no arguments. Set the prologue_end register of the
+ // state machine to true
+ State.Row.PrologueEnd = true;
+ break;
+
+ case DW_LNS_set_epilogue_begin:
+ // Takes no arguments. Set the basic_block register of the
+ // state machine to true
+ State.Row.EpilogueBegin = true;
+ break;
+
+ case DW_LNS_set_isa:
+ // Takes a single unsigned LEB128 operand and stores it in the
+ // column register of the state machine.
+ State.Row.Isa = debug_line_data.getULEB128(offset_ptr);
+ break;
+
+ default:
+ // Handle any unknown standard opcodes here. We know the lengths
+ // of such opcodes because they are specified in the prologue
+ // as a multiple of LEB128 operands for each opcode.
+ {
+ assert(opcode - 1U < Prologue.StandardOpcodeLengths.size());
+ uint8_t opcode_length = Prologue.StandardOpcodeLengths[opcode - 1];
+ for (uint8_t i = 0; i < opcode_length; ++i)
+ debug_line_data.getULEB128(offset_ptr);
+ }
+ break;
+ }
+ } else {
+ // Special Opcodes
+
+ // A special opcode value is chosen based on the amount that needs
+ // to be added to the line and address registers. The maximum line
+ // increment for a special opcode is the value of the line_base
+ // field in the header, plus the value of the line_range field,
+ // minus 1 (line base + line range - 1). If the desired line
+ // increment is greater than the maximum line increment, a standard
+ // opcode must be used instead of a special opcode. The "address
+ // advance" is calculated by dividing the desired address increment
+ // by the minimum_instruction_length field from the header. The
+ // special opcode is then calculated using the following formula:
+ //
+ // opcode = (desired line increment - line_base) +
+ // (line_range * address advance) + opcode_base
+ //
+ // If the resulting opcode is greater than 255, a standard opcode
+ // must be used instead.
+ //
+ // To decode a special opcode, subtract the opcode_base from the
+ // opcode itself to give the adjusted opcode. The amount to
+ // increment the address register is the result of the adjusted
+ // opcode divided by the line_range multiplied by the
+ // minimum_instruction_length field from the header. That is:
+ //
+ // address increment = (adjusted opcode / line_range) *
+ // minimum_instruction_length
+ //
+ // The amount to increment the line register is the line_base plus
+ // the result of the adjusted opcode modulo the line_range. That is:
+ //
+ // line increment = line_base + (adjusted opcode % line_range)
+
+ uint8_t adjust_opcode = opcode - Prologue.OpcodeBase;
+ uint64_t addr_offset =
+ (adjust_opcode / Prologue.LineRange) * Prologue.MinInstLength;
+ int32_t line_offset =
+ Prologue.LineBase + (adjust_opcode % Prologue.LineRange);
+ State.Row.Line += line_offset;
+ State.Row.Address += addr_offset;
+ State.appendRowToMatrix(*offset_ptr);
+ }
+ }
+
+ if (!State.Sequence.Empty) {
+ fprintf(stderr, "warning: last sequence in debug line table is not"
+ "terminated!\n");
+ }
+
+ // Sort all sequences so that address lookup will work faster.
+ if (!Sequences.empty()) {
+ std::sort(Sequences.begin(), Sequences.end(), Sequence::orderByLowPC);
+ // Note: actually, instruction address ranges of sequences should not
+ // overlap (in shared objects and executables). If they do, the address
+ // lookup would still work, though, but result would be ambiguous.
+ // We don't report warning in this case. For example,
+ // sometimes .so compiled from multiple object files contains a few
+ // rudimentary sequences for address ranges [0x0, 0xsomething).
+ }
+
+ return end_offset;
+}
+
+uint32_t
+DWARFDebugLine::LineTable::findRowInSeq(const DWARFDebugLine::Sequence &seq,
+ uint64_t address) const {
+ if (!seq.containsPC(address))
+ return UnknownRowIndex;
+ // Search for instruction address in the rows describing the sequence.
+ // Rows are stored in a vector, so we may use arithmetical operations with
+ // iterators.
+ DWARFDebugLine::Row row;
+ row.Address = address;
+ RowIter first_row = Rows.begin() + seq.FirstRowIndex;
+ RowIter last_row = Rows.begin() + seq.LastRowIndex;
+ LineTable::RowIter row_pos = std::lower_bound(
+ first_row, last_row, row, DWARFDebugLine::Row::orderByAddress);
+ if (row_pos == last_row) {
+ return seq.LastRowIndex - 1;
+ }
+ uint32_t index = seq.FirstRowIndex + (row_pos - first_row);
+ if (row_pos->Address > address) {
+ if (row_pos == first_row)
+ return UnknownRowIndex;
+ else
+ index--;
+ }
+ return index;
+}
+
+uint32_t DWARFDebugLine::LineTable::lookupAddress(uint64_t address) const {
+ if (Sequences.empty())
+ return UnknownRowIndex;
+ // First, find an instruction sequence containing the given address.
+ DWARFDebugLine::Sequence sequence;
+ sequence.LowPC = address;
+ SequenceIter first_seq = Sequences.begin();
+ SequenceIter last_seq = Sequences.end();
+ SequenceIter seq_pos = std::lower_bound(first_seq, last_seq, sequence,
+ DWARFDebugLine::Sequence::orderByLowPC);
+ DWARFDebugLine::Sequence found_seq;
+ if (seq_pos == last_seq) {
+ found_seq = Sequences.back();
+ } else if (seq_pos->LowPC == address) {
+ found_seq = *seq_pos;
+ } else {
+ if (seq_pos == first_seq)
+ return UnknownRowIndex;
+ found_seq = *(seq_pos - 1);
+ }
+ return findRowInSeq(found_seq, address);
+}
+
+bool DWARFDebugLine::LineTable::lookupAddressRange(
+ uint64_t address, uint64_t size, std::vector<uint32_t> &result) const {
+ if (Sequences.empty())
+ return false;
+ uint64_t end_addr = address + size;
+ // First, find an instruction sequence containing the given address.
+ DWARFDebugLine::Sequence sequence;
+ sequence.LowPC = address;
+ SequenceIter first_seq = Sequences.begin();
+ SequenceIter last_seq = Sequences.end();
+ SequenceIter seq_pos = std::lower_bound(first_seq, last_seq, sequence,
+ DWARFDebugLine::Sequence::orderByLowPC);
+ if (seq_pos == last_seq || seq_pos->LowPC != address) {
+ if (seq_pos == first_seq)
+ return false;
+ seq_pos--;
+ }
+ if (!seq_pos->containsPC(address))
+ return false;
+
+ SequenceIter start_pos = seq_pos;
+
+ // Add the rows from the first sequence to the vector, starting with the
+ // index we just calculated
+
+ while (seq_pos != last_seq && seq_pos->LowPC < end_addr) {
+ const DWARFDebugLine::Sequence &cur_seq = *seq_pos;
+ // For the first sequence, we need to find which row in the sequence is the
+ // first in our range.
+ uint32_t first_row_index = cur_seq.FirstRowIndex;
+ if (seq_pos == start_pos)
+ first_row_index = findRowInSeq(cur_seq, address);
+
+ // Figure out the last row in the range.
+ uint32_t last_row_index = findRowInSeq(cur_seq, end_addr - 1);
+ if (last_row_index == UnknownRowIndex)
+ last_row_index = cur_seq.LastRowIndex - 1;
+
+ assert(first_row_index != UnknownRowIndex);
+ assert(last_row_index != UnknownRowIndex);
+
+ for (uint32_t i = first_row_index; i <= last_row_index; ++i) {
+ result.push_back(i);
+ }
+
+ ++seq_pos;
+ }
+
+ return true;
+}
+
+bool
+DWARFDebugLine::LineTable::getFileNameByIndex(uint64_t FileIndex,
+ const char *CompDir,
+ FileLineInfoKind Kind,
+ std::string &Result) const {
+ if (FileIndex == 0 || FileIndex > Prologue.FileNames.size() ||
+ Kind == FileLineInfoKind::None)
+ return false;
+ const FileNameEntry &Entry = Prologue.FileNames[FileIndex - 1];
+ const char *FileName = Entry.Name;
+ if (Kind != FileLineInfoKind::AbsoluteFilePath ||
+ sys::path::is_absolute(FileName)) {
+ Result = FileName;
+ return true;
+ }
+
+ SmallString<16> FilePath;
+ uint64_t IncludeDirIndex = Entry.DirIdx;
+ const char *IncludeDir = "";
+ // Be defensive about the contents of Entry.
+ if (IncludeDirIndex > 0 &&
+ IncludeDirIndex <= Prologue.IncludeDirectories.size())
+ IncludeDir = Prologue.IncludeDirectories[IncludeDirIndex - 1];
+
+ // We may still need to append compilation directory of compile unit.
+ // We know that FileName is not absolute, the only way to have an
+ // absolute path at this point would be if IncludeDir is absolute.
+ if (CompDir && Kind == FileLineInfoKind::AbsoluteFilePath &&
+ sys::path::is_relative(IncludeDir))
+ sys::path::append(FilePath, CompDir);
+
+ // sys::path::append skips empty strings.
+ sys::path::append(FilePath, IncludeDir, FileName);
+ Result = FilePath.str();
+ return true;
+}
+
+bool
+DWARFDebugLine::LineTable::getFileLineInfoForAddress(uint64_t Address,
+ const char *CompDir,
+ FileLineInfoKind Kind,
+ DILineInfo &Result) const {
+ // Get the index of row we're looking for in the line table.
+ uint32_t RowIndex = lookupAddress(Address);
+ if (RowIndex == -1U)
+ return false;
+ // Take file number and line/column from the row.
+ const auto &Row = Rows[RowIndex];
+ if (!getFileNameByIndex(Row.File, CompDir, Kind, Result.FileName))
+ return false;
+ Result.Line = Row.Line;
+ Result.Column = Row.Column;
+ return true;
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
new file mode 100644
index 0000000..cd6fbef
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -0,0 +1,127 @@
+//===-- DWARFDebugLoc.cpp -------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void DWARFDebugLoc::dump(raw_ostream &OS) const {
+ for (const LocationList &L : Locations) {
+ OS << format("0x%8.8x: ", L.Offset);
+ const unsigned Indent = 12;
+ for (const Entry &E : L.Entries) {
+ if (&E != L.Entries.begin())
+ OS.indent(Indent);
+ OS << "Beginning address offset: " << format("0x%016" PRIx64, E.Begin)
+ << '\n';
+ OS.indent(Indent) << " Ending address offset: "
+ << format("0x%016" PRIx64, E.End) << '\n';
+ OS.indent(Indent) << " Location description: ";
+ for (unsigned char Loc : E.Loc) {
+ OS << format("%2.2x ", Loc);
+ }
+ OS << "\n\n";
+ }
+ }
+}
+
+void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) {
+ uint32_t Offset = 0;
+ while (data.isValidOffset(Offset+AddressSize-1)) {
+ Locations.resize(Locations.size() + 1);
+ LocationList &Loc = Locations.back();
+ Loc.Offset = Offset;
+ // 2.6.2 Location Lists
+ // A location list entry consists of:
+ while (true) {
+ Entry E;
+ RelocAddrMap::const_iterator AI = RelocMap.find(Offset);
+ // 1. A beginning address offset. ...
+ E.Begin = data.getUnsigned(&Offset, AddressSize);
+ if (AI != RelocMap.end())
+ E.Begin += AI->second.second;
+
+ AI = RelocMap.find(Offset);
+ // 2. An ending address offset. ...
+ E.End = data.getUnsigned(&Offset, AddressSize);
+ if (AI != RelocMap.end())
+ E.End += AI->second.second;
+
+ // The end of any given location list is marked by an end of list entry,
+ // which consists of a 0 for the beginning address offset and a 0 for the
+ // ending address offset.
+ if (E.Begin == 0 && E.End == 0)
+ break;
+
+ unsigned Bytes = data.getU16(&Offset);
+ // A single location description describing the location of the object...
+ StringRef str = data.getData().substr(Offset, Bytes);
+ Offset += Bytes;
+ E.Loc.append(str.begin(), str.end());
+ Loc.Entries.push_back(std::move(E));
+ }
+ }
+ if (data.isValidOffset(Offset))
+ llvm::errs() << "error: failed to consume entire .debug_loc section\n";
+}
+
+void DWARFDebugLocDWO::parse(DataExtractor data) {
+ uint32_t Offset = 0;
+ while (data.isValidOffset(Offset)) {
+ Locations.resize(Locations.size() + 1);
+ LocationList &Loc = Locations.back();
+ Loc.Offset = Offset;
+ dwarf::LocationListEntry Kind;
+ while ((Kind = static_cast<dwarf::LocationListEntry>(
+ data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list_entry) {
+
+ if (Kind != dwarf::DW_LLE_start_length_entry) {
+ llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
+ << " not implemented\n";
+ return;
+ }
+
+ Entry E;
+
+ E.Start = data.getULEB128(&Offset);
+ E.Length = data.getU32(&Offset);
+
+ unsigned Bytes = data.getU16(&Offset);
+ // A single location description describing the location of the object...
+ StringRef str = data.getData().substr(Offset, Bytes);
+ Offset += Bytes;
+ E.Loc.resize(str.size());
+ std::copy(str.begin(), str.end(), E.Loc.begin());
+
+ Loc.Entries.push_back(std::move(E));
+ }
+ }
+}
+
+void DWARFDebugLocDWO::dump(raw_ostream &OS) const {
+ for (const LocationList &L : Locations) {
+ OS << format("0x%8.8x: ", L.Offset);
+ const unsigned Indent = 12;
+ for (const Entry &E : L.Entries) {
+ if (&E != L.Entries.begin())
+ OS.indent(Indent);
+ OS << "Beginning address index: " << E.Start << '\n';
+ OS.indent(Indent) << " Length: " << E.Length << '\n';
+ OS.indent(Indent) << " Location description: ";
+ for (unsigned char Loc : E.Loc)
+ OS << format("%2.2x ", Loc);
+ OS << "\n\n";
+ }
+ }
+}
+
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp
new file mode 100644
index 0000000..b6555fa
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugMacro.cpp
@@ -0,0 +1,103 @@
+//===-- DWARFDebugMacro.cpp -----------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SyntaxHighlighting.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+using namespace dwarf;
+using namespace syntax;
+
+void DWARFDebugMacro::dump(raw_ostream &OS) const {
+ unsigned IndLevel = 0;
+ for (const Entry &E : Macros) {
+ // There should not be DW_MACINFO_end_file when IndLevel is Zero. However,
+ // this check handles the case of corrupted ".debug_macinfo" section.
+ if (IndLevel > 0)
+ IndLevel -= (E.Type == DW_MACINFO_end_file);
+ // Print indentation.
+ for (unsigned I = 0; I < IndLevel; I++)
+ OS << " ";
+ IndLevel += (E.Type == DW_MACINFO_start_file);
+
+ WithColor(OS, syntax::Macro).get() << MacinfoString(E.Type);
+ switch (E.Type) {
+ default:
+ // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
+ break;
+ case DW_MACINFO_define:
+ case DW_MACINFO_undef:
+ OS << " - lineno: " << E.Line;
+ OS << " macro: " << E.MacroStr;
+ break;
+ case DW_MACINFO_start_file:
+ OS << " - lineno: " << E.Line;
+ OS << " filenum: " << E.File;
+ break;
+ case DW_MACINFO_end_file:
+ break;
+ case DW_MACINFO_vendor_ext:
+ OS << " - constant: " << E.ExtConstant;
+ OS << " string: " << E.ExtStr;
+ break;
+ }
+ OS << "\n";
+ }
+}
+
+void DWARFDebugMacro::parse(DataExtractor data) {
+ uint32_t Offset = 0;
+ while (data.isValidOffset(Offset)) {
+ // A macro list entry consists of:
+ Entry E;
+ // 1. Macinfo type
+ E.Type = data.getULEB128(&Offset);
+
+ if (E.Type == 0) {
+ // Reached end of ".debug_macinfo" section.
+ return;
+ }
+
+ switch (E.Type) {
+ default:
+ // Got a corrupted ".debug_macinfo" section (invalid macinfo type).
+ // Push the corrupted entry to the list and halt parsing.
+ E.Type = DW_MACINFO_invalid;
+ Macros.push_back(E);
+ return;
+ case DW_MACINFO_define:
+ case DW_MACINFO_undef:
+ // 2. Source line
+ E.Line = data.getULEB128(&Offset);
+ // 3. Macro string
+ E.MacroStr = data.getCStr(&Offset);
+ break;
+ case DW_MACINFO_start_file:
+ // 2. Source line
+ E.Line = data.getULEB128(&Offset);
+ // 3. Source file id
+ E.File = data.getULEB128(&Offset);
+ break;
+ case DW_MACINFO_end_file:
+ break;
+ case DW_MACINFO_vendor_ext:
+ // 2. Vendor extension constant
+ E.ExtConstant = data.getULEB128(&Offset);
+ // 3. Vendor extension string
+ E.ExtStr = data.getCStr(&Offset);
+ break;
+ }
+
+ Macros.push_back(E);
+ }
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
new file mode 100644
index 0000000..d5df688
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp
@@ -0,0 +1,69 @@
+//===-- DWARFDebugRangesList.cpp ------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+void DWARFDebugRangeList::clear() {
+ Offset = -1U;
+ AddressSize = 0;
+ Entries.clear();
+}
+
+bool DWARFDebugRangeList::extract(DataExtractor data, uint32_t *offset_ptr) {
+ clear();
+ if (!data.isValidOffset(*offset_ptr))
+ return false;
+ AddressSize = data.getAddressSize();
+ if (AddressSize != 4 && AddressSize != 8)
+ return false;
+ Offset = *offset_ptr;
+ while (true) {
+ RangeListEntry entry;
+ uint32_t prev_offset = *offset_ptr;
+ entry.StartAddress = data.getAddress(offset_ptr);
+ entry.EndAddress = data.getAddress(offset_ptr);
+ // Check that both values were extracted correctly.
+ if (*offset_ptr != prev_offset + 2 * AddressSize) {
+ clear();
+ return false;
+ }
+ if (entry.isEndOfListEntry())
+ break;
+ Entries.push_back(entry);
+ }
+ return true;
+}
+
+void DWARFDebugRangeList::dump(raw_ostream &OS) const {
+ for (const RangeListEntry &RLE : Entries) {
+ const char *format_str = (AddressSize == 4
+ ? "%08x %08" PRIx64 " %08" PRIx64 "\n"
+ : "%08x %016" PRIx64 " %016" PRIx64 "\n");
+ OS << format(format_str, Offset, RLE.StartAddress, RLE.EndAddress);
+ }
+ OS << format("%08x <End of list>\n", Offset);
+}
+
+DWARFAddressRangesVector
+DWARFDebugRangeList::getAbsoluteRanges(uint64_t BaseAddress) const {
+ DWARFAddressRangesVector Res;
+ for (const RangeListEntry &RLE : Entries) {
+ if (RLE.isBaseAddressSelectionEntry(AddressSize)) {
+ BaseAddress = RLE.EndAddress;
+ } else {
+ Res.push_back(std::make_pair(BaseAddress + RLE.StartAddress,
+ BaseAddress + RLE.EndAddress));
+ }
+ }
+ return Res;
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
new file mode 100644
index 0000000..3dc5842
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFFormValue.cpp
@@ -0,0 +1,595 @@
+//===-- DWARFFormValue.cpp ------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SyntaxHighlighting.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/DebugInfo/DWARF/DWARFCompileUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cassert>
+#include <limits>
+using namespace llvm;
+using namespace dwarf;
+using namespace syntax;
+
+namespace {
+uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) {
+ // FIXME: Support DWARF64.
+ return (Version == 2) ? AddrSize : 4;
+}
+
+template <uint8_t AddrSize, uint8_t RefAddrSize>
+ArrayRef<uint8_t> makeFixedFormSizesArrayRef() {
+ static const uint8_t sizes[] = {
+ 0, // 0x00 unused
+ AddrSize, // 0x01 DW_FORM_addr
+ 0, // 0x02 unused
+ 0, // 0x03 DW_FORM_block2
+ 0, // 0x04 DW_FORM_block4
+ 2, // 0x05 DW_FORM_data2
+ 4, // 0x06 DW_FORM_data4
+ 8, // 0x07 DW_FORM_data8
+ 0, // 0x08 DW_FORM_string
+ 0, // 0x09 DW_FORM_block
+ 0, // 0x0a DW_FORM_block1
+ 1, // 0x0b DW_FORM_data1
+ 1, // 0x0c DW_FORM_flag
+ 0, // 0x0d DW_FORM_sdata
+ 4, // 0x0e DW_FORM_strp
+ 0, // 0x0f DW_FORM_udata
+ RefAddrSize, // 0x10 DW_FORM_ref_addr
+ 1, // 0x11 DW_FORM_ref1
+ 2, // 0x12 DW_FORM_ref2
+ 4, // 0x13 DW_FORM_ref4
+ 8, // 0x14 DW_FORM_ref8
+ 0, // 0x15 DW_FORM_ref_udata
+ 0, // 0x16 DW_FORM_indirect
+ 4, // 0x17 DW_FORM_sec_offset
+ 0, // 0x18 DW_FORM_exprloc
+ 0, // 0x19 DW_FORM_flag_present
+ };
+ return makeArrayRef(sizes);
+}
+}
+
+ArrayRef<uint8_t> DWARFFormValue::getFixedFormSizes(uint8_t AddrSize,
+ uint16_t Version) {
+ uint8_t RefAddrSize = getRefAddrSize(AddrSize, Version);
+ if (AddrSize == 4 && RefAddrSize == 4)
+ return makeFixedFormSizesArrayRef<4, 4>();
+ if (AddrSize == 4 && RefAddrSize == 8)
+ return makeFixedFormSizesArrayRef<4, 8>();
+ if (AddrSize == 8 && RefAddrSize == 4)
+ return makeFixedFormSizesArrayRef<8, 4>();
+ if (AddrSize == 8 && RefAddrSize == 8)
+ return makeFixedFormSizesArrayRef<8, 8>();
+ return None;
+}
+
+static const DWARFFormValue::FormClass DWARF4FormClasses[] = {
+ DWARFFormValue::FC_Unknown, // 0x0
+ DWARFFormValue::FC_Address, // 0x01 DW_FORM_addr
+ DWARFFormValue::FC_Unknown, // 0x02 unused
+ DWARFFormValue::FC_Block, // 0x03 DW_FORM_block2
+ DWARFFormValue::FC_Block, // 0x04 DW_FORM_block4
+ DWARFFormValue::FC_Constant, // 0x05 DW_FORM_data2
+ // --- These can be FC_SectionOffset in DWARF3 and below:
+ DWARFFormValue::FC_Constant, // 0x06 DW_FORM_data4
+ DWARFFormValue::FC_Constant, // 0x07 DW_FORM_data8
+ // ---
+ DWARFFormValue::FC_String, // 0x08 DW_FORM_string
+ DWARFFormValue::FC_Block, // 0x09 DW_FORM_block
+ DWARFFormValue::FC_Block, // 0x0a DW_FORM_block1
+ DWARFFormValue::FC_Constant, // 0x0b DW_FORM_data1
+ DWARFFormValue::FC_Flag, // 0x0c DW_FORM_flag
+ DWARFFormValue::FC_Constant, // 0x0d DW_FORM_sdata
+ DWARFFormValue::FC_String, // 0x0e DW_FORM_strp
+ DWARFFormValue::FC_Constant, // 0x0f DW_FORM_udata
+ DWARFFormValue::FC_Reference, // 0x10 DW_FORM_ref_addr
+ DWARFFormValue::FC_Reference, // 0x11 DW_FORM_ref1
+ DWARFFormValue::FC_Reference, // 0x12 DW_FORM_ref2
+ DWARFFormValue::FC_Reference, // 0x13 DW_FORM_ref4
+ DWARFFormValue::FC_Reference, // 0x14 DW_FORM_ref8
+ DWARFFormValue::FC_Reference, // 0x15 DW_FORM_ref_udata
+ DWARFFormValue::FC_Indirect, // 0x16 DW_FORM_indirect
+ DWARFFormValue::FC_SectionOffset, // 0x17 DW_FORM_sec_offset
+ DWARFFormValue::FC_Exprloc, // 0x18 DW_FORM_exprloc
+ DWARFFormValue::FC_Flag, // 0x19 DW_FORM_flag_present
+};
+
+bool DWARFFormValue::isFormClass(DWARFFormValue::FormClass FC) const {
+ // First, check DWARF4 form classes.
+ if (Form < makeArrayRef(DWARF4FormClasses).size() &&
+ DWARF4FormClasses[Form] == FC)
+ return true;
+ // Check more forms from DWARF4 and DWARF5 proposals.
+ switch (Form) {
+ case DW_FORM_ref_sig8:
+ case DW_FORM_GNU_ref_alt:
+ return (FC == FC_Reference);
+ case DW_FORM_GNU_addr_index:
+ return (FC == FC_Address);
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_strp_alt:
+ return (FC == FC_String);
+ }
+ // In DWARF3 DW_FORM_data4 and DW_FORM_data8 served also as a section offset.
+ // Don't check for DWARF version here, as some producers may still do this
+ // by mistake.
+ return (Form == DW_FORM_data4 || Form == DW_FORM_data8) &&
+ FC == FC_SectionOffset;
+}
+
+bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
+ const DWARFUnit *cu) {
+ bool indirect = false;
+ bool is_block = false;
+ Value.data = nullptr;
+ // Read the value for the form into value and follow and DW_FORM_indirect
+ // instances we run into
+ do {
+ indirect = false;
+ switch (Form) {
+ case DW_FORM_addr:
+ case DW_FORM_ref_addr: {
+ if (!cu)
+ return false;
+ uint16_t AddrSize =
+ (Form == DW_FORM_addr)
+ ? cu->getAddressByteSize()
+ : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
+ RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
+ if (AI != cu->getRelocMap()->end()) {
+ const std::pair<uint8_t, int64_t> &R = AI->second;
+ Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second;
+ } else
+ Value.uval = data.getUnsigned(offset_ptr, AddrSize);
+ break;
+ }
+ case DW_FORM_exprloc:
+ case DW_FORM_block:
+ Value.uval = data.getULEB128(offset_ptr);
+ is_block = true;
+ break;
+ case DW_FORM_block1:
+ Value.uval = data.getU8(offset_ptr);
+ is_block = true;
+ break;
+ case DW_FORM_block2:
+ Value.uval = data.getU16(offset_ptr);
+ is_block = true;
+ break;
+ case DW_FORM_block4:
+ Value.uval = data.getU32(offset_ptr);
+ is_block = true;
+ break;
+ case DW_FORM_data1:
+ case DW_FORM_ref1:
+ case DW_FORM_flag:
+ Value.uval = data.getU8(offset_ptr);
+ break;
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ Value.uval = data.getU16(offset_ptr);
+ break;
+ case DW_FORM_data4:
+ case DW_FORM_ref4: {
+ Value.uval = data.getU32(offset_ptr);
+ if (!cu)
+ break;
+ RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr-4);
+ if (AI != cu->getRelocMap()->end())
+ Value.uval += AI->second.second;
+ break;
+ }
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ Value.uval = data.getU64(offset_ptr);
+ break;
+ case DW_FORM_sdata:
+ Value.sval = data.getSLEB128(offset_ptr);
+ break;
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ Value.uval = data.getULEB128(offset_ptr);
+ break;
+ case DW_FORM_string:
+ Value.cstr = data.getCStr(offset_ptr);
+ break;
+ case DW_FORM_indirect:
+ Form = data.getULEB128(offset_ptr);
+ indirect = true;
+ break;
+ case DW_FORM_sec_offset:
+ case DW_FORM_strp:
+ case DW_FORM_GNU_ref_alt:
+ case DW_FORM_GNU_strp_alt: {
+ // FIXME: This is 64-bit for DWARF64.
+ Value.uval = data.getU32(offset_ptr);
+ if (!cu)
+ break;
+ RelocAddrMap::const_iterator AI =
+ cu->getRelocMap()->find(*offset_ptr - 4);
+ if (AI != cu->getRelocMap()->end())
+ Value.uval += AI->second.second;
+ break;
+ }
+ case DW_FORM_flag_present:
+ Value.uval = 1;
+ break;
+ case DW_FORM_ref_sig8:
+ Value.uval = data.getU64(offset_ptr);
+ break;
+ case DW_FORM_GNU_addr_index:
+ case DW_FORM_GNU_str_index:
+ Value.uval = data.getULEB128(offset_ptr);
+ break;
+ default:
+ return false;
+ }
+ } while (indirect);
+
+ if (is_block) {
+ StringRef str = data.getData().substr(*offset_ptr, Value.uval);
+ Value.data = nullptr;
+ if (!str.empty()) {
+ Value.data = reinterpret_cast<const uint8_t *>(str.data());
+ *offset_ptr += Value.uval;
+ }
+ }
+
+ return true;
+}
+
+bool
+DWARFFormValue::skipValue(DataExtractor debug_info_data, uint32_t* offset_ptr,
+ const DWARFUnit *cu) const {
+ return DWARFFormValue::skipValue(Form, debug_info_data, offset_ptr, cu);
+}
+
+bool
+DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
+ uint32_t *offset_ptr, const DWARFUnit *cu) {
+ return skipValue(form, debug_info_data, offset_ptr, cu->getVersion(),
+ cu->getAddressByteSize());
+}
+bool DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
+ uint32_t *offset_ptr, uint16_t Version,
+ uint8_t AddrSize) {
+ bool indirect = false;
+ do {
+ switch (form) {
+ // Blocks if inlined data that have a length field and the data bytes
+ // inlined in the .debug_info
+ case DW_FORM_exprloc:
+ case DW_FORM_block: {
+ uint64_t size = debug_info_data.getULEB128(offset_ptr);
+ *offset_ptr += size;
+ return true;
+ }
+ case DW_FORM_block1: {
+ uint8_t size = debug_info_data.getU8(offset_ptr);
+ *offset_ptr += size;
+ return true;
+ }
+ case DW_FORM_block2: {
+ uint16_t size = debug_info_data.getU16(offset_ptr);
+ *offset_ptr += size;
+ return true;
+ }
+ case DW_FORM_block4: {
+ uint32_t size = debug_info_data.getU32(offset_ptr);
+ *offset_ptr += size;
+ return true;
+ }
+
+ // Inlined NULL terminated C-strings
+ case DW_FORM_string:
+ debug_info_data.getCStr(offset_ptr);
+ return true;
+
+ // Compile unit address sized values
+ case DW_FORM_addr:
+ *offset_ptr += AddrSize;
+ return true;
+ case DW_FORM_ref_addr:
+ *offset_ptr += getRefAddrSize(AddrSize, Version);
+ return true;
+
+ // 0 byte values - implied from the form.
+ case DW_FORM_flag_present:
+ return true;
+
+ // 1 byte values
+ case DW_FORM_data1:
+ case DW_FORM_flag:
+ case DW_FORM_ref1:
+ *offset_ptr += 1;
+ return true;
+
+ // 2 byte values
+ case DW_FORM_data2:
+ case DW_FORM_ref2:
+ *offset_ptr += 2;
+ return true;
+
+ // 4 byte values
+ case DW_FORM_data4:
+ case DW_FORM_ref4:
+ *offset_ptr += 4;
+ return true;
+
+ // 8 byte values
+ case DW_FORM_data8:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_sig8:
+ *offset_ptr += 8;
+ return true;
+
+ // signed or unsigned LEB 128 values
+ // case DW_FORM_APPLE_db_str:
+ case DW_FORM_sdata:
+ case DW_FORM_udata:
+ case DW_FORM_ref_udata:
+ case DW_FORM_GNU_str_index:
+ case DW_FORM_GNU_addr_index:
+ debug_info_data.getULEB128(offset_ptr);
+ return true;
+
+ case DW_FORM_indirect:
+ indirect = true;
+ form = debug_info_data.getULEB128(offset_ptr);
+ break;
+
+ // FIXME: 4 for DWARF32, 8 for DWARF64.
+ case DW_FORM_sec_offset:
+ case DW_FORM_strp:
+ case DW_FORM_GNU_ref_alt:
+ case DW_FORM_GNU_strp_alt:
+ *offset_ptr += 4;
+ return true;
+
+ default:
+ return false;
+ }
+ } while (indirect);
+ return true;
+}
+
+void
+DWARFFormValue::dump(raw_ostream &OS, const DWARFUnit *cu) const {
+ uint64_t uvalue = Value.uval;
+ bool cu_relative_offset = false;
+
+ switch (Form) {
+ case DW_FORM_addr: OS << format("0x%016" PRIx64, uvalue); break;
+ case DW_FORM_GNU_addr_index: {
+ OS << format(" indexed (%8.8x) address = ", (uint32_t)uvalue);
+ uint64_t Address;
+ if (cu->getAddrOffsetSectionItem(uvalue, Address))
+ OS << format("0x%016" PRIx64, Address);
+ else
+ OS << "<no .debug_addr section>";
+ break;
+ }
+ case DW_FORM_flag_present: OS << "true"; break;
+ case DW_FORM_flag:
+ case DW_FORM_data1: OS << format("0x%02x", (uint8_t)uvalue); break;
+ case DW_FORM_data2: OS << format("0x%04x", (uint16_t)uvalue); break;
+ case DW_FORM_data4: OS << format("0x%08x", (uint32_t)uvalue); break;
+ case DW_FORM_ref_sig8:
+ case DW_FORM_data8: OS << format("0x%016" PRIx64, uvalue); break;
+ case DW_FORM_string:
+ OS << '"';
+ OS.write_escaped(Value.cstr);
+ OS << '"';
+ break;
+ case DW_FORM_exprloc:
+ case DW_FORM_block:
+ case DW_FORM_block1:
+ case DW_FORM_block2:
+ case DW_FORM_block4:
+ if (uvalue > 0) {
+ switch (Form) {
+ case DW_FORM_exprloc:
+ case DW_FORM_block: OS << format("<0x%" PRIx64 "> ", uvalue); break;
+ case DW_FORM_block1: OS << format("<0x%2.2x> ", (uint8_t)uvalue); break;
+ case DW_FORM_block2: OS << format("<0x%4.4x> ", (uint16_t)uvalue); break;
+ case DW_FORM_block4: OS << format("<0x%8.8x> ", (uint32_t)uvalue); break;
+ default: break;
+ }
+
+ const uint8_t* data_ptr = Value.data;
+ if (data_ptr) {
+ // uvalue contains size of block
+ const uint8_t* end_data_ptr = data_ptr + uvalue;
+ while (data_ptr < end_data_ptr) {
+ OS << format("%2.2x ", *data_ptr);
+ ++data_ptr;
+ }
+ }
+ else
+ OS << "NULL";
+ }
+ break;
+
+ case DW_FORM_sdata: OS << Value.sval; break;
+ case DW_FORM_udata: OS << Value.uval; break;
+ case DW_FORM_strp: {
+ OS << format(" .debug_str[0x%8.8x] = ", (uint32_t)uvalue);
+ dumpString(OS, cu);
+ break;
+ }
+ case DW_FORM_GNU_str_index: {
+ OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue);
+ dumpString(OS, cu);
+ break;
+ }
+ case DW_FORM_GNU_strp_alt: {
+ OS << format("alt indirect string, offset: 0x%" PRIx64 "", uvalue);
+ dumpString(OS, cu);
+ break;
+ }
+ case DW_FORM_ref_addr:
+ OS << format("0x%016" PRIx64, uvalue);
+ break;
+ case DW_FORM_ref1:
+ cu_relative_offset = true;
+ OS << format("cu + 0x%2.2x", (uint8_t)uvalue);
+ break;
+ case DW_FORM_ref2:
+ cu_relative_offset = true;
+ OS << format("cu + 0x%4.4x", (uint16_t)uvalue);
+ break;
+ case DW_FORM_ref4:
+ cu_relative_offset = true;
+ OS << format("cu + 0x%4.4x", (uint32_t)uvalue);
+ break;
+ case DW_FORM_ref8:
+ cu_relative_offset = true;
+ OS << format("cu + 0x%8.8" PRIx64, uvalue);
+ break;
+ case DW_FORM_ref_udata:
+ cu_relative_offset = true;
+ OS << format("cu + 0x%" PRIx64, uvalue);
+ break;
+ case DW_FORM_GNU_ref_alt:
+ OS << format("<alt 0x%" PRIx64 ">", uvalue);
+ break;
+
+ // All DW_FORM_indirect attributes should be resolved prior to calling
+ // this function
+ case DW_FORM_indirect:
+ OS << "DW_FORM_indirect";
+ break;
+
+ // Should be formatted to 64-bit for DWARF64.
+ case DW_FORM_sec_offset:
+ OS << format("0x%08x", (uint32_t)uvalue);
+ break;
+
+ default:
+ OS << format("DW_FORM(0x%4.4x)", Form);
+ break;
+ }
+
+ if (cu_relative_offset) {
+ OS << " => {";
+ WithColor(OS, syntax::Address).get()
+ << format("0x%8.8" PRIx64, uvalue + (cu ? cu->getOffset() : 0));
+ OS << "}";
+ }
+}
+
+void DWARFFormValue::dumpString(raw_ostream &OS, const DWARFUnit *U) const {
+ Optional<const char *> DbgStr = getAsCString(U);
+ if (DbgStr.hasValue()) {
+ raw_ostream &COS = WithColor(OS, syntax::String);
+ COS << '"';
+ COS.write_escaped(DbgStr.getValue());
+ COS << '"';
+ }
+}
+
+Optional<const char *> DWARFFormValue::getAsCString(const DWARFUnit *U) const {
+ if (!isFormClass(FC_String))
+ return None;
+ if (Form == DW_FORM_string)
+ return Value.cstr;
+ // FIXME: Add support for DW_FORM_GNU_strp_alt
+ if (Form == DW_FORM_GNU_strp_alt || U == nullptr)
+ return None;
+ uint32_t Offset = Value.uval;
+ if (Form == DW_FORM_GNU_str_index) {
+ uint32_t StrOffset;
+ if (!U->getStringOffsetSectionItem(Offset, StrOffset))
+ return None;
+ Offset = StrOffset;
+ }
+ if (const char *Str = U->getStringExtractor().getCStr(&Offset)) {
+ return Str;
+ }
+ return None;
+}
+
+Optional<uint64_t> DWARFFormValue::getAsAddress(const DWARFUnit *U) const {
+ if (!isFormClass(FC_Address))
+ return None;
+ if (Form == DW_FORM_GNU_addr_index) {
+ uint32_t Index = Value.uval;
+ uint64_t Result;
+ if (!U || !U->getAddrOffsetSectionItem(Index, Result))
+ return None;
+ return Result;
+ }
+ return Value.uval;
+}
+
+Optional<uint64_t> DWARFFormValue::getAsReference(const DWARFUnit *U) const {
+ if (!isFormClass(FC_Reference))
+ return None;
+ switch (Form) {
+ case DW_FORM_ref1:
+ case DW_FORM_ref2:
+ case DW_FORM_ref4:
+ case DW_FORM_ref8:
+ case DW_FORM_ref_udata:
+ if (!U)
+ return None;
+ return Value.uval + U->getOffset();
+ case DW_FORM_ref_addr:
+ return Value.uval;
+ // FIXME: Add proper support for DW_FORM_ref_sig8 and DW_FORM_GNU_ref_alt.
+ default:
+ return None;
+ }
+}
+
+Optional<uint64_t> DWARFFormValue::getAsSectionOffset() const {
+ if (!isFormClass(FC_SectionOffset))
+ return None;
+ return Value.uval;
+}
+
+Optional<uint64_t> DWARFFormValue::getAsUnsignedConstant() const {
+ if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag))
+ || Form == DW_FORM_sdata)
+ return None;
+ return Value.uval;
+}
+
+Optional<int64_t> DWARFFormValue::getAsSignedConstant() const {
+ if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) ||
+ (Form == DW_FORM_udata && uint64_t(std::numeric_limits<int64_t>::max()) < Value.uval))
+ return None;
+ switch (Form) {
+ case DW_FORM_data4:
+ return int32_t(Value.uval);
+ case DW_FORM_data2:
+ return int16_t(Value.uval);
+ case DW_FORM_data1:
+ return int8_t(Value.uval);
+ case DW_FORM_sdata:
+ case DW_FORM_data8:
+ default:
+ return Value.sval;
+ }
+}
+
+Optional<ArrayRef<uint8_t>> DWARFFormValue::getAsBlock() const {
+ if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc))
+ return None;
+ return makeArrayRef(Value.data, Value.uval);
+}
+
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
new file mode 100644
index 0000000..766e8ac
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp
@@ -0,0 +1,40 @@
+//===-- DWARFTypeUnit.cpp -------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+bool DWARFTypeUnit::extractImpl(DataExtractor debug_info,
+ uint32_t *offset_ptr) {
+ if (!DWARFUnit::extractImpl(debug_info, offset_ptr))
+ return false;
+ TypeHash = debug_info.getU64(offset_ptr);
+ TypeOffset = debug_info.getU32(offset_ptr);
+ return TypeOffset < getLength();
+}
+
+void DWARFTypeUnit::dump(raw_ostream &OS) {
+ OS << format("0x%08x", getOffset()) << ": Type Unit:"
+ << " length = " << format("0x%08x", getLength())
+ << " version = " << format("0x%04x", getVersion())
+ << " abbr_offset = " << format("0x%04x", getAbbreviations()->getOffset())
+ << " addr_size = " << format("0x%02x", getAddressByteSize())
+ << " type_signature = " << format("0x%16" PRIx64, TypeHash)
+ << " type_offset = " << format("0x%04x", TypeOffset)
+ << " (next unit at " << format("0x%08x", getNextUnitOffset())
+ << ")\n";
+
+ if (const DWARFDebugInfoEntryMinimal *TU = getUnitDIE(false))
+ TU->dump(OS, this, -1U);
+ else
+ OS << "<type unit can't be parsed!>\n\n";
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
new file mode 100644
index 0000000..92ca2d4
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp
@@ -0,0 +1,405 @@
+//===-- DWARFUnit.cpp -----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Path.h"
+#include <cstdio>
+
+namespace llvm {
+using namespace dwarf;
+
+void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) {
+ parseImpl(C, Section, C.getDebugAbbrev(), C.getRangeSection(),
+ C.getStringSection(), StringRef(), C.getAddrSection(),
+ C.getLineSection().Data, C.isLittleEndian());
+}
+
+void DWARFUnitSectionBase::parseDWO(DWARFContext &C,
+ const DWARFSection &DWOSection,
+ DWARFUnitIndex *Index) {
+ parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(),
+ C.getStringDWOSection(), C.getStringOffsetDWOSection(),
+ C.getAddrSection(), C.getLineDWOSection().Data, C.isLittleEndian());
+}
+
+DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section,
+ const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS,
+ StringRef SOS, StringRef AOS, StringRef LS, bool LE,
+ const DWARFUnitSectionBase &UnitSection,
+ const DWARFUnitIndex::Entry *IndexEntry)
+ : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS),
+ LineSection(LS), StringSection(SS), StringOffsetSection([&]() {
+ if (IndexEntry)
+ if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS))
+ return SOS.slice(C->Offset, C->Offset + C->Length);
+ return SOS;
+ }()),
+ AddrOffsetSection(AOS), isLittleEndian(LE), UnitSection(UnitSection),
+ IndexEntry(IndexEntry) {
+ clear();
+}
+
+DWARFUnit::~DWARFUnit() {
+}
+
+bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index,
+ uint64_t &Result) const {
+ uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize;
+ if (AddrOffsetSection.size() < Offset + AddrSize)
+ return false;
+ DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize);
+ Result = DA.getAddress(&Offset);
+ return true;
+}
+
+bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index,
+ uint32_t &Result) const {
+ // FIXME: string offset section entries are 8-byte for DWARF64.
+ const uint32_t ItemSize = 4;
+ uint32_t Offset = Index * ItemSize;
+ if (StringOffsetSection.size() < Offset + ItemSize)
+ return false;
+ DataExtractor DA(StringOffsetSection, isLittleEndian, 0);
+ Result = DA.getU32(&Offset);
+ return true;
+}
+
+bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
+ Length = debug_info.getU32(offset_ptr);
+ Version = debug_info.getU16(offset_ptr);
+ uint64_t AbbrOffset = debug_info.getU32(offset_ptr);
+ if (IndexEntry) {
+ if (AbbrOffset)
+ return false;
+ auto *UnitContrib = IndexEntry->getOffset();
+ if (!UnitContrib || UnitContrib->Length != (Length + 4))
+ return false;
+ auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV);
+ if (!AbbrEntry)
+ return false;
+ AbbrOffset = AbbrEntry->Offset;
+ }
+ AddrSize = debug_info.getU8(offset_ptr);
+
+ bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
+ bool VersionOK = DWARFContext::isSupportedVersion(Version);
+ bool AddrSizeOK = AddrSize == 4 || AddrSize == 8;
+
+ if (!LengthOK || !VersionOK || !AddrSizeOK)
+ return false;
+
+ Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
+ return Abbrevs != nullptr;
+}
+
+bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
+ clear();
+
+ Offset = *offset_ptr;
+
+ if (debug_info.isValidOffset(*offset_ptr)) {
+ if (extractImpl(debug_info, offset_ptr))
+ return true;
+
+ // reset the offset to where we tried to parse from if anything went wrong
+ *offset_ptr = Offset;
+ }
+
+ return false;
+}
+
+bool DWARFUnit::extractRangeList(uint32_t RangeListOffset,
+ DWARFDebugRangeList &RangeList) const {
+ // Require that compile unit is extracted.
+ assert(DieArray.size() > 0);
+ DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize);
+ uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset;
+ return RangeList.extract(RangesData, &ActualRangeListOffset);
+}
+
+void DWARFUnit::clear() {
+ Offset = 0;
+ Length = 0;
+ Version = 0;
+ Abbrevs = nullptr;
+ AddrSize = 0;
+ BaseAddr = 0;
+ RangeSectionBase = 0;
+ AddrOffsetSectionBase = 0;
+ clearDIEs(false);
+ DWO.reset();
+}
+
+const char *DWARFUnit::getCompilationDir() {
+ extractDIEsIfNeeded(true);
+ if (DieArray.empty())
+ return nullptr;
+ return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
+}
+
+uint64_t DWARFUnit::getDWOId() {
+ extractDIEsIfNeeded(true);
+ const uint64_t FailValue = -1ULL;
+ if (DieArray.empty())
+ return FailValue;
+ return DieArray[0]
+ .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue);
+}
+
+void DWARFUnit::setDIERelations() {
+ if (DieArray.size() <= 1)
+ return;
+
+ std::vector<DWARFDebugInfoEntryMinimal *> ParentChain;
+ DWARFDebugInfoEntryMinimal *SiblingChain = nullptr;
+ for (auto &DIE : DieArray) {
+ if (SiblingChain) {
+ SiblingChain->setSibling(&DIE);
+ }
+ if (const DWARFAbbreviationDeclaration *AbbrDecl =
+ DIE.getAbbreviationDeclarationPtr()) {
+ // Normal DIE.
+ if (AbbrDecl->hasChildren()) {
+ ParentChain.push_back(&DIE);
+ SiblingChain = nullptr;
+ } else {
+ SiblingChain = &DIE;
+ }
+ } else {
+ // NULL entry terminates the sibling chain.
+ SiblingChain = ParentChain.back();
+ ParentChain.pop_back();
+ }
+ }
+ assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]);
+ assert(ParentChain.empty());
+}
+
+void DWARFUnit::extractDIEsToVector(
+ bool AppendCUDie, bool AppendNonCUDies,
+ std::vector<DWARFDebugInfoEntryMinimal> &Dies) const {
+ if (!AppendCUDie && !AppendNonCUDies)
+ return;
+
+ // Set the offset to that of the first DIE and calculate the start of the
+ // next compilation unit header.
+ uint32_t DIEOffset = Offset + getHeaderSize();
+ uint32_t NextCUOffset = getNextUnitOffset();
+ DWARFDebugInfoEntryMinimal DIE;
+ uint32_t Depth = 0;
+ bool IsCUDie = true;
+
+ while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) {
+ if (IsCUDie) {
+ if (AppendCUDie)
+ Dies.push_back(DIE);
+ if (!AppendNonCUDies)
+ break;
+ // The average bytes per DIE entry has been seen to be
+ // around 14-20 so let's pre-reserve the needed memory for
+ // our DIE entries accordingly.
+ Dies.reserve(Dies.size() + getDebugInfoSize() / 14);
+ IsCUDie = false;
+ } else {
+ Dies.push_back(DIE);
+ }
+
+ if (const DWARFAbbreviationDeclaration *AbbrDecl =
+ DIE.getAbbreviationDeclarationPtr()) {
+ // Normal DIE
+ if (AbbrDecl->hasChildren())
+ ++Depth;
+ } else {
+ // NULL DIE.
+ if (Depth > 0)
+ --Depth;
+ if (Depth == 0)
+ break; // We are done with this compile unit!
+ }
+ }
+
+ // Give a little bit of info if we encounter corrupt DWARF (our offset
+ // should always terminate at or before the start of the next compilation
+ // unit header).
+ if (DIEOffset > NextCUOffset)
+ fprintf(stderr, "warning: DWARF compile unit extends beyond its "
+ "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset);
+}
+
+size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) {
+ if ((CUDieOnly && DieArray.size() > 0) ||
+ DieArray.size() > 1)
+ return 0; // Already parsed.
+
+ bool HasCUDie = DieArray.size() > 0;
+ extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray);
+
+ if (DieArray.empty())
+ return 0;
+
+ // If CU DIE was just parsed, copy several attribute values from it.
+ if (!HasCUDie) {
+ uint64_t BaseAddr =
+ DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL);
+ if (BaseAddr == -1ULL)
+ BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0);
+ setBaseAddress(BaseAddr);
+ AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
+ this, DW_AT_GNU_addr_base, 0);
+ RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset(
+ this, DW_AT_ranges_base, 0);
+ // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for
+ // skeleton CU DIE, so that DWARF users not aware of it are not broken.
+ }
+
+ setDIERelations();
+ return DieArray.size();
+}
+
+DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath)
+ : DWOFile(), DWOContext(), DWOU(nullptr) {
+ auto Obj = object::ObjectFile::createObjectFile(DWOPath);
+ if (!Obj)
+ return;
+ DWOFile = std::move(Obj.get());
+ DWOContext.reset(
+ cast<DWARFContext>(new DWARFContextInMemory(*DWOFile.getBinary())));
+ if (DWOContext->getNumDWOCompileUnits() > 0)
+ DWOU = DWOContext->getDWOCompileUnitAtIndex(0);
+}
+
+bool DWARFUnit::parseDWO() {
+ if (DWO.get())
+ return false;
+ extractDIEsIfNeeded(true);
+ if (DieArray.empty())
+ return false;
+ const char *DWOFileName =
+ DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr);
+ if (!DWOFileName)
+ return false;
+ const char *CompilationDir =
+ DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr);
+ SmallString<16> AbsolutePath;
+ if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) {
+ sys::path::append(AbsolutePath, CompilationDir);
+ }
+ sys::path::append(AbsolutePath, DWOFileName);
+ DWO = llvm::make_unique<DWOHolder>(AbsolutePath);
+ DWARFUnit *DWOCU = DWO->getUnit();
+ // Verify that compile unit in .dwo file is valid.
+ if (!DWOCU || DWOCU->getDWOId() != getDWOId()) {
+ DWO.reset();
+ return false;
+ }
+ // Share .debug_addr and .debug_ranges section with compile unit in .dwo
+ DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase);
+ uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0);
+ DWOCU->setRangesSection(RangeSection, DWORangesBase);
+ return true;
+}
+
+void DWARFUnit::clearDIEs(bool KeepCUDie) {
+ if (DieArray.size() > (unsigned)KeepCUDie) {
+ // std::vectors never get any smaller when resized to a smaller size,
+ // or when clear() or erase() are called, the size will report that it
+ // is smaller, but the memory allocated remains intact (call capacity()
+ // to see this). So we need to create a temporary vector and swap the
+ // contents which will cause just the internal pointers to be swapped
+ // so that when temporary vector goes out of scope, it will destroy the
+ // contents.
+ std::vector<DWARFDebugInfoEntryMinimal> TmpArray;
+ DieArray.swap(TmpArray);
+ // Save at least the compile unit DIE
+ if (KeepCUDie)
+ DieArray.push_back(TmpArray.front());
+ }
+}
+
+void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) {
+ const auto *U = getUnitDIE();
+ if (U == nullptr)
+ return;
+ // First, check if unit DIE describes address ranges for the whole unit.
+ const auto &CUDIERanges = U->getAddressRanges(this);
+ if (!CUDIERanges.empty()) {
+ CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end());
+ return;
+ }
+
+ // This function is usually called if there in no .debug_aranges section
+ // in order to produce a compile unit level set of address ranges that
+ // is accurate. If the DIEs weren't parsed, then we don't want all dies for
+ // all compile units to stay loaded when they weren't needed. So we can end
+ // up parsing the DWARF and then throwing them all away to keep memory usage
+ // down.
+ const bool ClearDIEs = extractDIEsIfNeeded(false) > 1;
+ DieArray[0].collectChildrenAddressRanges(this, CURanges);
+
+ // Collect address ranges from DIEs in .dwo if necessary.
+ bool DWOCreated = parseDWO();
+ if (DWO.get())
+ DWO->getUnit()->collectAddressRanges(CURanges);
+ if (DWOCreated)
+ DWO.reset();
+
+ // Keep memory down by clearing DIEs if this generate function
+ // caused them to be parsed.
+ if (ClearDIEs)
+ clearDIEs(true);
+}
+
+const DWARFDebugInfoEntryMinimal *
+DWARFUnit::getSubprogramForAddress(uint64_t Address) {
+ extractDIEsIfNeeded(false);
+ for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) {
+ if (DIE.isSubprogramDIE() &&
+ DIE.addressRangeContainsAddress(this, Address)) {
+ return &DIE;
+ }
+ }
+ return nullptr;
+}
+
+DWARFDebugInfoEntryInlinedChain
+DWARFUnit::getInlinedChainForAddress(uint64_t Address) {
+ // First, find a subprogram that contains the given address (the root
+ // of inlined chain).
+ const DWARFUnit *ChainCU = nullptr;
+ const DWARFDebugInfoEntryMinimal *SubprogramDIE =
+ getSubprogramForAddress(Address);
+ if (SubprogramDIE) {
+ ChainCU = this;
+ } else {
+ // Try to look for subprogram DIEs in the DWO file.
+ parseDWO();
+ if (DWO.get()) {
+ SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
+ if (SubprogramDIE)
+ ChainCU = DWO->getUnit();
+ }
+ }
+
+ // Get inlined chain rooted at this subprogram DIE.
+ if (!SubprogramDIE)
+ return DWARFDebugInfoEntryInlinedChain();
+ return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address);
+}
+
+const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context,
+ DWARFSectionKind Kind) {
+ if (Kind == DW_SECT_INFO)
+ return Context.getCUIndex();
+ assert(Kind == DW_SECT_TYPES);
+ return Context.getTUIndex();
+}
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp b/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
new file mode 100644
index 0000000..96b3169
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/DWARFUnitIndex.cpp
@@ -0,0 +1,168 @@
+//===-- DWARFUnitIndex.cpp ------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ErrorHandling.h"
+
+namespace llvm {
+
+bool DWARFUnitIndex::Header::parse(DataExtractor IndexData,
+ uint32_t *OffsetPtr) {
+ if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
+ return false;
+ Version = IndexData.getU32(OffsetPtr);
+ NumColumns = IndexData.getU32(OffsetPtr);
+ NumUnits = IndexData.getU32(OffsetPtr);
+ NumBuckets = IndexData.getU32(OffsetPtr);
+ return Version <= 2;
+}
+
+void DWARFUnitIndex::Header::dump(raw_ostream &OS) const {
+ OS << format("version = %u slots = %u\n\n", Version, NumBuckets);
+}
+
+bool DWARFUnitIndex::parse(DataExtractor IndexData) {
+ bool b = parseImpl(IndexData);
+ if (!b) {
+ // Make sure we don't try to dump anything
+ Header.NumBuckets = 0;
+ // Release any partially initialized data.
+ ColumnKinds.reset();
+ Rows.reset();
+ }
+ return b;
+}
+
+bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
+ uint32_t Offset = 0;
+ if (!Header.parse(IndexData, &Offset))
+ return false;
+
+ if (!IndexData.isValidOffsetForDataOfSize(
+ Offset, Header.NumBuckets * (8 + 4) +
+ (2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
+ return false;
+
+ Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
+ auto Contribs =
+ llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
+ ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);
+
+ // Read Hash Table of Signatures
+ for (unsigned i = 0; i != Header.NumBuckets; ++i)
+ Rows[i].Signature = IndexData.getU64(&Offset);
+
+ // Read Parallel Table of Indexes
+ for (unsigned i = 0; i != Header.NumBuckets; ++i) {
+ auto Index = IndexData.getU32(&Offset);
+ if (!Index)
+ continue;
+ Rows[i].Index = this;
+ Rows[i].Contributions =
+ llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
+ Contribs[Index - 1] = Rows[i].Contributions.get();
+ }
+
+ // Read the Column Headers
+ for (unsigned i = 0; i != Header.NumColumns; ++i) {
+ ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
+ if (ColumnKinds[i] == InfoColumnKind) {
+ if (InfoColumn != -1)
+ return false;
+ InfoColumn = i;
+ }
+ }
+
+ if (InfoColumn == -1)
+ return false;
+
+ // Read Table of Section Offsets
+ for (unsigned i = 0; i != Header.NumUnits; ++i) {
+ auto *Contrib = Contribs[i];
+ for (unsigned i = 0; i != Header.NumColumns; ++i)
+ Contrib[i].Offset = IndexData.getU32(&Offset);
+ }
+
+ // Read Table of Section Sizes
+ for (unsigned i = 0; i != Header.NumUnits; ++i) {
+ auto *Contrib = Contribs[i];
+ for (unsigned i = 0; i != Header.NumColumns; ++i)
+ Contrib[i].Length = IndexData.getU32(&Offset);
+ }
+
+ return true;
+}
+
+StringRef DWARFUnitIndex::getColumnHeader(DWARFSectionKind DS) {
+#define CASE(DS) \
+ case DW_SECT_##DS: \
+ return #DS;
+ switch (DS) {
+ CASE(INFO);
+ CASE(TYPES);
+ CASE(ABBREV);
+ CASE(LINE);
+ CASE(LOC);
+ CASE(STR_OFFSETS);
+ CASE(MACINFO);
+ CASE(MACRO);
+ }
+ llvm_unreachable("unknown DWARFSectionKind");
+}
+
+void DWARFUnitIndex::dump(raw_ostream &OS) const {
+ if (!Header.NumBuckets)
+ return;
+
+ Header.dump(OS);
+ OS << "Index Signature ";
+ for (unsigned i = 0; i != Header.NumColumns; ++i)
+ OS << ' ' << left_justify(getColumnHeader(ColumnKinds[i]), 24);
+ OS << "\n----- ------------------";
+ for (unsigned i = 0; i != Header.NumColumns; ++i)
+ OS << " ------------------------";
+ OS << '\n';
+ for (unsigned i = 0; i != Header.NumBuckets; ++i) {
+ auto &Row = Rows[i];
+ if (auto *Contribs = Row.Contributions.get()) {
+ OS << format("%5u 0x%016" PRIx64 " ", i + 1, Row.Signature);
+ for (unsigned i = 0; i != Header.NumColumns; ++i) {
+ auto &Contrib = Contribs[i];
+ OS << format("[0x%08x, 0x%08x) ", Contrib.Offset,
+ Contrib.Offset + Contrib.Length);
+ }
+ OS << '\n';
+ }
+ }
+}
+
+const DWARFUnitIndex::Entry::SectionContribution *
+DWARFUnitIndex::Entry::getOffset(DWARFSectionKind Sec) const {
+ uint32_t i = 0;
+ for (; i != Index->Header.NumColumns; ++i)
+ if (Index->ColumnKinds[i] == Sec)
+ return &Contributions[i];
+ return nullptr;
+}
+const DWARFUnitIndex::Entry::SectionContribution *
+DWARFUnitIndex::Entry::getOffset() const {
+ return &Contributions[Index->InfoColumn];
+}
+
+const DWARFUnitIndex::Entry *
+DWARFUnitIndex::getFromOffset(uint32_t Offset) const {
+ for (uint32_t i = 0; i != Header.NumBuckets; ++i)
+ if (const auto &Contribs = Rows[i].Contributions)
+ if (Contribs[InfoColumn].Offset == Offset)
+ return &Rows[i];
+ return nullptr;
+}
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp b/contrib/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp
new file mode 100644
index 0000000..4f561d0
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp
@@ -0,0 +1,38 @@
+//===-- SyntaxHighlighting.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SyntaxHighlighting.h"
+#include "llvm/Support/CommandLine.h"
+using namespace llvm;
+using namespace dwarf;
+using namespace syntax;
+
+static cl::opt<cl::boolOrDefault>
+ UseColor("color",
+ cl::desc("use colored syntax highlighting (default=autodetect)"),
+ cl::init(cl::BOU_UNSET));
+
+WithColor::WithColor(llvm::raw_ostream &OS, enum HighlightColor Type) : OS(OS) {
+ // Detect color from terminal type unless the user passed the --color option.
+ if (UseColor == cl::BOU_UNSET ? OS.has_colors() : UseColor == cl::BOU_TRUE) {
+ switch (Type) {
+ case Address: OS.changeColor(llvm::raw_ostream::YELLOW); break;
+ case String: OS.changeColor(llvm::raw_ostream::GREEN); break;
+ case Tag: OS.changeColor(llvm::raw_ostream::BLUE); break;
+ case Attribute: OS.changeColor(llvm::raw_ostream::CYAN); break;
+ case Enumerator: OS.changeColor(llvm::raw_ostream::MAGENTA); break;
+ case Macro: OS.changeColor(llvm::raw_ostream::RED); break;
+ }
+ }
+}
+
+WithColor::~WithColor() {
+ if (UseColor == cl::BOU_UNSET ? OS.has_colors() : UseColor == cl::BOU_TRUE)
+ OS.resetColor();
+}
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.h b/contrib/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.h
new file mode 100644
index 0000000..16e6835
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/SyntaxHighlighting.h
@@ -0,0 +1,39 @@
+//===-- SyntaxHighlighting.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_LIB_DEBUGINFO_SYNTAXHIGHLIGHTING_H
+#define LLVM_LIB_DEBUGINFO_SYNTAXHIGHLIGHTING_H
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+namespace dwarf {
+namespace syntax {
+
+// Symbolic names for various syntax elements.
+enum HighlightColor { Address, String, Tag, Attribute, Enumerator, Macro };
+
+/// An RAII object that temporarily switches an output stream to a
+/// specific color.
+class WithColor {
+ llvm::raw_ostream &OS;
+
+public:
+ /// To be used like this: WithColor(OS, syntax::String) << "text";
+ WithColor(llvm::raw_ostream &OS, enum HighlightColor Type);
+ ~WithColor();
+
+ llvm::raw_ostream& get() { return OS; }
+ operator llvm::raw_ostream& () { return OS; }
+};
+}
+}
+}
+
+#endif
diff --git a/contrib/llvm/lib/DebugInfo/DWARF/module.modulemap b/contrib/llvm/lib/DebugInfo/DWARF/module.modulemap
new file mode 100644
index 0000000..c2f624f
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/DWARF/module.modulemap
@@ -0,0 +1 @@
+module DebugInfoDWARF { requires cplusplus umbrella "." module * { export * } }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIADataStream.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIADataStream.cpp
new file mode 100644
index 0000000..e0e1b27
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIADataStream.cpp
@@ -0,0 +1,73 @@
+//===- DIADataStream.cpp - DIA implementation of IPDBDataStream -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIADataStream.h"
+#include "llvm/Support/ConvertUTF.h"
+
+using namespace llvm;
+
+DIADataStream::DIADataStream(CComPtr<IDiaEnumDebugStreamData> DiaStreamData)
+ : StreamData(DiaStreamData) {}
+
+uint32_t DIADataStream::getRecordCount() const {
+ LONG Count = 0;
+ return (S_OK == StreamData->get_Count(&Count)) ? Count : 0;
+}
+
+std::string DIADataStream::getName() const {
+ CComBSTR Name16;
+ if (S_OK != StreamData->get_name(&Name16))
+ return std::string();
+
+ std::string Name8;
+ llvm::ArrayRef<char> Name16Bytes(reinterpret_cast<char *>(Name16.m_str),
+ Name16.ByteLength());
+ if (!llvm::convertUTF16ToUTF8String(Name16Bytes, Name8))
+ return std::string();
+ return Name8;
+}
+
+llvm::Optional<DIADataStream::RecordType>
+DIADataStream::getItemAtIndex(uint32_t Index) const {
+ RecordType Record;
+ DWORD RecordSize = 0;
+ StreamData->Item(Index, 0, &RecordSize, nullptr);
+ if (RecordSize == 0)
+ return llvm::Optional<RecordType>();
+
+ Record.resize(RecordSize);
+ if (S_OK != StreamData->Item(Index, RecordSize, &RecordSize, &Record[0]))
+ return llvm::Optional<RecordType>();
+ return Record;
+}
+
+bool DIADataStream::getNext(RecordType &Record) {
+ Record.clear();
+ DWORD RecordSize = 0;
+ ULONG CountFetched = 0;
+ StreamData->Next(1, 0, &RecordSize, nullptr, &CountFetched);
+ if (RecordSize == 0)
+ return false;
+
+ Record.resize(RecordSize);
+ if (S_OK ==
+ StreamData->Next(1, RecordSize, &RecordSize, &Record[0], &CountFetched))
+ return false;
+ return true;
+}
+
+void DIADataStream::reset() { StreamData->Reset(); }
+
+DIADataStream *DIADataStream::clone() const {
+ CComPtr<IDiaEnumDebugStreamData> EnumeratorClone;
+ if (S_OK != StreamData->Clone(&EnumeratorClone))
+ return nullptr;
+
+ return new DIADataStream(EnumeratorClone);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp
new file mode 100644
index 0000000..23c6489
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp
@@ -0,0 +1,53 @@
+//==- DIAEnumDebugStreams.cpp - DIA Debug Stream Enumerator impl -*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIADataStream.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
+
+using namespace llvm;
+
+DIAEnumDebugStreams::DIAEnumDebugStreams(
+ CComPtr<IDiaEnumDebugStreams> DiaEnumerator)
+ : Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumDebugStreams::getChildCount() const {
+ LONG Count = 0;
+ return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBDataStream>
+DIAEnumDebugStreams::getChildAtIndex(uint32_t Index) const {
+ CComPtr<IDiaEnumDebugStreamData> Item;
+ VARIANT VarIndex;
+ VarIndex.vt = VT_I4;
+ VarIndex.lVal = Index;
+ if (S_OK != Enumerator->Item(VarIndex, &Item))
+ return nullptr;
+
+ return std::unique_ptr<IPDBDataStream>(new DIADataStream(Item));
+}
+
+std::unique_ptr<IPDBDataStream> DIAEnumDebugStreams::getNext() {
+ CComPtr<IDiaEnumDebugStreamData> Item;
+ ULONG NumFetched = 0;
+ if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+ return nullptr;
+
+ return std::unique_ptr<IPDBDataStream>(new DIADataStream(Item));
+}
+
+void DIAEnumDebugStreams::reset() { Enumerator->Reset(); }
+
+DIAEnumDebugStreams *DIAEnumDebugStreams::clone() const {
+ CComPtr<IDiaEnumDebugStreams> EnumeratorClone;
+ if (S_OK != Enumerator->Clone(&EnumeratorClone))
+ return nullptr;
+ return new DIAEnumDebugStreams(EnumeratorClone);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp
new file mode 100644
index 0000000..32a9af2
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp
@@ -0,0 +1,50 @@
+//==- DIAEnumLineNumbers.cpp - DIA Line Number Enumerator impl ---*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/DIA/DIALineNumber.h"
+
+using namespace llvm;
+
+DIAEnumLineNumbers::DIAEnumLineNumbers(
+ CComPtr<IDiaEnumLineNumbers> DiaEnumerator)
+ : Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumLineNumbers::getChildCount() const {
+ LONG Count = 0;
+ return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBLineNumber>
+DIAEnumLineNumbers::getChildAtIndex(uint32_t Index) const {
+ CComPtr<IDiaLineNumber> Item;
+ if (S_OK != Enumerator->Item(Index, &Item))
+ return nullptr;
+
+ return std::unique_ptr<IPDBLineNumber>(new DIALineNumber(Item));
+}
+
+std::unique_ptr<IPDBLineNumber> DIAEnumLineNumbers::getNext() {
+ CComPtr<IDiaLineNumber> Item;
+ ULONG NumFetched = 0;
+ if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+ return nullptr;
+
+ return std::unique_ptr<IPDBLineNumber>(new DIALineNumber(Item));
+}
+
+void DIAEnumLineNumbers::reset() { Enumerator->Reset(); }
+
+DIAEnumLineNumbers *DIAEnumLineNumbers::clone() const {
+ CComPtr<IDiaEnumLineNumbers> EnumeratorClone;
+ if (S_OK != Enumerator->Clone(&EnumeratorClone))
+ return nullptr;
+ return new DIAEnumLineNumbers(EnumeratorClone);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp
new file mode 100644
index 0000000..1a94610
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp
@@ -0,0 +1,50 @@
+//==- DIAEnumSourceFiles.cpp - DIA Source File Enumerator impl ---*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
+
+using namespace llvm;
+
+DIAEnumSourceFiles::DIAEnumSourceFiles(
+ const DIASession &PDBSession, CComPtr<IDiaEnumSourceFiles> DiaEnumerator)
+ : Session(PDBSession), Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumSourceFiles::getChildCount() const {
+ LONG Count = 0;
+ return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<IPDBSourceFile>
+DIAEnumSourceFiles::getChildAtIndex(uint32_t Index) const {
+ CComPtr<IDiaSourceFile> Item;
+ if (S_OK != Enumerator->Item(Index, &Item))
+ return nullptr;
+
+ return std::unique_ptr<IPDBSourceFile>(new DIASourceFile(Session, Item));
+}
+
+std::unique_ptr<IPDBSourceFile> DIAEnumSourceFiles::getNext() {
+ CComPtr<IDiaSourceFile> Item;
+ ULONG NumFetched = 0;
+ if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+ return nullptr;
+
+ return std::unique_ptr<IPDBSourceFile>(new DIASourceFile(Session, Item));
+}
+
+void DIAEnumSourceFiles::reset() { Enumerator->Reset(); }
+
+DIAEnumSourceFiles *DIAEnumSourceFiles::clone() const {
+ CComPtr<IDiaEnumSourceFiles> EnumeratorClone;
+ if (S_OK != Enumerator->Clone(&EnumeratorClone))
+ return nullptr;
+ return new DIAEnumSourceFiles(Session, EnumeratorClone);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp
new file mode 100644
index 0000000..6754d9a
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp
@@ -0,0 +1,54 @@
+//==- DIAEnumSymbols.cpp - DIA Symbol Enumerator impl ------------*- C++ -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h"
+#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+
+using namespace llvm;
+
+DIAEnumSymbols::DIAEnumSymbols(const DIASession &PDBSession,
+ CComPtr<IDiaEnumSymbols> DiaEnumerator)
+ : Session(PDBSession), Enumerator(DiaEnumerator) {}
+
+uint32_t DIAEnumSymbols::getChildCount() const {
+ LONG Count = 0;
+ return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0;
+}
+
+std::unique_ptr<PDBSymbol>
+DIAEnumSymbols::getChildAtIndex(uint32_t Index) const {
+ CComPtr<IDiaSymbol> Item;
+ if (S_OK != Enumerator->Item(Index, &Item))
+ return nullptr;
+
+ std::unique_ptr<DIARawSymbol> RawSymbol(new DIARawSymbol(Session, Item));
+ return std::unique_ptr<PDBSymbol>(PDBSymbol::create(Session, std::move(RawSymbol)));
+}
+
+std::unique_ptr<PDBSymbol> DIAEnumSymbols::getNext() {
+ CComPtr<IDiaSymbol> Item;
+ ULONG NumFetched = 0;
+ if (S_OK != Enumerator->Next(1, &Item, &NumFetched))
+ return nullptr;
+
+ std::unique_ptr<DIARawSymbol> RawSymbol(new DIARawSymbol(Session, Item));
+ return std::unique_ptr<PDBSymbol>(
+ PDBSymbol::create(Session, std::move(RawSymbol)));
+}
+
+void DIAEnumSymbols::reset() { Enumerator->Reset(); }
+
+DIAEnumSymbols *DIAEnumSymbols::clone() const {
+ CComPtr<IDiaEnumSymbols> EnumeratorClone;
+ if (S_OK != Enumerator->Clone(&EnumeratorClone))
+ return nullptr;
+ return new DIAEnumSymbols(Session, EnumeratorClone);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIALineNumber.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIALineNumber.cpp
new file mode 100644
index 0000000..c5577f1
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIALineNumber.cpp
@@ -0,0 +1,75 @@
+//===- DIALineNumber.cpp - DIA implementation of IPDBLineNumber -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIALineNumber.h"
+
+using namespace llvm;
+
+DIALineNumber::DIALineNumber(CComPtr<IDiaLineNumber> DiaLineNumber)
+ : LineNumber(DiaLineNumber) {}
+
+uint32_t DIALineNumber::getLineNumber() const {
+ DWORD Line = 0;
+ return (S_OK == LineNumber->get_lineNumber(&Line)) ? Line : 0;
+}
+
+uint32_t DIALineNumber::getLineNumberEnd() const {
+ DWORD LineEnd = 0;
+ return (S_OK == LineNumber->get_lineNumberEnd(&LineEnd)) ? LineEnd : 0;
+}
+
+uint32_t DIALineNumber::getColumnNumber() const {
+ DWORD Column = 0;
+ return (S_OK == LineNumber->get_columnNumber(&Column)) ? Column : 0;
+}
+
+uint32_t DIALineNumber::getColumnNumberEnd() const {
+ DWORD ColumnEnd = 0;
+ return (S_OK == LineNumber->get_columnNumberEnd(&ColumnEnd)) ? ColumnEnd : 0;
+}
+
+uint32_t DIALineNumber::getAddressSection() const {
+ DWORD Section = 0;
+ return (S_OK == LineNumber->get_addressSection(&Section)) ? Section : 0;
+}
+
+uint32_t DIALineNumber::getAddressOffset() const {
+ DWORD Offset = 0;
+ return (S_OK == LineNumber->get_addressOffset(&Offset)) ? Offset : 0;
+}
+
+uint32_t DIALineNumber::getRelativeVirtualAddress() const {
+ DWORD RVA = 0;
+ return (S_OK == LineNumber->get_relativeVirtualAddress(&RVA)) ? RVA : 0;
+}
+
+uint64_t DIALineNumber::getVirtualAddress() const {
+ ULONGLONG Addr = 0;
+ return (S_OK == LineNumber->get_virtualAddress(&Addr)) ? Addr : 0;
+}
+
+uint32_t DIALineNumber::getLength() const {
+ DWORD Length = 0;
+ return (S_OK == LineNumber->get_length(&Length)) ? Length : 0;
+}
+
+uint32_t DIALineNumber::getSourceFileId() const {
+ DWORD Id = 0;
+ return (S_OK == LineNumber->get_sourceFileId(&Id)) ? Id : 0;
+}
+
+uint32_t DIALineNumber::getCompilandId() const {
+ DWORD Id = 0;
+ return (S_OK == LineNumber->get_compilandId(&Id)) ? Id : 0;
+}
+
+bool DIALineNumber::isStatement() const {
+ BOOL Statement = 0;
+ return (S_OK == LineNumber->get_statement(&Statement)) ? Statement : false;
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
new file mode 100644
index 0000000..abe0ab5
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp
@@ -0,0 +1,1095 @@
+//===- DIARawSymbol.cpp - DIA implementation of IPDBRawSymbol ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h"
+#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+namespace {
+Variant VariantFromVARIANT(const VARIANT &V) {
+ Variant Result;
+ switch (V.vt) {
+ case VT_I1:
+ Result.Int8 = V.cVal;
+ Result.Type = PDB_VariantType::Int8;
+ break;
+ case VT_I2:
+ Result.Int16 = V.iVal;
+ Result.Type = PDB_VariantType::Int16;
+ break;
+ case VT_I4:
+ Result.Int32 = V.intVal;
+ Result.Type = PDB_VariantType::Int32;
+ break;
+ case VT_I8:
+ Result.Int64 = V.llVal;
+ Result.Type = PDB_VariantType::Int64;
+ break;
+ case VT_UI1:
+ Result.UInt8 = V.bVal;
+ Result.Type = PDB_VariantType::UInt8;
+ break;
+ case VT_UI2:
+ Result.UInt16 = V.uiVal;
+ Result.Type = PDB_VariantType::UInt16;
+ break;
+ case VT_UI4:
+ Result.UInt32 = V.uintVal;
+ Result.Type = PDB_VariantType::UInt32;
+ break;
+ case VT_UI8:
+ Result.UInt64 = V.ullVal;
+ Result.Type = PDB_VariantType::UInt64;
+ break;
+ case VT_BOOL:
+ Result.Bool = (V.boolVal == VARIANT_TRUE) ? true : false;
+ Result.Type = PDB_VariantType::Bool;
+ break;
+ case VT_R4:
+ Result.Single = V.fltVal;
+ Result.Type = PDB_VariantType::Single;
+ break;
+ case VT_R8:
+ Result.Double = V.dblVal;
+ Result.Type = PDB_VariantType::Double;
+ break;
+ default:
+ Result.Type = PDB_VariantType::Unknown;
+ break;
+ }
+ return Result;
+}
+
+template <typename ArgType>
+ArgType PrivateGetDIAValue(IDiaSymbol *Symbol,
+ HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
+ ArgType Value;
+ if (S_OK == (Symbol->*Method)(&Value))
+ return static_cast<ArgType>(Value);
+
+ return ArgType();
+}
+
+template <typename ArgType, typename RetType>
+RetType PrivateGetDIAValue(IDiaSymbol *Symbol,
+ HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
+ ArgType Value;
+ if (S_OK == (Symbol->*Method)(&Value))
+ return static_cast<RetType>(Value);
+
+ return RetType();
+}
+
+std::string
+PrivateGetDIAValue(IDiaSymbol *Symbol,
+ HRESULT (__stdcall IDiaSymbol::*Method)(BSTR *)) {
+ CComBSTR Result16;
+ if (S_OK != (Symbol->*Method)(&Result16))
+ return std::string();
+
+ const char *SrcBytes = reinterpret_cast<const char *>(Result16.m_str);
+ llvm::ArrayRef<char> SrcByteArray(SrcBytes, Result16.ByteLength());
+ std::string Result8;
+ if (!llvm::convertUTF16ToUTF8String(SrcByteArray, Result8))
+ return std::string();
+ return Result8;
+}
+
+PDB_UniqueId
+PrivateGetDIAValue(IDiaSymbol *Symbol,
+ HRESULT (__stdcall IDiaSymbol::*Method)(GUID *)) {
+ GUID Result;
+ if (S_OK != (Symbol->*Method)(&Result))
+ return PDB_UniqueId();
+
+ static_assert(sizeof(PDB_UniqueId) == sizeof(GUID),
+ "PDB_UniqueId is the wrong size!");
+ PDB_UniqueId IdResult;
+ ::memcpy(&IdResult, &Result, sizeof(GUID));
+ return IdResult;
+}
+
+template <typename ArgType>
+void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
+ IDiaSymbol *Symbol,
+ HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) {
+ ArgType Value;
+ if (S_OK == (Symbol->*Method)(&Value)) {
+ OS << "\n";
+ OS.indent(Indent);
+ OS << Name << ": " << Value;
+ }
+}
+
+void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
+ IDiaSymbol *Symbol,
+ HRESULT (__stdcall IDiaSymbol::*Method)(BSTR *)) {
+ BSTR Value = nullptr;
+ if (S_OK != (Symbol->*Method)(&Value))
+ return;
+ const char *Bytes = reinterpret_cast<const char *>(Value);
+ ArrayRef<char> ByteArray(Bytes, ::SysStringByteLen(Value));
+ std::string Result;
+ if (llvm::convertUTF16ToUTF8String(ByteArray, Result)) {
+ OS << "\n";
+ OS.indent(Indent);
+ OS << Name << ": " << Result;
+ }
+ ::SysFreeString(Value);
+}
+
+void DumpDIAValue(llvm::raw_ostream &OS, int Indent, StringRef Name,
+ IDiaSymbol *Symbol,
+ HRESULT (__stdcall IDiaSymbol::*Method)(VARIANT *)) {
+ VARIANT Value;
+ Value.vt = VT_EMPTY;
+ if (S_OK != (Symbol->*Method)(&Value))
+ return;
+ OS << "\n";
+ OS.indent(Indent);
+ Variant V = VariantFromVARIANT(Value);
+ OS << V;
+}
+}
+
+namespace llvm {
+raw_ostream &operator<<(raw_ostream &OS, const GUID &Guid) {
+ const PDB_UniqueId *Id = reinterpret_cast<const PDB_UniqueId *>(&Guid);
+ OS << *Id;
+ return OS;
+}
+}
+
+DIARawSymbol::DIARawSymbol(const DIASession &PDBSession,
+ CComPtr<IDiaSymbol> DiaSymbol)
+ : Session(PDBSession), Symbol(DiaSymbol) {}
+
+#define RAW_METHOD_DUMP(Stream, Method) \
+ DumpDIAValue(Stream, Indent, StringRef(#Method), Symbol, &IDiaSymbol::Method);
+
+void DIARawSymbol::dump(raw_ostream &OS, int Indent) const {
+ RAW_METHOD_DUMP(OS, get_access)
+ RAW_METHOD_DUMP(OS, get_addressOffset)
+ RAW_METHOD_DUMP(OS, get_addressSection)
+ RAW_METHOD_DUMP(OS, get_age)
+ RAW_METHOD_DUMP(OS, get_arrayIndexTypeId)
+ RAW_METHOD_DUMP(OS, get_backEndMajor)
+ RAW_METHOD_DUMP(OS, get_backEndMinor)
+ RAW_METHOD_DUMP(OS, get_backEndBuild)
+ RAW_METHOD_DUMP(OS, get_backEndQFE)
+ RAW_METHOD_DUMP(OS, get_baseDataOffset)
+ RAW_METHOD_DUMP(OS, get_baseDataSlot)
+ RAW_METHOD_DUMP(OS, get_baseSymbolId)
+ RAW_METHOD_DUMP(OS, get_baseType)
+ RAW_METHOD_DUMP(OS, get_bitPosition)
+ RAW_METHOD_DUMP(OS, get_callingConvention)
+ RAW_METHOD_DUMP(OS, get_classParentId)
+ RAW_METHOD_DUMP(OS, get_compilerName)
+ RAW_METHOD_DUMP(OS, get_count)
+ RAW_METHOD_DUMP(OS, get_countLiveRanges)
+ RAW_METHOD_DUMP(OS, get_frontEndMajor)
+ RAW_METHOD_DUMP(OS, get_frontEndMinor)
+ RAW_METHOD_DUMP(OS, get_frontEndBuild)
+ RAW_METHOD_DUMP(OS, get_frontEndQFE)
+ RAW_METHOD_DUMP(OS, get_lexicalParentId)
+ RAW_METHOD_DUMP(OS, get_libraryName)
+ RAW_METHOD_DUMP(OS, get_liveRangeStartAddressOffset)
+ RAW_METHOD_DUMP(OS, get_liveRangeStartAddressSection)
+ RAW_METHOD_DUMP(OS, get_liveRangeStartRelativeVirtualAddress)
+ RAW_METHOD_DUMP(OS, get_localBasePointerRegisterId)
+ RAW_METHOD_DUMP(OS, get_lowerBoundId)
+ RAW_METHOD_DUMP(OS, get_memorySpaceKind)
+ RAW_METHOD_DUMP(OS, get_name)
+ RAW_METHOD_DUMP(OS, get_numberOfAcceleratorPointerTags)
+ RAW_METHOD_DUMP(OS, get_numberOfColumns)
+ RAW_METHOD_DUMP(OS, get_numberOfModifiers)
+ RAW_METHOD_DUMP(OS, get_numberOfRegisterIndices)
+ RAW_METHOD_DUMP(OS, get_numberOfRows)
+ RAW_METHOD_DUMP(OS, get_objectFileName)
+ RAW_METHOD_DUMP(OS, get_oemId)
+ RAW_METHOD_DUMP(OS, get_oemSymbolId)
+ RAW_METHOD_DUMP(OS, get_offsetInUdt)
+ RAW_METHOD_DUMP(OS, get_platform)
+ RAW_METHOD_DUMP(OS, get_rank)
+ RAW_METHOD_DUMP(OS, get_registerId)
+ RAW_METHOD_DUMP(OS, get_registerType)
+ RAW_METHOD_DUMP(OS, get_relativeVirtualAddress)
+ RAW_METHOD_DUMP(OS, get_samplerSlot)
+ RAW_METHOD_DUMP(OS, get_signature)
+ RAW_METHOD_DUMP(OS, get_sizeInUdt)
+ RAW_METHOD_DUMP(OS, get_slot)
+ RAW_METHOD_DUMP(OS, get_sourceFileName)
+ RAW_METHOD_DUMP(OS, get_stride)
+ RAW_METHOD_DUMP(OS, get_subTypeId)
+ RAW_METHOD_DUMP(OS, get_symbolsFileName)
+ RAW_METHOD_DUMP(OS, get_symIndexId)
+ RAW_METHOD_DUMP(OS, get_targetOffset)
+ RAW_METHOD_DUMP(OS, get_targetRelativeVirtualAddress)
+ RAW_METHOD_DUMP(OS, get_targetVirtualAddress)
+ RAW_METHOD_DUMP(OS, get_targetSection)
+ RAW_METHOD_DUMP(OS, get_textureSlot)
+ RAW_METHOD_DUMP(OS, get_timeStamp)
+ RAW_METHOD_DUMP(OS, get_token)
+ RAW_METHOD_DUMP(OS, get_typeId)
+ RAW_METHOD_DUMP(OS, get_uavSlot)
+ RAW_METHOD_DUMP(OS, get_undecoratedName)
+ RAW_METHOD_DUMP(OS, get_unmodifiedTypeId)
+ RAW_METHOD_DUMP(OS, get_upperBoundId)
+ RAW_METHOD_DUMP(OS, get_virtualBaseDispIndex)
+ RAW_METHOD_DUMP(OS, get_virtualBaseOffset)
+ RAW_METHOD_DUMP(OS, get_virtualTableShapeId)
+ RAW_METHOD_DUMP(OS, get_dataKind)
+ RAW_METHOD_DUMP(OS, get_symTag)
+ RAW_METHOD_DUMP(OS, get_guid)
+ RAW_METHOD_DUMP(OS, get_offset)
+ RAW_METHOD_DUMP(OS, get_thisAdjust)
+ RAW_METHOD_DUMP(OS, get_virtualBasePointerOffset)
+ RAW_METHOD_DUMP(OS, get_locationType)
+ RAW_METHOD_DUMP(OS, get_machineType)
+ RAW_METHOD_DUMP(OS, get_thunkOrdinal)
+ RAW_METHOD_DUMP(OS, get_length)
+ RAW_METHOD_DUMP(OS, get_liveRangeLength)
+ RAW_METHOD_DUMP(OS, get_virtualAddress)
+ RAW_METHOD_DUMP(OS, get_udtKind)
+ RAW_METHOD_DUMP(OS, get_constructor)
+ RAW_METHOD_DUMP(OS, get_customCallingConvention)
+ RAW_METHOD_DUMP(OS, get_farReturn)
+ RAW_METHOD_DUMP(OS, get_code)
+ RAW_METHOD_DUMP(OS, get_compilerGenerated)
+ RAW_METHOD_DUMP(OS, get_constType)
+ RAW_METHOD_DUMP(OS, get_editAndContinueEnabled)
+ RAW_METHOD_DUMP(OS, get_function)
+ RAW_METHOD_DUMP(OS, get_stride)
+ RAW_METHOD_DUMP(OS, get_noStackOrdering)
+ RAW_METHOD_DUMP(OS, get_hasAlloca)
+ RAW_METHOD_DUMP(OS, get_hasAssignmentOperator)
+ RAW_METHOD_DUMP(OS, get_isCTypes)
+ RAW_METHOD_DUMP(OS, get_hasCastOperator)
+ RAW_METHOD_DUMP(OS, get_hasDebugInfo)
+ RAW_METHOD_DUMP(OS, get_hasEH)
+ RAW_METHOD_DUMP(OS, get_hasEHa)
+ RAW_METHOD_DUMP(OS, get_hasInlAsm)
+ RAW_METHOD_DUMP(OS, get_framePointerPresent)
+ RAW_METHOD_DUMP(OS, get_inlSpec)
+ RAW_METHOD_DUMP(OS, get_interruptReturn)
+ RAW_METHOD_DUMP(OS, get_hasLongJump)
+ RAW_METHOD_DUMP(OS, get_hasManagedCode)
+ RAW_METHOD_DUMP(OS, get_hasNestedTypes)
+ RAW_METHOD_DUMP(OS, get_noInline)
+ RAW_METHOD_DUMP(OS, get_noReturn)
+ RAW_METHOD_DUMP(OS, get_optimizedCodeDebugInfo)
+ RAW_METHOD_DUMP(OS, get_overloadedOperator)
+ RAW_METHOD_DUMP(OS, get_hasSEH)
+ RAW_METHOD_DUMP(OS, get_hasSecurityChecks)
+ RAW_METHOD_DUMP(OS, get_hasSetJump)
+ RAW_METHOD_DUMP(OS, get_strictGSCheck)
+ RAW_METHOD_DUMP(OS, get_isAcceleratorGroupSharedLocal)
+ RAW_METHOD_DUMP(OS, get_isAcceleratorPointerTagLiveRange)
+ RAW_METHOD_DUMP(OS, get_isAcceleratorStubFunction)
+ RAW_METHOD_DUMP(OS, get_isAggregated)
+ RAW_METHOD_DUMP(OS, get_intro)
+ RAW_METHOD_DUMP(OS, get_isCVTCIL)
+ RAW_METHOD_DUMP(OS, get_isConstructorVirtualBase)
+ RAW_METHOD_DUMP(OS, get_isCxxReturnUdt)
+ RAW_METHOD_DUMP(OS, get_isDataAligned)
+ RAW_METHOD_DUMP(OS, get_isHLSLData)
+ RAW_METHOD_DUMP(OS, get_isHotpatchable)
+ RAW_METHOD_DUMP(OS, get_indirectVirtualBaseClass)
+ RAW_METHOD_DUMP(OS, get_isInterfaceUdt)
+ RAW_METHOD_DUMP(OS, get_intrinsic)
+ RAW_METHOD_DUMP(OS, get_isLTCG)
+ RAW_METHOD_DUMP(OS, get_isLocationControlFlowDependent)
+ RAW_METHOD_DUMP(OS, get_isMSILNetmodule)
+ RAW_METHOD_DUMP(OS, get_isMatrixRowMajor)
+ RAW_METHOD_DUMP(OS, get_managed)
+ RAW_METHOD_DUMP(OS, get_msil)
+ RAW_METHOD_DUMP(OS, get_isMultipleInheritance)
+ RAW_METHOD_DUMP(OS, get_isNaked)
+ RAW_METHOD_DUMP(OS, get_nested)
+ RAW_METHOD_DUMP(OS, get_isOptimizedAway)
+ RAW_METHOD_DUMP(OS, get_packed)
+ RAW_METHOD_DUMP(OS, get_isPointerBasedOnSymbolValue)
+ RAW_METHOD_DUMP(OS, get_isPointerToDataMember)
+ RAW_METHOD_DUMP(OS, get_isPointerToMemberFunction)
+ RAW_METHOD_DUMP(OS, get_pure)
+ RAW_METHOD_DUMP(OS, get_RValueReference)
+ RAW_METHOD_DUMP(OS, get_isRefUdt)
+ RAW_METHOD_DUMP(OS, get_reference)
+ RAW_METHOD_DUMP(OS, get_restrictedType)
+ RAW_METHOD_DUMP(OS, get_isReturnValue)
+ RAW_METHOD_DUMP(OS, get_isSafeBuffers)
+ RAW_METHOD_DUMP(OS, get_scoped)
+ RAW_METHOD_DUMP(OS, get_isSdl)
+ RAW_METHOD_DUMP(OS, get_isSingleInheritance)
+ RAW_METHOD_DUMP(OS, get_isSplitted)
+ RAW_METHOD_DUMP(OS, get_isStatic)
+ RAW_METHOD_DUMP(OS, get_isStripped)
+ RAW_METHOD_DUMP(OS, get_unalignedType)
+ RAW_METHOD_DUMP(OS, get_notReached)
+ RAW_METHOD_DUMP(OS, get_isValueUdt)
+ RAW_METHOD_DUMP(OS, get_virtual)
+ RAW_METHOD_DUMP(OS, get_virtualBaseClass)
+ RAW_METHOD_DUMP(OS, get_isVirtualInheritance)
+ RAW_METHOD_DUMP(OS, get_volatileType)
+ RAW_METHOD_DUMP(OS, get_wasInlined)
+ RAW_METHOD_DUMP(OS, get_unused)
+ RAW_METHOD_DUMP(OS, get_value)
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildren(PDB_SymType Type) const {
+ enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+ CComPtr<IDiaEnumSymbols> DiaEnumerator;
+ if (S_OK != Symbol->findChildrenEx(EnumVal, nullptr, nsNone, &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const {
+ llvm::SmallVector<UTF16, 32> Name16;
+ llvm::convertUTF8ToUTF16String(Name, Name16);
+
+ enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+ DWORD CompareFlags = static_cast<DWORD>(Flags);
+ wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data());
+
+ CComPtr<IDiaEnumSymbols> DiaEnumerator;
+ if (S_OK !=
+ Symbol->findChildrenEx(EnumVal, Name16Str, CompareFlags, &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags, uint32_t RVA) const {
+ llvm::SmallVector<UTF16, 32> Name16;
+ llvm::convertUTF8ToUTF16String(Name, Name16);
+
+ enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+ DWORD CompareFlags = static_cast<DWORD>(Flags);
+ wchar_t *Name16Str = reinterpret_cast<wchar_t *>(Name16.data());
+
+ CComPtr<IDiaEnumSymbols> DiaEnumerator;
+ if (S_OK !=
+ Symbol->findChildrenExByRVA(EnumVal, Name16Str, CompareFlags, RVA,
+ &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+DIARawSymbol::findInlineFramesByRVA(uint32_t RVA) const {
+ CComPtr<IDiaEnumSymbols> DiaEnumerator;
+ if (S_OK != Symbol->findInlineFramesByRVA(RVA, &DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSymbols>(Session, DiaEnumerator);
+}
+
+void DIARawSymbol::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) const {
+ bytes.clear();
+
+ DWORD DataSize = 0;
+ Symbol->get_dataBytes(0, &DataSize, nullptr);
+ if (DataSize == 0)
+ return;
+
+ bytes.resize(DataSize);
+ Symbol->get_dataBytes(DataSize, &DataSize, bytes.data());
+}
+
+PDB_MemberAccess DIARawSymbol::getAccess() const {
+ return PrivateGetDIAValue<DWORD, PDB_MemberAccess>(Symbol,
+ &IDiaSymbol::get_access);
+}
+
+uint32_t DIARawSymbol::getAddressOffset() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_addressOffset);
+}
+
+uint32_t DIARawSymbol::getAddressSection() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_addressSection);
+}
+
+uint32_t DIARawSymbol::getAge() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_age);
+}
+
+uint32_t DIARawSymbol::getArrayIndexTypeId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_arrayIndexTypeId);
+}
+
+void DIARawSymbol::getBackEndVersion(VersionInfo &Version) const {
+ Version.Major = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_backEndMajor);
+ Version.Minor = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_backEndMinor);
+ Version.Build = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_backEndBuild);
+ Version.QFE = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_backEndQFE);
+}
+
+uint32_t DIARawSymbol::getBaseDataOffset() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_baseDataOffset);
+}
+
+uint32_t DIARawSymbol::getBaseDataSlot() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_baseDataSlot);
+}
+
+uint32_t DIARawSymbol::getBaseSymbolId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_baseSymbolId);
+}
+
+PDB_BuiltinType DIARawSymbol::getBuiltinType() const {
+ return PrivateGetDIAValue<DWORD, PDB_BuiltinType>(Symbol,
+ &IDiaSymbol::get_baseType);
+}
+
+uint32_t DIARawSymbol::getBitPosition() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_bitPosition);
+}
+
+PDB_CallingConv DIARawSymbol::getCallingConvention() const {
+ return PrivateGetDIAValue<DWORD, PDB_CallingConv>(
+ Symbol, &IDiaSymbol::get_callingConvention);
+}
+
+uint32_t DIARawSymbol::getClassParentId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_classParentId);
+}
+
+std::string DIARawSymbol::getCompilerName() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_compilerName);
+}
+
+uint32_t DIARawSymbol::getCount() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_count);
+}
+
+uint32_t DIARawSymbol::getCountLiveRanges() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_countLiveRanges);
+}
+
+void DIARawSymbol::getFrontEndVersion(VersionInfo &Version) const {
+ Version.Major = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_frontEndMajor);
+ Version.Minor = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_frontEndMinor);
+ Version.Build = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_frontEndBuild);
+ Version.QFE = PrivateGetDIAValue(Symbol, &IDiaSymbol::get_frontEndQFE);
+}
+
+PDB_Lang DIARawSymbol::getLanguage() const {
+ return PrivateGetDIAValue<DWORD, PDB_Lang>(Symbol, &IDiaSymbol::get_language);
+}
+
+uint32_t DIARawSymbol::getLexicalParentId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_lexicalParentId);
+}
+
+std::string DIARawSymbol::getLibraryName() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_libraryName);
+}
+
+uint32_t DIARawSymbol::getLiveRangeStartAddressOffset() const {
+ return PrivateGetDIAValue(Symbol,
+ &IDiaSymbol::get_liveRangeStartAddressOffset);
+}
+
+uint32_t DIARawSymbol::getLiveRangeStartAddressSection() const {
+ return PrivateGetDIAValue(Symbol,
+ &IDiaSymbol::get_liveRangeStartAddressSection);
+}
+
+uint32_t DIARawSymbol::getLiveRangeStartRelativeVirtualAddress() const {
+ return PrivateGetDIAValue(
+ Symbol, &IDiaSymbol::get_liveRangeStartRelativeVirtualAddress);
+}
+
+PDB_RegisterId DIARawSymbol::getLocalBasePointerRegisterId() const {
+ return PrivateGetDIAValue<DWORD, PDB_RegisterId>(
+ Symbol, &IDiaSymbol::get_localBasePointerRegisterId);
+}
+
+uint32_t DIARawSymbol::getLowerBoundId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_lowerBoundId);
+}
+
+uint32_t DIARawSymbol::getMemorySpaceKind() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_memorySpaceKind);
+}
+
+std::string DIARawSymbol::getName() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_name);
+}
+
+uint32_t DIARawSymbol::getNumberOfAcceleratorPointerTags() const {
+ return PrivateGetDIAValue(Symbol,
+ &IDiaSymbol::get_numberOfAcceleratorPointerTags);
+}
+
+uint32_t DIARawSymbol::getNumberOfColumns() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_numberOfColumns);
+}
+
+uint32_t DIARawSymbol::getNumberOfModifiers() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_numberOfModifiers);
+}
+
+uint32_t DIARawSymbol::getNumberOfRegisterIndices() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_numberOfRegisterIndices);
+}
+
+uint32_t DIARawSymbol::getNumberOfRows() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_numberOfRows);
+}
+
+std::string DIARawSymbol::getObjectFileName() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_objectFileName);
+}
+
+uint32_t DIARawSymbol::getOemId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_oemId);
+}
+
+uint32_t DIARawSymbol::getOemSymbolId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_oemSymbolId);
+}
+
+uint32_t DIARawSymbol::getOffsetInUdt() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_offsetInUdt);
+}
+
+PDB_Cpu DIARawSymbol::getPlatform() const {
+ return PrivateGetDIAValue<DWORD, PDB_Cpu>(Symbol, &IDiaSymbol::get_platform);
+}
+
+uint32_t DIARawSymbol::getRank() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_rank);
+}
+
+PDB_RegisterId DIARawSymbol::getRegisterId() const {
+ return PrivateGetDIAValue<DWORD, PDB_RegisterId>(Symbol,
+ &IDiaSymbol::get_registerId);
+}
+
+uint32_t DIARawSymbol::getRegisterType() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_registerType);
+}
+
+uint32_t DIARawSymbol::getRelativeVirtualAddress() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_relativeVirtualAddress);
+}
+
+uint32_t DIARawSymbol::getSamplerSlot() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_samplerSlot);
+}
+
+uint32_t DIARawSymbol::getSignature() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_signature);
+}
+
+uint32_t DIARawSymbol::getSizeInUdt() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_sizeInUdt);
+}
+
+uint32_t DIARawSymbol::getSlot() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_slot);
+}
+
+std::string DIARawSymbol::getSourceFileName() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_sourceFileName);
+}
+
+uint32_t DIARawSymbol::getStride() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_stride);
+}
+
+uint32_t DIARawSymbol::getSubTypeId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_subTypeId);
+}
+
+std::string DIARawSymbol::getSymbolsFileName() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_symbolsFileName);
+}
+
+uint32_t DIARawSymbol::getSymIndexId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_symIndexId);
+}
+
+uint32_t DIARawSymbol::getTargetOffset() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_targetOffset);
+}
+
+uint32_t DIARawSymbol::getTargetRelativeVirtualAddress() const {
+ return PrivateGetDIAValue(Symbol,
+ &IDiaSymbol::get_targetRelativeVirtualAddress);
+}
+
+uint64_t DIARawSymbol::getTargetVirtualAddress() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_targetVirtualAddress);
+}
+
+uint32_t DIARawSymbol::getTargetSection() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_targetSection);
+}
+
+uint32_t DIARawSymbol::getTextureSlot() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_textureSlot);
+}
+
+uint32_t DIARawSymbol::getTimeStamp() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_timeStamp);
+}
+
+uint32_t DIARawSymbol::getToken() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_token);
+}
+
+uint32_t DIARawSymbol::getTypeId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_typeId);
+}
+
+uint32_t DIARawSymbol::getUavSlot() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_uavSlot);
+}
+
+std::string DIARawSymbol::getUndecoratedName() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_undecoratedName);
+}
+
+uint32_t DIARawSymbol::getUnmodifiedTypeId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_unmodifiedTypeId);
+}
+
+uint32_t DIARawSymbol::getUpperBoundId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_upperBoundId);
+}
+
+Variant DIARawSymbol::getValue() const {
+ VARIANT Value;
+ Value.vt = VT_EMPTY;
+ if (S_OK != Symbol->get_value(&Value))
+ return Variant();
+
+ return VariantFromVARIANT(Value);
+}
+
+uint32_t DIARawSymbol::getVirtualBaseDispIndex() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualBaseDispIndex);
+}
+
+uint32_t DIARawSymbol::getVirtualBaseOffset() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualBaseOffset);
+}
+
+uint32_t DIARawSymbol::getVirtualTableShapeId() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualTableShapeId);
+}
+
+PDB_DataKind DIARawSymbol::getDataKind() const {
+ return PrivateGetDIAValue<DWORD, PDB_DataKind>(Symbol,
+ &IDiaSymbol::get_dataKind);
+}
+
+PDB_SymType DIARawSymbol::getSymTag() const {
+ return PrivateGetDIAValue<DWORD, PDB_SymType>(Symbol,
+ &IDiaSymbol::get_symTag);
+}
+
+PDB_UniqueId DIARawSymbol::getGuid() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_guid);
+}
+
+int32_t DIARawSymbol::getOffset() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_offset);
+}
+
+int32_t DIARawSymbol::getThisAdjust() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_thisAdjust);
+}
+
+int32_t DIARawSymbol::getVirtualBasePointerOffset() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualBasePointerOffset);
+}
+
+PDB_LocType DIARawSymbol::getLocationType() const {
+ return PrivateGetDIAValue<DWORD, PDB_LocType>(Symbol,
+ &IDiaSymbol::get_locationType);
+}
+
+PDB_Machine DIARawSymbol::getMachineType() const {
+ return PrivateGetDIAValue<DWORD, PDB_Machine>(Symbol,
+ &IDiaSymbol::get_machineType);
+}
+
+PDB_ThunkOrdinal DIARawSymbol::getThunkOrdinal() const {
+ return PrivateGetDIAValue<DWORD, PDB_ThunkOrdinal>(
+ Symbol, &IDiaSymbol::get_thunkOrdinal);
+}
+
+uint64_t DIARawSymbol::getLength() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_length);
+}
+
+uint64_t DIARawSymbol::getLiveRangeLength() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_liveRangeLength);
+}
+
+uint64_t DIARawSymbol::getVirtualAddress() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualAddress);
+}
+
+PDB_UdtType DIARawSymbol::getUdtKind() const {
+ return PrivateGetDIAValue<DWORD, PDB_UdtType>(Symbol,
+ &IDiaSymbol::get_udtKind);
+}
+
+bool DIARawSymbol::hasConstructor() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_constructor);
+}
+
+bool DIARawSymbol::hasCustomCallingConvention() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_customCallingConvention);
+}
+
+bool DIARawSymbol::hasFarReturn() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_farReturn);
+}
+
+bool DIARawSymbol::isCode() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_code);
+}
+
+bool DIARawSymbol::isCompilerGenerated() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_compilerGenerated);
+}
+
+bool DIARawSymbol::isConstType() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_constType);
+}
+
+bool DIARawSymbol::isEditAndContinueEnabled() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_editAndContinueEnabled);
+}
+
+bool DIARawSymbol::isFunction() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_function);
+}
+
+bool DIARawSymbol::getAddressTaken() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_addressTaken);
+}
+
+bool DIARawSymbol::getNoStackOrdering() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_noStackOrdering);
+}
+
+bool DIARawSymbol::hasAlloca() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasAlloca);
+}
+
+bool DIARawSymbol::hasAssignmentOperator() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasAssignmentOperator);
+}
+
+bool DIARawSymbol::hasCTypes() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isCTypes);
+}
+
+bool DIARawSymbol::hasCastOperator() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasCastOperator);
+}
+
+bool DIARawSymbol::hasDebugInfo() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasDebugInfo);
+}
+
+bool DIARawSymbol::hasEH() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasEH);
+}
+
+bool DIARawSymbol::hasEHa() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasEHa);
+}
+
+bool DIARawSymbol::hasInlAsm() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasInlAsm);
+}
+
+bool DIARawSymbol::hasInlineAttribute() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_inlSpec);
+}
+
+bool DIARawSymbol::hasInterruptReturn() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_interruptReturn);
+}
+
+bool DIARawSymbol::hasFramePointer() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_framePointerPresent);
+}
+
+bool DIARawSymbol::hasLongJump() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasLongJump);
+}
+
+bool DIARawSymbol::hasManagedCode() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasManagedCode);
+}
+
+bool DIARawSymbol::hasNestedTypes() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasNestedTypes);
+}
+
+bool DIARawSymbol::hasNoInlineAttribute() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_noInline);
+}
+
+bool DIARawSymbol::hasNoReturnAttribute() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_noReturn);
+}
+
+bool DIARawSymbol::hasOptimizedCodeDebugInfo() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_optimizedCodeDebugInfo);
+}
+
+bool DIARawSymbol::hasOverloadedOperator() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_overloadedOperator);
+}
+
+bool DIARawSymbol::hasSEH() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasSEH);
+}
+
+bool DIARawSymbol::hasSecurityChecks() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasSecurityChecks);
+}
+
+bool DIARawSymbol::hasSetJump() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_hasSetJump);
+}
+
+bool DIARawSymbol::hasStrictGSCheck() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_strictGSCheck);
+}
+
+bool DIARawSymbol::isAcceleratorGroupSharedLocal() const {
+ return PrivateGetDIAValue(Symbol,
+ &IDiaSymbol::get_isAcceleratorGroupSharedLocal);
+}
+
+bool DIARawSymbol::isAcceleratorPointerTagLiveRange() const {
+ return PrivateGetDIAValue(Symbol,
+ &IDiaSymbol::get_isAcceleratorPointerTagLiveRange);
+}
+
+bool DIARawSymbol::isAcceleratorStubFunction() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isAcceleratorStubFunction);
+}
+
+bool DIARawSymbol::isAggregated() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isAggregated);
+}
+
+bool DIARawSymbol::isIntroVirtualFunction() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_intro);
+}
+
+bool DIARawSymbol::isCVTCIL() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isCVTCIL);
+}
+
+bool DIARawSymbol::isConstructorVirtualBase() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isConstructorVirtualBase);
+}
+
+bool DIARawSymbol::isCxxReturnUdt() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isCxxReturnUdt);
+}
+
+bool DIARawSymbol::isDataAligned() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isDataAligned);
+}
+
+bool DIARawSymbol::isHLSLData() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isHLSLData);
+}
+
+bool DIARawSymbol::isHotpatchable() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isHotpatchable);
+}
+
+bool DIARawSymbol::isIndirectVirtualBaseClass() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_indirectVirtualBaseClass);
+}
+
+bool DIARawSymbol::isInterfaceUdt() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isInterfaceUdt);
+}
+
+bool DIARawSymbol::isIntrinsic() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_intrinsic);
+}
+
+bool DIARawSymbol::isLTCG() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isLTCG);
+}
+
+bool DIARawSymbol::isLocationControlFlowDependent() const {
+ return PrivateGetDIAValue(Symbol,
+ &IDiaSymbol::get_isLocationControlFlowDependent);
+}
+
+bool DIARawSymbol::isMSILNetmodule() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isMSILNetmodule);
+}
+
+bool DIARawSymbol::isMatrixRowMajor() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isMatrixRowMajor);
+}
+
+bool DIARawSymbol::isManagedCode() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_managed);
+}
+
+bool DIARawSymbol::isMSILCode() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_msil);
+}
+
+bool DIARawSymbol::isMultipleInheritance() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isMultipleInheritance);
+}
+
+bool DIARawSymbol::isNaked() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isNaked);
+}
+
+bool DIARawSymbol::isNested() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_nested);
+}
+
+bool DIARawSymbol::isOptimizedAway() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isOptimizedAway);
+}
+
+bool DIARawSymbol::isPacked() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_packed);
+}
+
+bool DIARawSymbol::isPointerBasedOnSymbolValue() const {
+ return PrivateGetDIAValue(Symbol,
+ &IDiaSymbol::get_isPointerBasedOnSymbolValue);
+}
+
+bool DIARawSymbol::isPointerToDataMember() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isPointerToDataMember);
+}
+
+bool DIARawSymbol::isPointerToMemberFunction() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isPointerToMemberFunction);
+}
+
+bool DIARawSymbol::isPureVirtual() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_pure);
+}
+
+bool DIARawSymbol::isRValueReference() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_RValueReference);
+}
+
+bool DIARawSymbol::isRefUdt() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isRefUdt);
+}
+
+bool DIARawSymbol::isReference() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_reference);
+}
+
+bool DIARawSymbol::isRestrictedType() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_restrictedType);
+}
+
+bool DIARawSymbol::isReturnValue() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isReturnValue);
+}
+
+bool DIARawSymbol::isSafeBuffers() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isSafeBuffers);
+}
+
+bool DIARawSymbol::isScoped() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_scoped);
+}
+
+bool DIARawSymbol::isSdl() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isSdl);
+}
+
+bool DIARawSymbol::isSingleInheritance() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isSingleInheritance);
+}
+
+bool DIARawSymbol::isSplitted() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isSplitted);
+}
+
+bool DIARawSymbol::isStatic() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isStatic);
+}
+
+bool DIARawSymbol::hasPrivateSymbols() const {
+ // hasPrivateSymbols is the opposite of isStripped, but we expose
+ // hasPrivateSymbols as a more intuitive interface.
+ return !PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isStripped);
+}
+
+bool DIARawSymbol::isUnalignedType() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_unalignedType);
+}
+
+bool DIARawSymbol::isUnreached() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_notReached);
+}
+
+bool DIARawSymbol::isValueUdt() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isValueUdt);
+}
+
+bool DIARawSymbol::isVirtual() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtual);
+}
+
+bool DIARawSymbol::isVirtualBaseClass() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_virtualBaseClass);
+}
+
+bool DIARawSymbol::isVirtualInheritance() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_isVirtualInheritance);
+}
+
+bool DIARawSymbol::isVolatileType() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_volatileType);
+}
+
+bool DIARawSymbol::wasInlined() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_wasInlined);
+}
+
+std::string DIARawSymbol::getUnused() const {
+ return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_unused);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
new file mode 100644
index 0000000..99fe750
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASession.cpp
@@ -0,0 +1,205 @@
+//===- DIASession.cpp - DIA implementation of IPDBSession -------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumDebugStreams.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumLineNumbers.h"
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSourceFiles.h"
+#include "llvm/DebugInfo/PDB/DIA/DIARawSymbol.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/Support/ConvertUTF.h"
+
+using namespace llvm;
+
+namespace {}
+
+DIASession::DIASession(CComPtr<IDiaSession> DiaSession) : Session(DiaSession) {}
+
+PDB_ErrorCode DIASession::createFromPdb(StringRef Path,
+ std::unique_ptr<IPDBSession> &Session) {
+ CComPtr<IDiaDataSource> DiaDataSource;
+ CComPtr<IDiaSession> DiaSession;
+
+ // We assume that CoInitializeEx has already been called by the executable.
+ HRESULT Result = ::CoCreateInstance(
+ CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
+ reinterpret_cast<LPVOID *>(&DiaDataSource));
+ if (FAILED(Result))
+ return PDB_ErrorCode::NoPdbImpl;
+
+ llvm::SmallVector<UTF16, 128> Path16;
+ if (!llvm::convertUTF8ToUTF16String(Path, Path16))
+ return PDB_ErrorCode::InvalidPath;
+
+ const wchar_t *Path16Str = reinterpret_cast<const wchar_t*>(Path16.data());
+ if (FAILED(Result = DiaDataSource->loadDataFromPdb(Path16Str))) {
+ if (Result == E_PDB_NOT_FOUND)
+ return PDB_ErrorCode::InvalidPath;
+ else if (Result == E_PDB_FORMAT)
+ return PDB_ErrorCode::InvalidFileFormat;
+ else if (Result == E_INVALIDARG)
+ return PDB_ErrorCode::InvalidParameter;
+ else if (Result == E_UNEXPECTED)
+ return PDB_ErrorCode::AlreadyLoaded;
+ else
+ return PDB_ErrorCode::UnknownError;
+ }
+
+ if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
+ if (Result == E_OUTOFMEMORY)
+ return PDB_ErrorCode::NoMemory;
+ else
+ return PDB_ErrorCode::UnknownError;
+ }
+
+ Session.reset(new DIASession(DiaSession));
+ return PDB_ErrorCode::Success;
+}
+
+PDB_ErrorCode DIASession::createFromExe(StringRef Path,
+ std::unique_ptr<IPDBSession> &Session) {
+ CComPtr<IDiaDataSource> DiaDataSource;
+ CComPtr<IDiaSession> DiaSession;
+
+ // We assume that CoInitializeEx has already been called by the executable.
+ HRESULT Result = ::CoCreateInstance(
+ CLSID_DiaSource, nullptr, CLSCTX_INPROC_SERVER, IID_IDiaDataSource,
+ reinterpret_cast<LPVOID *>(&DiaDataSource));
+ if (FAILED(Result))
+ return PDB_ErrorCode::NoPdbImpl;
+
+ llvm::SmallVector<UTF16, 128> Path16;
+ if (!llvm::convertUTF8ToUTF16String(Path, Path16))
+ return PDB_ErrorCode::InvalidPath;
+
+ const wchar_t *Path16Str = reinterpret_cast<const wchar_t *>(Path16.data());
+ if (FAILED(Result =
+ DiaDataSource->loadDataForExe(Path16Str, nullptr, nullptr))) {
+ if (Result == E_PDB_NOT_FOUND)
+ return PDB_ErrorCode::InvalidPath;
+ else if (Result == E_PDB_FORMAT)
+ return PDB_ErrorCode::InvalidFileFormat;
+ else if (Result == E_PDB_INVALID_SIG || Result == E_PDB_INVALID_AGE)
+ return PDB_ErrorCode::DebugInfoMismatch;
+ else if (Result == E_INVALIDARG)
+ return PDB_ErrorCode::InvalidParameter;
+ else if (Result == E_UNEXPECTED)
+ return PDB_ErrorCode::AlreadyLoaded;
+ else
+ return PDB_ErrorCode::UnknownError;
+ }
+
+ if (FAILED(Result = DiaDataSource->openSession(&DiaSession))) {
+ if (Result == E_OUTOFMEMORY)
+ return PDB_ErrorCode::NoMemory;
+ else
+ return PDB_ErrorCode::UnknownError;
+ }
+
+ Session.reset(new DIASession(DiaSession));
+ return PDB_ErrorCode::Success;
+}
+
+uint64_t DIASession::getLoadAddress() const {
+ uint64_t LoadAddress;
+ bool success = (S_OK == Session->get_loadAddress(&LoadAddress));
+ return (success) ? LoadAddress : 0;
+}
+
+void DIASession::setLoadAddress(uint64_t Address) {
+ Session->put_loadAddress(Address);
+}
+
+std::unique_ptr<PDBSymbolExe> DIASession::getGlobalScope() const {
+ CComPtr<IDiaSymbol> GlobalScope;
+ if (S_OK != Session->get_globalScope(&GlobalScope))
+ return nullptr;
+
+ auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, GlobalScope);
+ auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol)));
+ std::unique_ptr<PDBSymbolExe> ExeSymbol(
+ static_cast<PDBSymbolExe *>(PdbSymbol.release()));
+ return ExeSymbol;
+}
+
+std::unique_ptr<PDBSymbol> DIASession::getSymbolById(uint32_t SymbolId) const {
+ CComPtr<IDiaSymbol> LocatedSymbol;
+ if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol))
+ return nullptr;
+
+ auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, LocatedSymbol);
+ return PDBSymbol::create(*this, std::move(RawSymbol));
+}
+
+std::unique_ptr<PDBSymbol>
+DIASession::findSymbolByAddress(uint64_t Address, PDB_SymType Type) const {
+ enum SymTagEnum EnumVal = static_cast<enum SymTagEnum>(Type);
+
+ CComPtr<IDiaSymbol> Symbol;
+ if (S_OK != Session->findSymbolByVA(Address, EnumVal, &Symbol)) {
+ ULONGLONG LoadAddr = 0;
+ if (S_OK != Session->get_loadAddress(&LoadAddr))
+ return nullptr;
+ DWORD RVA = static_cast<DWORD>(Address - LoadAddr);
+ if (S_OK != Session->findSymbolByRVA(RVA, EnumVal, &Symbol))
+ return nullptr;
+ }
+ auto RawSymbol = llvm::make_unique<DIARawSymbol>(*this, Symbol);
+ return PDBSymbol::create(*this, std::move(RawSymbol));
+}
+
+std::unique_ptr<IPDBEnumLineNumbers>
+DIASession::findLineNumbersByAddress(uint64_t Address, uint32_t Length) const {
+ CComPtr<IDiaEnumLineNumbers> LineNumbers;
+ if (S_OK != Session->findLinesByVA(Address, Length, &LineNumbers))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumLineNumbers>(LineNumbers);
+}
+
+std::unique_ptr<IPDBEnumSourceFiles> DIASession::getAllSourceFiles() const {
+ CComPtr<IDiaEnumSourceFiles> Files;
+ if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
+}
+
+std::unique_ptr<IPDBEnumSourceFiles> DIASession::getSourceFilesForCompiland(
+ const PDBSymbolCompiland &Compiland) const {
+ CComPtr<IDiaEnumSourceFiles> Files;
+
+ const DIARawSymbol &RawSymbol =
+ static_cast<const DIARawSymbol &>(Compiland.getRawSymbol());
+ if (S_OK !=
+ Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumSourceFiles>(*this, Files);
+}
+
+std::unique_ptr<IPDBSourceFile>
+DIASession::getSourceFileById(uint32_t FileId) const {
+ CComPtr<IDiaSourceFile> LocatedFile;
+ if (S_OK != Session->findFileById(FileId, &LocatedFile))
+ return nullptr;
+
+ return llvm::make_unique<DIASourceFile>(*this, LocatedFile);
+}
+
+std::unique_ptr<IPDBEnumDataStreams> DIASession::getDebugStreams() const {
+ CComPtr<IDiaEnumDebugStreams> DiaEnumerator;
+ if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator))
+ return nullptr;
+
+ return llvm::make_unique<DIAEnumDebugStreams>(DiaEnumerator);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp
new file mode 100644
index 0000000..0a9c444
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp
@@ -0,0 +1,67 @@
+//===- DIASourceFile.cpp - DIA implementation of IPDBSourceFile -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/DIA/DIAEnumSymbols.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#include "llvm/DebugInfo/PDB/DIA/DIASourceFile.h"
+#include "llvm/Support/ConvertUTF.h"
+
+using namespace llvm;
+
+DIASourceFile::DIASourceFile(const DIASession &PDBSession,
+ CComPtr<IDiaSourceFile> DiaSourceFile)
+ : Session(PDBSession), SourceFile(DiaSourceFile) {}
+
+std::string DIASourceFile::getFileName() const {
+ CComBSTR FileName16;
+ HRESULT Result = SourceFile->get_fileName(&FileName16);
+ if (S_OK != Result)
+ return std::string();
+
+ std::string FileName8;
+ llvm::ArrayRef<char> FileNameBytes(reinterpret_cast<char *>(FileName16.m_str),
+ FileName16.ByteLength());
+ llvm::convertUTF16ToUTF8String(FileNameBytes, FileName8);
+ return FileName8;
+}
+
+uint32_t DIASourceFile::getUniqueId() const {
+ DWORD Id;
+ return (S_OK == SourceFile->get_uniqueId(&Id)) ? Id : 0;
+}
+
+std::string DIASourceFile::getChecksum() const {
+ DWORD ByteSize = 0;
+ HRESULT Result = SourceFile->get_checksum(0, &ByteSize, nullptr);
+ if (ByteSize == 0)
+ return std::string();
+ std::vector<BYTE> ChecksumBytes(ByteSize);
+ Result = SourceFile->get_checksum(ByteSize, &ByteSize, &ChecksumBytes[0]);
+ if (S_OK != Result)
+ return std::string();
+ return std::string(ChecksumBytes.begin(), ChecksumBytes.end());
+}
+
+PDB_Checksum DIASourceFile::getChecksumType() const {
+ DWORD Type;
+ HRESULT Result = SourceFile->get_checksumType(&Type);
+ if (S_OK != Result)
+ return PDB_Checksum::None;
+ return static_cast<PDB_Checksum>(Type);
+}
+
+std::unique_ptr<IPDBEnumSymbols> DIASourceFile::getCompilands() const {
+ CComPtr<IDiaEnumSymbols> DiaEnumerator;
+ HRESULT Result = SourceFile->get_compilands(&DiaEnumerator);
+ if (S_OK != Result)
+ return nullptr;
+
+ return std::unique_ptr<IPDBEnumSymbols>(
+ new DIAEnumSymbols(Session, DiaEnumerator));
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp b/contrib/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp
new file mode 100644
index 0000000..3abe59d
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/IPDBSourceFile.cpp
@@ -0,0 +1,32 @@
+//===- IPDBSourceFile.cpp - base interface for a PDB source file *- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+IPDBSourceFile::~IPDBSourceFile() {}
+
+void IPDBSourceFile::dump(raw_ostream &OS, int Indent) const {
+ OS.indent(Indent);
+ PDB_Checksum ChecksumType = getChecksumType();
+ OS << "[";
+ if (ChecksumType != PDB_Checksum::None) {
+ OS << ChecksumType << ": ";
+ std::string Checksum = getChecksum();
+ for (uint8_t c : Checksum)
+ OS << format_hex_no_prefix(c, 2, true);
+ } else
+ OS << "No checksum";
+ OS << "] " << getFileName() << "\n";
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp
new file mode 100644
index 0000000..613407e
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDB.cpp
@@ -0,0 +1,39 @@
+//===- PDB.cpp - base header file for creating a PDB reader -----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDB.h"
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+
+#if HAVE_DIA_SDK
+#include "llvm/DebugInfo/PDB/DIA/DIASession.h"
+#endif
+
+using namespace llvm;
+
+PDB_ErrorCode llvm::loadDataForPDB(PDB_ReaderType Type, StringRef Path,
+ std::unique_ptr<IPDBSession> &Session) {
+ // Create the correct concrete instance type based on the value of Type.
+#if HAVE_DIA_SDK
+ return DIASession::createFromPdb(Path, Session);
+#endif
+ return PDB_ErrorCode::NoPdbImpl;
+}
+
+PDB_ErrorCode llvm::loadDataForEXE(PDB_ReaderType Type, StringRef Path,
+ std::unique_ptr<IPDBSession> &Session) {
+ // Create the correct concrete instance type based on the value of Type.
+#if HAVE_DIA_SDK
+ return DIASession::createFromExe(Path, Session);
+#endif
+ return PDB_ErrorCode::NoPdbImpl;
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp
new file mode 100644
index 0000000..ca2ae66
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBContext.cpp
@@ -0,0 +1,120 @@
+//===-- PDBContext.cpp ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===/
+
+#include "llvm/DebugInfo/PDB/PDBContext.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBSourceFile.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/Object/COFF.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+PDBContext::PDBContext(const COFFObjectFile &Object,
+ std::unique_ptr<IPDBSession> PDBSession)
+ : DIContext(CK_PDB), Session(std::move(PDBSession)) {
+ ErrorOr<uint64_t> ImageBase = Object.getImageBase();
+ if (ImageBase)
+ Session->setLoadAddress(ImageBase.get());
+}
+
+void PDBContext::dump(raw_ostream &OS, DIDumpType DumpType) {}
+
+DILineInfo PDBContext::getLineInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Specifier) {
+ DILineInfo Result;
+ Result.FunctionName = getFunctionName(Address, Specifier.FNKind);
+
+ uint32_t Length = 1;
+ std::unique_ptr<PDBSymbol> Symbol =
+ Session->findSymbolByAddress(Address, PDB_SymType::None);
+ if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(Symbol.get())) {
+ Length = Func->getLength();
+ } else if (auto Data = dyn_cast_or_null<PDBSymbolData>(Symbol.get())) {
+ Length = Data->getLength();
+ }
+
+ // If we couldn't find a symbol, then just assume 1 byte, so that we get
+ // only the line number of the first instruction.
+ auto LineNumbers = Session->findLineNumbersByAddress(Address, Length);
+ if (!LineNumbers || LineNumbers->getChildCount() == 0)
+ return Result;
+
+ auto LineInfo = LineNumbers->getNext();
+ assert(LineInfo);
+ auto SourceFile = Session->getSourceFileById(LineInfo->getSourceFileId());
+
+ if (SourceFile &&
+ Specifier.FLIKind != DILineInfoSpecifier::FileLineInfoKind::None)
+ Result.FileName = SourceFile->getFileName();
+ Result.Column = LineInfo->getColumnNumber();
+ Result.Line = LineInfo->getLineNumber();
+ return Result;
+}
+
+DILineInfoTable
+PDBContext::getLineInfoForAddressRange(uint64_t Address, uint64_t Size,
+ DILineInfoSpecifier Specifier) {
+ if (Size == 0)
+ return DILineInfoTable();
+
+ DILineInfoTable Table;
+ auto LineNumbers = Session->findLineNumbersByAddress(Address, Size);
+ if (!LineNumbers || LineNumbers->getChildCount() == 0)
+ return Table;
+
+ while (auto LineInfo = LineNumbers->getNext()) {
+ DILineInfo LineEntry =
+ getLineInfoForAddress(LineInfo->getVirtualAddress(), Specifier);
+ Table.push_back(std::make_pair(LineInfo->getVirtualAddress(), LineEntry));
+ }
+ return Table;
+}
+
+DIInliningInfo
+PDBContext::getInliningInfoForAddress(uint64_t Address,
+ DILineInfoSpecifier Specifier) {
+ DIInliningInfo InlineInfo;
+ DILineInfo Frame = getLineInfoForAddress(Address, Specifier);
+ InlineInfo.addFrame(Frame);
+ return InlineInfo;
+}
+
+std::string PDBContext::getFunctionName(uint64_t Address,
+ DINameKind NameKind) const {
+ if (NameKind == DINameKind::None)
+ return std::string();
+
+ if (NameKind == DINameKind::LinkageName) {
+ // It is not possible to get the mangled linkage name through a
+ // PDBSymbolFunc. For that we have to specifically request a
+ // PDBSymbolPublicSymbol.
+ auto PublicSym =
+ Session->findSymbolByAddress(Address, PDB_SymType::PublicSymbol);
+ if (auto PS = dyn_cast_or_null<PDBSymbolPublicSymbol>(PublicSym.get()))
+ return PS->getName();
+ }
+
+ auto FuncSymbol =
+ Session->findSymbolByAddress(Address, PDB_SymType::Function);
+
+ // This could happen either if there was no public symbol (e.g. not
+ // external) or the user requested the short name. In the former case,
+ // although they technically requested the linkage name, if the linkage
+ // name is not available we fallback to at least returning a non-empty
+ // string.
+ if (auto Func = dyn_cast_or_null<PDBSymbolFunc>(FuncSymbol.get()))
+ return Func->getName();
+
+ return std::string();
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp
new file mode 100644
index 0000000..4b9437c
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBExtras.cpp
@@ -0,0 +1,339 @@
+//===- PDBExtras.cpp - helper functions and classes for PDBs -----*- C++-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBExtras.h"
+
+#include "llvm/ADT/ArrayRef.h"
+
+using namespace llvm;
+
+#define CASE_OUTPUT_ENUM_CLASS_STR(Class, Value, Str, Stream) \
+ case Class::Value: \
+ Stream << Str; \
+ break;
+
+#define CASE_OUTPUT_ENUM_CLASS_NAME(Class, Value, Stream) \
+ CASE_OUTPUT_ENUM_CLASS_STR(Class, Value, #Value, Stream)
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_VariantType &Type) {
+ switch (Type) {
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Bool, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Single, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Double, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Int8, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Int16, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Int32, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, Int64, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, UInt8, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, UInt16, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, UInt32, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_VariantType, UInt64, OS)
+ default:
+ OS << "Unknown";
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_CallingConv &Conv) {
+ OS << "__";
+ switch (Conv) {
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearCdecl, "cdecl", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarCdecl, "cdecl", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearPascal, "pascal", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarPascal, "pascal", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearFastcall, "fastcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarFastcall, "fastcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Skipped, "skippedcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearStdcall, "stdcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarStdcall, "stdcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearSyscall, "syscall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, FarSyscall, "syscall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Thiscall, "thiscall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, MipsCall, "mipscall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Generic, "genericcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Alphacall, "alphacall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Ppccall, "ppccall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, SuperHCall, "superhcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Armcall, "armcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, AM33call, "am33call", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Tricall, "tricall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Sh5call, "sh5call", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, M32R, "m32rcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Clrcall, "clrcall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, Inline, "inlinecall", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_CallingConv, NearVectorcall, "vectorcall",
+ OS)
+ default:
+ OS << "unknowncall";
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_DataKind &Data) {
+ switch (Data) {
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Unknown, "unknown", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Local, "local", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, StaticLocal, "static local", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Param, "param", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, ObjectPtr, "this ptr", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, FileStatic, "static global", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Global, "global", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Member, "member", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, StaticMember, "static member", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_DataKind, Constant, "const", OS)
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_RegisterId &Reg) {
+ switch (Reg) {
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, AL, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, CL, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, DL, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, BL, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, AH, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, CH, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, DH, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, BH, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, AX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, CX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, DX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, BX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, SP, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, BP, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, SI, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, DI, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, EAX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, ECX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, EDX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, EBX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, ESP, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, EBP, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, ESI, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, EDI, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, ES, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, CS, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, SS, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, DS, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, FS, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, GS, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, IP, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, RAX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, RBX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, RCX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, RDX, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, RSI, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, RDI, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, RBP, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, RSP, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, R8, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, R9, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, R10, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, R11, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, R12, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, R13, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, R14, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_RegisterId, R15, OS)
+ default:
+ OS << static_cast<int>(Reg);
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_LocType &Loc) {
+ switch (Loc) {
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, Static, "static", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, TLS, "tls", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, RegRel, "regrel", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, ThisRel, "thisrel", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, Enregistered, "register", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, BitField, "bitfield", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, Slot, "slot", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, IlRel, "IL rel", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, MetaData, "metadata", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_LocType, Constant, "constant", OS)
+ default:
+ OS << "Unknown";
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_ThunkOrdinal &Thunk) {
+ switch (Thunk) {
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_ThunkOrdinal, BranchIsland, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_ThunkOrdinal, Pcode, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_ThunkOrdinal, Standard, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_ThunkOrdinal, ThisAdjustor, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_ThunkOrdinal, TrampIncremental, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_ThunkOrdinal, UnknownLoad, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_ThunkOrdinal, Vcall, OS)
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_Checksum &Checksum) {
+ switch (Checksum) {
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, None, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, MD5, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Checksum, SHA1, OS)
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_Lang &Lang) {
+ switch (Lang) {
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, C, OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_Lang, Cpp, "C++", OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Fortran, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Masm, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Pascal, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Basic, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Cobol, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Link, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Cvtres, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Cvtpgd, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, CSharp, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, VB, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, ILAsm, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, Java, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, JScript, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, MSIL, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_Lang, HLSL, OS)
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_SymType &Tag) {
+ switch (Tag) {
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Exe, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Compiland, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CompilandDetails, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CompilandEnv, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Function, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Block, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Data, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Annotation, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Label, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, PublicSymbol, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, UDT, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Enum, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, FunctionSig, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, PointerType, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, ArrayType, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, BuiltinType, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Typedef, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, BaseClass, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Friend, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, FunctionArg, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, FuncDebugStart, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, FuncDebugEnd, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, UsingNamespace, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, VTableShape, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, VTable, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Custom, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Thunk, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, CustomType, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, ManagedType, OS)
+ CASE_OUTPUT_ENUM_CLASS_NAME(PDB_SymType, Dimension, OS)
+ default:
+ OS << "Unknown";
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_MemberAccess &Access) {
+ switch (Access) {
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Public, "public", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Protected, "protected", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_MemberAccess, Private, "private", OS)
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UdtType &Type) {
+ switch (Type) {
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Class, "class", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Struct, "struct", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Interface, "interface", OS)
+ CASE_OUTPUT_ENUM_CLASS_STR(PDB_UdtType, Union, "union", OS)
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const PDB_UniqueId &Id) {
+ static const char *Lookup = "0123456789ABCDEF";
+
+ static_assert(sizeof(PDB_UniqueId) == 16, "Expected 16-byte GUID");
+ ArrayRef<uint8_t> GuidBytes(reinterpret_cast<const uint8_t*>(&Id), 16);
+ OS << "{";
+ for (int i=0; i < 16;) {
+ uint8_t Byte = GuidBytes[i];
+ uint8_t HighNibble = (Byte >> 4) & 0xF;
+ uint8_t LowNibble = Byte & 0xF;
+ OS << Lookup[HighNibble] << Lookup[LowNibble];
+ ++i;
+ if (i>=4 && i<=10 && i%2==0)
+ OS << "-";
+ }
+ OS << "}";
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const Variant &Value) {
+ switch (Value.Type) {
+ case PDB_VariantType::Bool:
+ OS << (Value.Bool ? "true" : "false");
+ break;
+ case PDB_VariantType::Double:
+ OS << Value.Double;
+ break;
+ case PDB_VariantType::Int16:
+ OS << Value.Int16;
+ break;
+ case PDB_VariantType::Int32:
+ OS << Value.Int32;
+ break;
+ case PDB_VariantType::Int64:
+ OS << Value.Int64;
+ break;
+ case PDB_VariantType::Int8:
+ OS << static_cast<int>(Value.Int8);
+ break;
+ case PDB_VariantType::Single:
+ OS << Value.Single;
+ break;
+ case PDB_VariantType::UInt16:
+ OS << Value.Double;
+ break;
+ case PDB_VariantType::UInt32:
+ OS << Value.UInt32;
+ break;
+ case PDB_VariantType::UInt64:
+ OS << Value.UInt64;
+ break;
+ case PDB_VariantType::UInt8:
+ OS << static_cast<unsigned>(Value.UInt8);
+ break;
+ default:
+ OS << Value.Type;
+ }
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const VersionInfo &Version) {
+ OS << Version.Major << "." << Version.Minor << "." << Version.Build;
+ return OS;
+}
+
+raw_ostream &llvm::operator<<(raw_ostream &OS, const TagStats &Stats) {
+ for (auto Tag : Stats) {
+ OS << Tag.first << ":" << Tag.second << " ";
+ }
+ return OS;
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
new file mode 100644
index 0000000..7b6268d
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp
@@ -0,0 +1,28 @@
+//===- PDBInterfaceAnchors.h - defines class anchor funcions ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+// Class anchors are necessary per the LLVM Coding style guide, to ensure that
+// the vtable is only generated in this object file, and not in every object
+// file that incldues the corresponding header.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/IPDBDataStream.h"
+#include "llvm/DebugInfo/PDB/IPDBLineNumber.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+
+using namespace llvm;
+
+IPDBSession::~IPDBSession() {}
+
+IPDBDataStream::~IPDBDataStream() {}
+
+IPDBRawSymbol::~IPDBRawSymbol() {}
+
+IPDBLineNumber::~IPDBLineNumber() {}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp
new file mode 100644
index 0000000..121e2d1
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymDumper.cpp
@@ -0,0 +1,146 @@
+//===- PDBSymDumper.cpp - ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace llvm;
+
+#define PDB_SYMDUMP_UNREACHABLE(Type) \
+ if (RequireImpl) \
+ llvm_unreachable("Attempt to dump " #Type " with no dump implementation");
+
+PDBSymDumper::PDBSymDumper(bool ShouldRequireImpl)
+ : RequireImpl(ShouldRequireImpl) {}
+
+PDBSymDumper::~PDBSymDumper() {}
+
+void PDBSymDumper::dump(const PDBSymbolAnnotation &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolAnnotation)
+}
+
+void PDBSymDumper::dump(const PDBSymbolBlock &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolBlock)
+}
+
+void PDBSymDumper::dump(const PDBSymbolCompiland &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolCompiland)
+}
+
+void PDBSymDumper::dump(const PDBSymbolCompilandDetails &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolCompilandDetails)
+}
+
+void PDBSymDumper::dump(const PDBSymbolCompilandEnv &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolCompilandEnv)
+}
+
+void PDBSymDumper::dump(const PDBSymbolCustom &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolCustom)
+}
+
+void PDBSymDumper::dump(const PDBSymbolData &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolData)
+}
+
+void PDBSymDumper::dump(const PDBSymbolExe &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolExe)
+}
+
+void PDBSymDumper::dump(const PDBSymbolFunc &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolFunc)
+}
+
+void PDBSymDumper::dump(const PDBSymbolFuncDebugEnd &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolFuncDebugEnd)
+}
+
+void PDBSymDumper::dump(const PDBSymbolFuncDebugStart &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolFuncDebugStart)
+}
+
+void PDBSymDumper::dump(const PDBSymbolLabel &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolLabel)
+}
+
+void PDBSymDumper::dump(const PDBSymbolPublicSymbol &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolPublicSymbol)
+}
+
+void PDBSymDumper::dump(const PDBSymbolThunk &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolThunk)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeArray &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeArray)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeBaseClass &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeBaseClass)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeBuiltin &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeBuiltin)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeCustom &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeCustom)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeDimension &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeDimension)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeEnum &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeEnum)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeFriend &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeFriend)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeFunctionArg &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeFunctionArg)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeFunctionSig &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeFunctionSig)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeManaged &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeManaged)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypePointer &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypePointer)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeTypedef &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeTypedef)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeUDT &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeUDT)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeVTable &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeVTable)
+}
+
+void PDBSymDumper::dump(const PDBSymbolTypeVTableShape &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeVTableShape)
+}
+
+void PDBSymDumper::dump(const PDBSymbolUnknown &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolUnknown)
+}
+
+void PDBSymDumper::dump(const PDBSymbolUsingNamespace &Symbol) {
+ PDB_SYMDUMP_UNREACHABLE(PDBSymbolUsingNamespace)
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
new file mode 100644
index 0000000..f9aaf3a
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbol.cpp
@@ -0,0 +1,151 @@
+//===- PDBSymbol.cpp - base class for user-facing symbol types --*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolAnnotation.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolCustom.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include <memory>
+#include <utility>
+
+#include <memory>
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbol::PDBSymbol(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : Session(PDBSession), RawSymbol(std::move(Symbol)) {}
+
+PDBSymbol::~PDBSymbol() {}
+
+#define FACTORY_SYMTAG_CASE(Tag, Type) \
+ case PDB_SymType::Tag: \
+ return std::unique_ptr<PDBSymbol>(new Type(PDBSession, std::move(Symbol)));
+
+std::unique_ptr<PDBSymbol>
+PDBSymbol::create(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol) {
+ switch (Symbol->getSymTag()) {
+ FACTORY_SYMTAG_CASE(Exe, PDBSymbolExe)
+ FACTORY_SYMTAG_CASE(Compiland, PDBSymbolCompiland)
+ FACTORY_SYMTAG_CASE(CompilandDetails, PDBSymbolCompilandDetails)
+ FACTORY_SYMTAG_CASE(CompilandEnv, PDBSymbolCompilandEnv)
+ FACTORY_SYMTAG_CASE(Function, PDBSymbolFunc)
+ FACTORY_SYMTAG_CASE(Block, PDBSymbolBlock)
+ FACTORY_SYMTAG_CASE(Data, PDBSymbolData)
+ FACTORY_SYMTAG_CASE(Annotation, PDBSymbolAnnotation)
+ FACTORY_SYMTAG_CASE(Label, PDBSymbolLabel)
+ FACTORY_SYMTAG_CASE(PublicSymbol, PDBSymbolPublicSymbol)
+ FACTORY_SYMTAG_CASE(UDT, PDBSymbolTypeUDT)
+ FACTORY_SYMTAG_CASE(Enum, PDBSymbolTypeEnum)
+ FACTORY_SYMTAG_CASE(FunctionSig, PDBSymbolTypeFunctionSig)
+ FACTORY_SYMTAG_CASE(PointerType, PDBSymbolTypePointer)
+ FACTORY_SYMTAG_CASE(ArrayType, PDBSymbolTypeArray)
+ FACTORY_SYMTAG_CASE(BuiltinType, PDBSymbolTypeBuiltin)
+ FACTORY_SYMTAG_CASE(Typedef, PDBSymbolTypeTypedef)
+ FACTORY_SYMTAG_CASE(BaseClass, PDBSymbolTypeBaseClass)
+ FACTORY_SYMTAG_CASE(Friend, PDBSymbolTypeFriend)
+ FACTORY_SYMTAG_CASE(FunctionArg, PDBSymbolTypeFunctionArg)
+ FACTORY_SYMTAG_CASE(FuncDebugStart, PDBSymbolFuncDebugStart)
+ FACTORY_SYMTAG_CASE(FuncDebugEnd, PDBSymbolFuncDebugEnd)
+ FACTORY_SYMTAG_CASE(UsingNamespace, PDBSymbolUsingNamespace)
+ FACTORY_SYMTAG_CASE(VTableShape, PDBSymbolTypeVTableShape)
+ FACTORY_SYMTAG_CASE(VTable, PDBSymbolTypeVTable)
+ FACTORY_SYMTAG_CASE(Custom, PDBSymbolCustom)
+ FACTORY_SYMTAG_CASE(Thunk, PDBSymbolThunk)
+ FACTORY_SYMTAG_CASE(CustomType, PDBSymbolTypeCustom)
+ FACTORY_SYMTAG_CASE(ManagedType, PDBSymbolTypeManaged)
+ FACTORY_SYMTAG_CASE(Dimension, PDBSymbolTypeDimension)
+ default:
+ return std::unique_ptr<PDBSymbol>(
+ new PDBSymbolUnknown(PDBSession, std::move(Symbol)));
+ }
+}
+
+#define TRY_DUMP_TYPE(Type) \
+ if (const Type *DerivedThis = dyn_cast<Type>(this)) \
+ Dumper.dump(OS, Indent, *DerivedThis);
+
+#define ELSE_TRY_DUMP_TYPE(Type, Dumper) else TRY_DUMP_TYPE(Type, Dumper)
+
+void PDBSymbol::defaultDump(raw_ostream &OS, int Indent) const {
+ RawSymbol->dump(OS, Indent);
+}
+
+PDB_SymType PDBSymbol::getSymTag() const { return RawSymbol->getSymTag(); }
+
+std::unique_ptr<IPDBEnumSymbols> PDBSymbol::findAllChildren() const {
+ return findAllChildren(PDB_SymType::None);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findAllChildren(PDB_SymType Type) const {
+ return RawSymbol->findChildren(Type);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findChildren(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags) const {
+ return RawSymbol->findChildren(Type, Name, Flags);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name,
+ PDB_NameSearchFlags Flags, uint32_t RVA) const {
+ return RawSymbol->findChildrenByRVA(Type, Name, Flags, RVA);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const {
+ return RawSymbol->findInlineFramesByRVA(RVA);
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbol::getChildStats(TagStats &Stats) const {
+ std::unique_ptr<IPDBEnumSymbols> Result(findAllChildren());
+ Stats.clear();
+ while (auto Child = Result->getNext()) {
+ ++Stats[Child->getSymTag()];
+ }
+ Result->reset();
+ return Result;
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp
new file mode 100644
index 0000000..a782cad
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp
@@ -0,0 +1,24 @@
+//===- PDBSymbolAnnotation.cpp - --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolAnnotation.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolAnnotation::PDBSymbolAnnotation(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolAnnotation::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp
new file mode 100644
index 0000000..46b0ea5
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolBlock.cpp
@@ -0,0 +1,23 @@
+//===- PDBSymbolBlock.cpp - -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolBlock.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolBlock::PDBSymbolBlock(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolBlock::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
new file mode 100644
index 0000000..7436914
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp
@@ -0,0 +1,24 @@
+//===- PDBSymbolCompiland.cpp - compiland details --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolCompiland.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolCompiland::PDBSymbolCompiland(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolCompiland::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp
new file mode 100644
index 0000000..7b351a0
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolCompilandDetails.cpp - compiland details --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandDetails.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolCompilandDetails::PDBSymbolCompilandDetails(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolCompilandDetails::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp
new file mode 100644
index 0000000..e863ccf
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp
@@ -0,0 +1,31 @@
+//===- PDBSymbolCompilandEnv.cpp - compiland env variables ------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolCompilandEnv.h"
+
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolCompilandEnv::PDBSymbolCompilandEnv(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+std::string PDBSymbolCompilandEnv::getValue() const {
+ // call RawSymbol->getValue() and convert the result to an std::string.
+ return std::string();
+}
+
+void PDBSymbolCompilandEnv::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp
new file mode 100644
index 0000000..bd7d9cd
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolCustom.cpp
@@ -0,0 +1,28 @@
+//===- PDBSymbolCustom.cpp - compiler-specific types ------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolCustom.h"
+
+#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolCustom::PDBSymbolCustom(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> CustomSymbol)
+ : PDBSymbol(PDBSession, std::move(CustomSymbol)) {}
+
+void PDBSymbolCustom::getDataBytes(llvm::SmallVector<uint8_t, 32> &bytes) {
+ RawSymbol->getDataBytes(bytes);
+}
+
+void PDBSymbolCustom::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
new file mode 100644
index 0000000..a948c2d
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolData.cpp
@@ -0,0 +1,27 @@
+//===- PDBSymbolData.cpp - PDB data (e.g. variable) accessors ---*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolData::PDBSymbolData(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> DataSymbol)
+ : PDBSymbol(PDBSession, std::move(DataSymbol)) {}
+
+std::unique_ptr<PDBSymbol> PDBSymbolData::getType() const {
+ return Session.getSymbolById(getTypeId());
+}
+
+void PDBSymbolData::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
new file mode 100644
index 0000000..c9e34ea
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolExe.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolExe.cpp - ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolExe.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolExe::PDBSymbolExe(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolExe::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
new file mode 100644
index 0000000..0aff327
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFunc.cpp
@@ -0,0 +1,102 @@
+//===- PDBSymbolFunc.cpp - --------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
+
+#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBTypes.h"
+
+#include <unordered_set>
+#include <utility>
+#include <vector>
+
+using namespace llvm;
+
+namespace {
+class FunctionArgEnumerator : public IPDBEnumChildren<PDBSymbolData> {
+public:
+ typedef ConcreteSymbolEnumerator<PDBSymbolData> ArgEnumeratorType;
+
+ FunctionArgEnumerator(const IPDBSession &PDBSession,
+ const PDBSymbolFunc &PDBFunc)
+ : Session(PDBSession), Func(PDBFunc) {
+ // Arguments can appear multiple times if they have live range
+ // information, so we only take the first occurrence.
+ std::unordered_set<std::string> SeenNames;
+ auto DataChildren = Func.findAllChildren<PDBSymbolData>();
+ while (auto Child = DataChildren->getNext()) {
+ if (Child->getDataKind() == PDB_DataKind::Param) {
+ std::string Name = Child->getName();
+ if (SeenNames.find(Name) != SeenNames.end())
+ continue;
+ Args.push_back(std::move(Child));
+ SeenNames.insert(Name);
+ }
+ }
+ reset();
+ }
+
+ uint32_t getChildCount() const override { return Args.size(); }
+
+ std::unique_ptr<PDBSymbolData>
+ getChildAtIndex(uint32_t Index) const override {
+ if (Index >= Args.size())
+ return nullptr;
+
+ return Session.getConcreteSymbolById<PDBSymbolData>(
+ Args[Index]->getSymIndexId());
+ }
+
+ std::unique_ptr<PDBSymbolData> getNext() override {
+ if (CurIter == Args.end())
+ return nullptr;
+ const auto &Result = **CurIter;
+ ++CurIter;
+ return Session.getConcreteSymbolById<PDBSymbolData>(Result.getSymIndexId());
+ }
+
+ void reset() override { CurIter = Args.empty() ? Args.end() : Args.begin(); }
+
+ FunctionArgEnumerator *clone() const override {
+ return new FunctionArgEnumerator(Session, Func);
+ }
+
+private:
+ typedef std::vector<std::unique_ptr<PDBSymbolData>> ArgListType;
+ const IPDBSession &Session;
+ const PDBSymbolFunc &Func;
+ ArgListType Args;
+ ArgListType::const_iterator CurIter;
+};
+}
+
+PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+std::unique_ptr<PDBSymbolTypeFunctionSig> PDBSymbolFunc::getSignature() const {
+ return Session.getConcreteSymbolById<PDBSymbolTypeFunctionSig>(getTypeId());
+}
+
+std::unique_ptr<IPDBEnumChildren<PDBSymbolData>>
+PDBSymbolFunc::getArguments() const {
+ return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
+}
+
+std::unique_ptr<PDBSymbolTypeUDT> PDBSymbolFunc::getClassParent() const {
+ return Session.getConcreteSymbolById<PDBSymbolTypeUDT>(getClassParentId());
+}
+
+void PDBSymbolFunc::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp
new file mode 100644
index 0000000..8e559b3
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolFuncDebugEnd.cpp - ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugEnd.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolFuncDebugEnd::PDBSymbolFuncDebugEnd(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolFuncDebugEnd::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp
new file mode 100644
index 0000000..ff4254f
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolFuncDebugStart.cpp - ----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolFuncDebugStart.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolFuncDebugStart::PDBSymbolFuncDebugStart(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolFuncDebugStart::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp
new file mode 100644
index 0000000..f39dee8
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolLabel.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolLabel.cpp - -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolLabel.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolLabel::PDBSymbolLabel(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolLabel::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp
new file mode 100644
index 0000000..bd6fe89
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolPublicSymbol.cpp - ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolPublicSymbol.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolPublicSymbol::PDBSymbolPublicSymbol(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolPublicSymbol::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp
new file mode 100644
index 0000000..733eb5f
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolThunk.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolThunk.cpp - -------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolThunk.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolThunk::PDBSymbolThunk(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolThunk::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
new file mode 100644
index 0000000..1980965
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp
@@ -0,0 +1,29 @@
+//===- PDBSymbolTypeArray.cpp - ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeArray.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeArray::PDBSymbolTypeArray(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+std::unique_ptr<PDBSymbol> PDBSymbolTypeArray::getElementType() const {
+ return Session.getSymbolById(getTypeId());
+}
+
+void PDBSymbolTypeArray::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp
new file mode 100644
index 0000000..c1f0d2f
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolTypeBaseClass.cpp - -----------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeBaseClass::PDBSymbolTypeBaseClass(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeBaseClass::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp
new file mode 100644
index 0000000..b302b66
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp
@@ -0,0 +1,24 @@
+//===- PDBSymbolTypeBuiltin.cpp - ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeBuiltin::PDBSymbolTypeBuiltin(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeBuiltin::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp
new file mode 100644
index 0000000..cc391f1
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolTypeCustom.cpp - --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeCustom.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeCustom::PDBSymbolTypeCustom(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeCustom::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp
new file mode 100644
index 0000000..1e19d0b
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp
@@ -0,0 +1,26 @@
+//===- PDBSymbolTypeDimension.cpp - --------------------------------*- C++
+//-*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeDimension.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeDimension::PDBSymbolTypeDimension(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeDimension::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp
new file mode 100644
index 0000000..8dd26a3
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp
@@ -0,0 +1,34 @@
+//===- PDBSymbolTypeEnum.cpp - --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeEnum.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeEnum::PDBSymbolTypeEnum(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+std::unique_ptr<PDBSymbolTypeUDT> PDBSymbolTypeEnum::getClassParent() const {
+ return Session.getConcreteSymbolById<PDBSymbolTypeUDT>(getClassParentId());
+}
+
+std::unique_ptr<PDBSymbolTypeBuiltin>
+PDBSymbolTypeEnum::getUnderlyingType() const {
+ return Session.getConcreteSymbolById<PDBSymbolTypeBuiltin>(getTypeId());
+}
+
+void PDBSymbolTypeEnum::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp
new file mode 100644
index 0000000..d332660
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolTypeFriend.cpp - --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFriend.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeFriend::PDBSymbolTypeFriend(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeFriend::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp
new file mode 100644
index 0000000..f8f71ea
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp
@@ -0,0 +1,24 @@
+//===- PDBSymbolTypeFunctionArg.cpp - --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeFunctionArg::PDBSymbolTypeFunctionArg(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeFunctionArg::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
new file mode 100644
index 0000000..af3563f
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp
@@ -0,0 +1,90 @@
+//===- PDBSymbolTypeFunctionSig.cpp - --------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionSig.h"
+
+#include "llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h"
+#include "llvm/DebugInfo/PDB/IPDBEnumChildren.h"
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeFunctionArg.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+namespace {
+class FunctionArgEnumerator : public IPDBEnumSymbols {
+public:
+ typedef ConcreteSymbolEnumerator<PDBSymbolTypeFunctionArg> ArgEnumeratorType;
+
+ FunctionArgEnumerator(const IPDBSession &PDBSession,
+ const PDBSymbolTypeFunctionSig &Sig)
+ : Session(PDBSession),
+ Enumerator(Sig.findAllChildren<PDBSymbolTypeFunctionArg>()) {}
+
+ FunctionArgEnumerator(const IPDBSession &PDBSession,
+ std::unique_ptr<ArgEnumeratorType> ArgEnumerator)
+ : Session(PDBSession), Enumerator(std::move(ArgEnumerator)) {}
+
+ uint32_t getChildCount() const override {
+ return Enumerator->getChildCount();
+ }
+
+ std::unique_ptr<PDBSymbol> getChildAtIndex(uint32_t Index) const override {
+ auto FunctionArgSymbol = Enumerator->getChildAtIndex(Index);
+ if (!FunctionArgSymbol)
+ return nullptr;
+ return Session.getSymbolById(FunctionArgSymbol->getTypeId());
+ }
+
+ std::unique_ptr<PDBSymbol> getNext() override {
+ auto FunctionArgSymbol = Enumerator->getNext();
+ if (!FunctionArgSymbol)
+ return nullptr;
+ return Session.getSymbolById(FunctionArgSymbol->getTypeId());
+ }
+
+ void reset() override { Enumerator->reset(); }
+
+ MyType *clone() const override {
+ std::unique_ptr<ArgEnumeratorType> Clone(Enumerator->clone());
+ return new FunctionArgEnumerator(Session, std::move(Clone));
+ }
+
+private:
+ const IPDBSession &Session;
+ std::unique_ptr<ArgEnumeratorType> Enumerator;
+};
+}
+
+PDBSymbolTypeFunctionSig::PDBSymbolTypeFunctionSig(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+std::unique_ptr<PDBSymbol> PDBSymbolTypeFunctionSig::getReturnType() const {
+ return Session.getSymbolById(getTypeId());
+}
+
+std::unique_ptr<IPDBEnumSymbols>
+PDBSymbolTypeFunctionSig::getArguments() const {
+ return llvm::make_unique<FunctionArgEnumerator>(Session, *this);
+}
+
+std::unique_ptr<PDBSymbol> PDBSymbolTypeFunctionSig::getClassParent() const {
+ uint32_t ClassId = getClassParentId();
+ if (ClassId == 0)
+ return nullptr;
+ return Session.getSymbolById(ClassId);
+}
+
+void PDBSymbolTypeFunctionSig::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp
new file mode 100644
index 0000000..a7fac30
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymboTypelManaged.cpp - ------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeManaged.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeManaged::PDBSymbolTypeManaged(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeManaged::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
new file mode 100644
index 0000000..082ed83
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp
@@ -0,0 +1,29 @@
+//===- PDBSymbolTypePointer.cpp -----------------------------------*- C++ -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
+
+#include "llvm/DebugInfo/PDB/IPDBSession.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypePointer::PDBSymbolTypePointer(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+std::unique_ptr<PDBSymbol> PDBSymbolTypePointer::getPointeeType() const {
+ return Session.getSymbolById(getTypeId());
+}
+
+void PDBSymbolTypePointer::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp
new file mode 100644
index 0000000..5a42699
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp
@@ -0,0 +1,24 @@
+//===- PDBSymbolTypeTypedef.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeTypedef.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeTypedef::PDBSymbolTypeTypedef(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeTypedef::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
new file mode 100644
index 0000000..2b5da29
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp
@@ -0,0 +1,22 @@
+//===- PDBSymbolTypeUDT.cpp - --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeUDT::PDBSymbolTypeUDT(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeUDT::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp
new file mode 100644
index 0000000..b465d023c
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp
@@ -0,0 +1,24 @@
+//===- PDBSymbolTypeVTable.cpp - --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeVTable::PDBSymbolTypeVTable(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeVTable::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp
new file mode 100644
index 0000000..16052f1
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolTypeVTableShape.cpp - ---------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTableShape.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolTypeVTableShape::PDBSymbolTypeVTableShape(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolTypeVTableShape::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp
new file mode 100644
index 0000000..48dc115
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp
@@ -0,0 +1,23 @@
+//===- PDBSymbolUnknown.cpp - -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolUnknown.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolUnknown::PDBSymbolUnknown(const IPDBSession &PDBSession,
+ std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolUnknown::dump(PDBSymDumper &Dumper) const { Dumper.dump(*this); }
diff --git a/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp
new file mode 100644
index 0000000..6cf13de
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp
@@ -0,0 +1,25 @@
+//===- PDBSymbolUsingNamespace.cpp - ------------------- --------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/PDB/PDBSymbolUsingNamespace.h"
+
+#include "llvm/DebugInfo/PDB/PDBSymbol.h"
+#include "llvm/DebugInfo/PDB/PDBSymDumper.h"
+
+#include <utility>
+
+using namespace llvm;
+
+PDBSymbolUsingNamespace::PDBSymbolUsingNamespace(
+ const IPDBSession &PDBSession, std::unique_ptr<IPDBRawSymbol> Symbol)
+ : PDBSymbol(PDBSession, std::move(Symbol)) {}
+
+void PDBSymbolUsingNamespace::dump(PDBSymDumper &Dumper) const {
+ Dumper.dump(*this);
+}
diff --git a/contrib/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp b/contrib/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
new file mode 100644
index 0000000..c6bfbc0
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/Symbolize/DIPrinter.cpp
@@ -0,0 +1,69 @@
+//===- lib/DebugInfo/Symbolize/DIPrinter.cpp ------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the DIPrinter class, which is responsible for printing
+// structures defined in DebugInfo/DIContext.h
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/Symbolize/DIPrinter.h"
+
+#include "llvm/DebugInfo/DIContext.h"
+
+namespace llvm {
+namespace symbolize {
+
+// By default, DILineInfo contains "<invalid>" for function/filename it
+// cannot fetch. We replace it to "??" to make our output closer to addr2line.
+static const char kDILineInfoBadString[] = "<invalid>";
+static const char kBadString[] = "??";
+
+void DIPrinter::printName(const DILineInfo &Info, bool Inlined) {
+ if (PrintFunctionNames) {
+ std::string FunctionName = Info.FunctionName;
+ if (FunctionName == kDILineInfoBadString)
+ FunctionName = kBadString;
+
+ StringRef Delimiter = (PrintPretty == true) ? " at " : "\n";
+ StringRef Prefix = (PrintPretty && Inlined) ? " (inlined by) " : "";
+ OS << Prefix << FunctionName << Delimiter;
+ }
+ std::string Filename = Info.FileName;
+ if (Filename == kDILineInfoBadString)
+ Filename = kBadString;
+ OS << Filename << ":" << Info.Line << ":" << Info.Column << "\n";
+}
+
+DIPrinter &DIPrinter::operator<<(const DILineInfo &Info) {
+ printName(Info, false);
+ return *this;
+}
+
+DIPrinter &DIPrinter::operator<<(const DIInliningInfo &Info) {
+ uint32_t FramesNum = Info.getNumberOfFrames();
+ if (FramesNum == 0) {
+ printName(DILineInfo(), false);
+ return *this;
+ }
+ for (uint32_t i = 0; i < FramesNum; i++)
+ printName(Info.getFrame(i), i > 0);
+ return *this;
+}
+
+DIPrinter &DIPrinter::operator<<(const DIGlobal &Global) {
+ std::string Name = Global.Name;
+ if (Name == kDILineInfoBadString)
+ Name = kBadString;
+ OS << Name << "\n";
+ OS << Global.Start << " " << Global.Size << "\n";
+ return *this;
+}
+
+}
+}
diff --git a/contrib/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp b/contrib/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
new file mode 100644
index 0000000..e314624
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp
@@ -0,0 +1,254 @@
+//===-- SymbolizableObjectFile.cpp ----------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation of SymbolizableObjectFile class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolizableObjectFile.h"
+#include "llvm/Object/SymbolSize.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+
+namespace llvm {
+namespace symbolize {
+
+using namespace object;
+
+static DILineInfoSpecifier
+getDILineInfoSpecifier(FunctionNameKind FNKind) {
+ return DILineInfoSpecifier(
+ DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FNKind);
+}
+
+ErrorOr<std::unique_ptr<SymbolizableObjectFile>>
+SymbolizableObjectFile::create(object::ObjectFile *Obj,
+ std::unique_ptr<DIContext> DICtx) {
+ std::unique_ptr<SymbolizableObjectFile> res(
+ new SymbolizableObjectFile(Obj, std::move(DICtx)));
+ std::unique_ptr<DataExtractor> OpdExtractor;
+ uint64_t OpdAddress = 0;
+ // Find the .opd (function descriptor) section if any, for big-endian
+ // PowerPC64 ELF.
+ if (Obj->getArch() == Triple::ppc64) {
+ for (section_iterator Section : Obj->sections()) {
+ StringRef Name;
+ StringRef Data;
+ if (auto EC = Section->getName(Name))
+ return EC;
+ if (Name == ".opd") {
+ if (auto EC = Section->getContents(Data))
+ return EC;
+ OpdExtractor.reset(new DataExtractor(Data, Obj->isLittleEndian(),
+ Obj->getBytesInAddress()));
+ OpdAddress = Section->getAddress();
+ break;
+ }
+ }
+ }
+ std::vector<std::pair<SymbolRef, uint64_t>> Symbols =
+ computeSymbolSizes(*Obj);
+ for (auto &P : Symbols)
+ res->addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress);
+
+ // If this is a COFF object and we didn't find any symbols, try the export
+ // table.
+ if (Symbols.empty()) {
+ if (auto *CoffObj = dyn_cast<COFFObjectFile>(Obj))
+ if (auto EC = res->addCoffExportSymbols(CoffObj))
+ return EC;
+ }
+ return std::move(res);
+}
+
+SymbolizableObjectFile::SymbolizableObjectFile(ObjectFile *Obj,
+ std::unique_ptr<DIContext> DICtx)
+ : Module(Obj), DebugInfoContext(std::move(DICtx)) {}
+
+namespace {
+struct OffsetNamePair {
+ uint32_t Offset;
+ StringRef Name;
+ bool operator<(const OffsetNamePair &R) const {
+ return Offset < R.Offset;
+ }
+};
+}
+
+std::error_code SymbolizableObjectFile::addCoffExportSymbols(
+ const COFFObjectFile *CoffObj) {
+ // Get all export names and offsets.
+ std::vector<OffsetNamePair> ExportSyms;
+ for (const ExportDirectoryEntryRef &Ref : CoffObj->export_directories()) {
+ StringRef Name;
+ uint32_t Offset;
+ if (auto EC = Ref.getSymbolName(Name))
+ return EC;
+ if (auto EC = Ref.getExportRVA(Offset))
+ return EC;
+ ExportSyms.push_back(OffsetNamePair{Offset, Name});
+ }
+ if (ExportSyms.empty())
+ return std::error_code();
+
+ // Sort by ascending offset.
+ array_pod_sort(ExportSyms.begin(), ExportSyms.end());
+
+ // Approximate the symbol sizes by assuming they run to the next symbol.
+ // FIXME: This assumes all exports are functions.
+ uint64_t ImageBase = CoffObj->getImageBase();
+ for (auto I = ExportSyms.begin(), E = ExportSyms.end(); I != E; ++I) {
+ OffsetNamePair &Export = *I;
+ // FIXME: The last export has a one byte size now.
+ uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1;
+ uint64_t SymbolStart = ImageBase + Export.Offset;
+ uint64_t SymbolSize = NextOffset - Export.Offset;
+ SymbolDesc SD = {SymbolStart, SymbolSize};
+ Functions.insert(std::make_pair(SD, Export.Name));
+ }
+ return std::error_code();
+}
+
+std::error_code SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol,
+ uint64_t SymbolSize,
+ DataExtractor *OpdExtractor,
+ uint64_t OpdAddress) {
+ SymbolRef::Type SymbolType = Symbol.getType();
+ if (SymbolType != SymbolRef::ST_Function && SymbolType != SymbolRef::ST_Data)
+ return std::error_code();
+ ErrorOr<uint64_t> SymbolAddressOrErr = Symbol.getAddress();
+ if (auto EC = SymbolAddressOrErr.getError())
+ return EC;
+ uint64_t SymbolAddress = *SymbolAddressOrErr;
+ if (OpdExtractor) {
+ // For big-endian PowerPC64 ELF, symbols in the .opd section refer to
+ // function descriptors. The first word of the descriptor is a pointer to
+ // the function's code.
+ // For the purposes of symbolization, pretend the symbol's address is that
+ // of the function's code, not the descriptor.
+ uint64_t OpdOffset = SymbolAddress - OpdAddress;
+ uint32_t OpdOffset32 = OpdOffset;
+ if (OpdOffset == OpdOffset32 &&
+ OpdExtractor->isValidOffsetForAddress(OpdOffset32))
+ SymbolAddress = OpdExtractor->getAddress(&OpdOffset32);
+ }
+ ErrorOr<StringRef> SymbolNameOrErr = Symbol.getName();
+ if (auto EC = SymbolNameOrErr.getError())
+ return EC;
+ StringRef SymbolName = *SymbolNameOrErr;
+ // Mach-O symbol table names have leading underscore, skip it.
+ if (Module->isMachO() && SymbolName.size() > 0 && SymbolName[0] == '_')
+ SymbolName = SymbolName.drop_front();
+ // FIXME: If a function has alias, there are two entries in symbol table
+ // with same address size. Make sure we choose the correct one.
+ auto &M = SymbolType == SymbolRef::ST_Function ? Functions : Objects;
+ SymbolDesc SD = { SymbolAddress, SymbolSize };
+ M.insert(std::make_pair(SD, SymbolName));
+ return std::error_code();
+}
+
+// Return true if this is a 32-bit x86 PE COFF module.
+bool SymbolizableObjectFile::isWin32Module() const {
+ auto *CoffObject = dyn_cast<COFFObjectFile>(Module);
+ return CoffObject && CoffObject->getMachine() == COFF::IMAGE_FILE_MACHINE_I386;
+}
+
+uint64_t SymbolizableObjectFile::getModulePreferredBase() const {
+ if (auto *CoffObject = dyn_cast<COFFObjectFile>(Module))
+ return CoffObject->getImageBase();
+ return 0;
+}
+
+bool SymbolizableObjectFile::getNameFromSymbolTable(SymbolRef::Type Type,
+ uint64_t Address,
+ std::string &Name,
+ uint64_t &Addr,
+ uint64_t &Size) const {
+ const auto &SymbolMap = Type == SymbolRef::ST_Function ? Functions : Objects;
+ if (SymbolMap.empty())
+ return false;
+ SymbolDesc SD = { Address, Address };
+ auto SymbolIterator = SymbolMap.upper_bound(SD);
+ if (SymbolIterator == SymbolMap.begin())
+ return false;
+ --SymbolIterator;
+ if (SymbolIterator->first.Size != 0 &&
+ SymbolIterator->first.Addr + SymbolIterator->first.Size <= Address)
+ return false;
+ Name = SymbolIterator->second.str();
+ Addr = SymbolIterator->first.Addr;
+ Size = SymbolIterator->first.Size;
+ return true;
+}
+
+bool SymbolizableObjectFile::shouldOverrideWithSymbolTable(
+ FunctionNameKind FNKind, bool UseSymbolTable) const {
+ // When DWARF is used with -gline-tables-only / -gmlt, the symbol table gives
+ // better answers for linkage names than the DIContext. Otherwise, we are
+ // probably using PEs and PDBs, and we shouldn't do the override. PE files
+ // generally only contain the names of exported symbols.
+ return FNKind == FunctionNameKind::LinkageName && UseSymbolTable &&
+ isa<DWARFContext>(DebugInfoContext.get());
+}
+
+DILineInfo SymbolizableObjectFile::symbolizeCode(uint64_t ModuleOffset,
+ FunctionNameKind FNKind,
+ bool UseSymbolTable) const {
+ DILineInfo LineInfo;
+ if (DebugInfoContext) {
+ LineInfo = DebugInfoContext->getLineInfoForAddress(
+ ModuleOffset, getDILineInfoSpecifier(FNKind));
+ }
+ // Override function name from symbol table if necessary.
+ if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) {
+ std::string FunctionName;
+ uint64_t Start, Size;
+ if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
+ FunctionName, Start, Size)) {
+ LineInfo.FunctionName = FunctionName;
+ }
+ }
+ return LineInfo;
+}
+
+DIInliningInfo SymbolizableObjectFile::symbolizeInlinedCode(
+ uint64_t ModuleOffset, FunctionNameKind FNKind, bool UseSymbolTable) const {
+ DIInliningInfo InlinedContext;
+
+ if (DebugInfoContext)
+ InlinedContext = DebugInfoContext->getInliningInfoForAddress(
+ ModuleOffset, getDILineInfoSpecifier(FNKind));
+ // Make sure there is at least one frame in context.
+ if (InlinedContext.getNumberOfFrames() == 0)
+ InlinedContext.addFrame(DILineInfo());
+
+ // Override the function name in lower frame with name from symbol table.
+ if (shouldOverrideWithSymbolTable(FNKind, UseSymbolTable)) {
+ std::string FunctionName;
+ uint64_t Start, Size;
+ if (getNameFromSymbolTable(SymbolRef::ST_Function, ModuleOffset,
+ FunctionName, Start, Size)) {
+ InlinedContext.getMutableFrame(InlinedContext.getNumberOfFrames() - 1)
+ ->FunctionName = FunctionName;
+ }
+ }
+
+ return InlinedContext;
+}
+
+DIGlobal SymbolizableObjectFile::symbolizeData(uint64_t ModuleOffset) const {
+ DIGlobal Res;
+ getNameFromSymbolTable(SymbolRef::ST_Data, ModuleOffset, Res.Name, Res.Start,
+ Res.Size);
+ return Res;
+}
+
+} // namespace symbolize
+} // namespace llvm
+
diff --git a/contrib/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h b/contrib/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h
new file mode 100644
index 0000000..8583b6a
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/Symbolize/SymbolizableObjectFile.h
@@ -0,0 +1,82 @@
+//===-- SymbolizableObjectFile.h -------------------------------- C++ -----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the SymbolizableObjectFile class.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_LIB_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEOBJECTFILE_H
+#define LLVM_LIB_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEOBJECTFILE_H
+
+#include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
+#include <map>
+
+namespace llvm {
+class DataExtractor;
+}
+
+namespace llvm {
+namespace symbolize {
+
+class SymbolizableObjectFile : public SymbolizableModule {
+public:
+ static ErrorOr<std::unique_ptr<SymbolizableObjectFile>>
+ create(object::ObjectFile *Obj, std::unique_ptr<DIContext> DICtx);
+
+ DILineInfo symbolizeCode(uint64_t ModuleOffset, FunctionNameKind FNKind,
+ bool UseSymbolTable) const override;
+ DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset,
+ FunctionNameKind FNKind,
+ bool UseSymbolTable) const override;
+ DIGlobal symbolizeData(uint64_t ModuleOffset) const override;
+
+ // Return true if this is a 32-bit x86 PE COFF module.
+ bool isWin32Module() const override;
+
+ // Returns the preferred base of the module, i.e. where the loader would place
+ // it in memory assuming there were no conflicts.
+ uint64_t getModulePreferredBase() const override;
+
+private:
+ bool shouldOverrideWithSymbolTable(FunctionNameKind FNKind,
+ bool UseSymbolTable) const;
+
+ bool getNameFromSymbolTable(object::SymbolRef::Type Type, uint64_t Address,
+ std::string &Name, uint64_t &Addr,
+ uint64_t &Size) const;
+ // For big-endian PowerPC64 ELF, OpdAddress is the address of the .opd
+ // (function descriptor) section and OpdExtractor refers to its contents.
+ std::error_code addSymbol(const object::SymbolRef &Symbol,
+ uint64_t SymbolSize,
+ DataExtractor *OpdExtractor = nullptr,
+ uint64_t OpdAddress = 0);
+ std::error_code addCoffExportSymbols(const object::COFFObjectFile *CoffObj);
+
+ object::ObjectFile *Module;
+ std::unique_ptr<DIContext> DebugInfoContext;
+
+ struct SymbolDesc {
+ uint64_t Addr;
+ // If size is 0, assume that symbol occupies the whole memory range up to
+ // the following symbol.
+ uint64_t Size;
+ friend bool operator<(const SymbolDesc &s1, const SymbolDesc &s2) {
+ return s1.Addr < s2.Addr;
+ }
+ };
+ std::map<SymbolDesc, StringRef> Functions;
+ std::map<SymbolDesc, StringRef> Objects;
+
+ SymbolizableObjectFile(object::ObjectFile *Obj,
+ std::unique_ptr<DIContext> DICtx);
+};
+
+} // namespace symbolize
+} // namespace llvm
+
+#endif // LLVM_LIB_DEBUGINFO_SYMBOLIZE_SYMBOLIZABLEOBJECTFILE_H
diff --git a/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp b/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
new file mode 100644
index 0000000..3da1963
--- /dev/null
+++ b/contrib/llvm/lib/DebugInfo/Symbolize/Symbolize.cpp
@@ -0,0 +1,456 @@
+//===-- LLVMSymbolize.cpp -------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implementation for LLVM symbolization library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/DebugInfo/Symbolize/Symbolize.h"
+
+#include "SymbolizableObjectFile.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/DebugInfo/DWARF/DWARFContext.h"
+#include "llvm/DebugInfo/PDB/PDB.h"
+#include "llvm/DebugInfo/PDB/PDBContext.h"
+#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Object/MachO.h"
+#include "llvm/Object/MachOUniversal.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Compression.h"
+#include "llvm/Support/DataExtractor.h"
+#include "llvm/Support/Errc.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Path.h"
+#include <stdlib.h>
+
+#if defined(_MSC_VER)
+#include <Windows.h>
+#include <DbgHelp.h>
+#pragma comment(lib, "dbghelp.lib")
+
+// Windows.h conflicts with our COFF header definitions.
+#ifdef IMAGE_FILE_MACHINE_I386
+#undef IMAGE_FILE_MACHINE_I386
+#endif
+#endif
+
+namespace llvm {
+namespace symbolize {
+
+ErrorOr<DILineInfo> LLVMSymbolizer::symbolizeCode(const std::string &ModuleName,
+ uint64_t ModuleOffset) {
+ auto InfoOrErr = getOrCreateModuleInfo(ModuleName);
+ if (auto EC = InfoOrErr.getError())
+ return EC;
+ SymbolizableModule *Info = InfoOrErr.get();
+
+ // If the user is giving us relative addresses, add the preferred base of the
+ // object to the offset before we do the query. It's what DIContext expects.
+ if (Opts.RelativeAddresses)
+ ModuleOffset += Info->getModulePreferredBase();
+
+ DILineInfo LineInfo = Info->symbolizeCode(ModuleOffset, Opts.PrintFunctions,
+ Opts.UseSymbolTable);
+ if (Opts.Demangle)
+ LineInfo.FunctionName = DemangleName(LineInfo.FunctionName, Info);
+ return LineInfo;
+}
+
+ErrorOr<DIInliningInfo>
+LLVMSymbolizer::symbolizeInlinedCode(const std::string &ModuleName,
+ uint64_t ModuleOffset) {
+ auto InfoOrErr = getOrCreateModuleInfo(ModuleName);
+ if (auto EC = InfoOrErr.getError())
+ return EC;
+ SymbolizableModule *Info = InfoOrErr.get();
+
+ // If the user is giving us relative addresses, add the preferred base of the
+ // object to the offset before we do the query. It's what DIContext expects.
+ if (Opts.RelativeAddresses)
+ ModuleOffset += Info->getModulePreferredBase();
+
+ DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(
+ ModuleOffset, Opts.PrintFunctions, Opts.UseSymbolTable);
+ if (Opts.Demangle) {
+ for (int i = 0, n = InlinedContext.getNumberOfFrames(); i < n; i++) {
+ auto *Frame = InlinedContext.getMutableFrame(i);
+ Frame->FunctionName = DemangleName(Frame->FunctionName, Info);
+ }
+ }
+ return InlinedContext;
+}
+
+ErrorOr<DIGlobal> LLVMSymbolizer::symbolizeData(const std::string &ModuleName,
+ uint64_t ModuleOffset) {
+ auto InfoOrErr = getOrCreateModuleInfo(ModuleName);
+ if (auto EC = InfoOrErr.getError())
+ return EC;
+ SymbolizableModule *Info = InfoOrErr.get();
+
+ // If the user is giving us relative addresses, add the preferred base of
+ // the object to the offset before we do the query. It's what DIContext
+ // expects.
+ if (Opts.RelativeAddresses)
+ ModuleOffset += Info->getModulePreferredBase();
+
+ DIGlobal Global = Info->symbolizeData(ModuleOffset);
+ if (Opts.Demangle)
+ Global.Name = DemangleName(Global.Name, Info);
+ return Global;
+}
+
+void LLVMSymbolizer::flush() {
+ ObjectForUBPathAndArch.clear();
+ BinaryForPath.clear();
+ ObjectPairForPathArch.clear();
+ Modules.clear();
+}
+
+// For Path="/path/to/foo" and Basename="foo" assume that debug info is in
+// /path/to/foo.dSYM/Contents/Resources/DWARF/foo.
+// For Path="/path/to/bar.dSYM" and Basename="foo" assume that debug info is in
+// /path/to/bar.dSYM/Contents/Resources/DWARF/foo.
+static
+std::string getDarwinDWARFResourceForPath(
+ const std::string &Path, const std::string &Basename) {
+ SmallString<16> ResourceName = StringRef(Path);
+ if (sys::path::extension(Path) != ".dSYM") {
+ ResourceName += ".dSYM";
+ }
+ sys::path::append(ResourceName, "Contents", "Resources", "DWARF");
+ sys::path::append(ResourceName, Basename);
+ return ResourceName.str();
+}
+
+static bool checkFileCRC(StringRef Path, uint32_t CRCHash) {
+ ErrorOr<std::unique_ptr<MemoryBuffer>> MB =
+ MemoryBuffer::getFileOrSTDIN(Path);
+ if (!MB)
+ return false;
+ return !zlib::isAvailable() || CRCHash == zlib::crc32(MB.get()->getBuffer());
+}
+
+static bool findDebugBinary(const std::string &OrigPath,
+ const std::string &DebuglinkName, uint32_t CRCHash,
+ std::string &Result) {
+ std::string OrigRealPath = OrigPath;
+#if defined(HAVE_REALPATH)
+ if (char *RP = realpath(OrigPath.c_str(), nullptr)) {
+ OrigRealPath = RP;
+ free(RP);
+ }
+#endif
+ SmallString<16> OrigDir(OrigRealPath);
+ llvm::sys::path::remove_filename(OrigDir);
+ SmallString<16> DebugPath = OrigDir;
+ // Try /path/to/original_binary/debuglink_name
+ llvm::sys::path::append(DebugPath, DebuglinkName);
+ if (checkFileCRC(DebugPath, CRCHash)) {
+ Result = DebugPath.str();
+ return true;
+ }
+ // Try /path/to/original_binary/.debug/debuglink_name
+ DebugPath = OrigRealPath;
+ llvm::sys::path::append(DebugPath, ".debug", DebuglinkName);
+ if (checkFileCRC(DebugPath, CRCHash)) {
+ Result = DebugPath.str();
+ return true;
+ }
+ // Try /usr/lib/debug/path/to/original_binary/debuglink_name
+ DebugPath = "/usr/lib/debug";
+ llvm::sys::path::append(DebugPath, llvm::sys::path::relative_path(OrigDir),
+ DebuglinkName);
+ if (checkFileCRC(DebugPath, CRCHash)) {
+ Result = DebugPath.str();
+ return true;
+ }
+ return false;
+}
+
+static bool getGNUDebuglinkContents(const ObjectFile *Obj, std::string &DebugName,
+ uint32_t &CRCHash) {
+ if (!Obj)
+ return false;
+ for (const SectionRef &Section : Obj->sections()) {
+ StringRef Name;
+ Section.getName(Name);
+ Name = Name.substr(Name.find_first_not_of("._"));
+ if (Name == "gnu_debuglink") {
+ StringRef Data;
+ Section.getContents(Data);
+ DataExtractor DE(Data, Obj->isLittleEndian(), 0);
+ uint32_t Offset = 0;
+ if (const char *DebugNameStr = DE.getCStr(&Offset)) {
+ // 4-byte align the offset.
+ Offset = (Offset + 3) & ~0x3;
+ if (DE.isValidOffsetForDataOfSize(Offset, 4)) {
+ DebugName = DebugNameStr;
+ CRCHash = DE.getU32(&Offset);
+ return true;
+ }
+ }
+ break;
+ }
+ }
+ return false;
+}
+
+static
+bool darwinDsymMatchesBinary(const MachOObjectFile *DbgObj,
+ const MachOObjectFile *Obj) {
+ ArrayRef<uint8_t> dbg_uuid = DbgObj->getUuid();
+ ArrayRef<uint8_t> bin_uuid = Obj->getUuid();
+ if (dbg_uuid.empty() || bin_uuid.empty())
+ return false;
+ return !memcmp(dbg_uuid.data(), bin_uuid.data(), dbg_uuid.size());
+}
+
+ObjectFile *LLVMSymbolizer::lookUpDsymFile(const std::string &ExePath,
+ const MachOObjectFile *MachExeObj, const std::string &ArchName) {
+ // On Darwin we may find DWARF in separate object file in
+ // resource directory.
+ std::vector<std::string> DsymPaths;
+ StringRef Filename = sys::path::filename(ExePath);
+ DsymPaths.push_back(getDarwinDWARFResourceForPath(ExePath, Filename));
+ for (const auto &Path : Opts.DsymHints) {
+ DsymPaths.push_back(getDarwinDWARFResourceForPath(Path, Filename));
+ }
+ for (const auto &Path : DsymPaths) {
+ auto DbgObjOrErr = getOrCreateObject(Path, ArchName);
+ if (!DbgObjOrErr)
+ continue;
+ ObjectFile *DbgObj = DbgObjOrErr.get();
+ const MachOObjectFile *MachDbgObj = dyn_cast<const MachOObjectFile>(DbgObj);
+ if (!MachDbgObj)
+ continue;
+ if (darwinDsymMatchesBinary(MachDbgObj, MachExeObj))
+ return DbgObj;
+ }
+ return nullptr;
+}
+
+ObjectFile *LLVMSymbolizer::lookUpDebuglinkObject(const std::string &Path,
+ const ObjectFile *Obj,
+ const std::string &ArchName) {
+ std::string DebuglinkName;
+ uint32_t CRCHash;
+ std::string DebugBinaryPath;
+ if (!getGNUDebuglinkContents(Obj, DebuglinkName, CRCHash))
+ return nullptr;
+ if (!findDebugBinary(Path, DebuglinkName, CRCHash, DebugBinaryPath))
+ return nullptr;
+ auto DbgObjOrErr = getOrCreateObject(DebugBinaryPath, ArchName);
+ if (!DbgObjOrErr)
+ return nullptr;
+ return DbgObjOrErr.get();
+}
+
+ErrorOr<LLVMSymbolizer::ObjectPair>
+LLVMSymbolizer::getOrCreateObjectPair(const std::string &Path,
+ const std::string &ArchName) {
+ const auto &I = ObjectPairForPathArch.find(std::make_pair(Path, ArchName));
+ if (I != ObjectPairForPathArch.end())
+ return I->second;
+
+ auto ObjOrErr = getOrCreateObject(Path, ArchName);
+ if (auto EC = ObjOrErr.getError()) {
+ ObjectPairForPathArch.insert(
+ std::make_pair(std::make_pair(Path, ArchName), EC));
+ return EC;
+ }
+
+ ObjectFile *Obj = ObjOrErr.get();
+ assert(Obj != nullptr);
+ ObjectFile *DbgObj = nullptr;
+
+ if (auto MachObj = dyn_cast<const MachOObjectFile>(Obj))
+ DbgObj = lookUpDsymFile(Path, MachObj, ArchName);
+ if (!DbgObj)
+ DbgObj = lookUpDebuglinkObject(Path, Obj, ArchName);
+ if (!DbgObj)
+ DbgObj = Obj;
+ ObjectPair Res = std::make_pair(Obj, DbgObj);
+ ObjectPairForPathArch.insert(
+ std::make_pair(std::make_pair(Path, ArchName), Res));
+ return Res;
+}
+
+ErrorOr<ObjectFile *>
+LLVMSymbolizer::getOrCreateObject(const std::string &Path,
+ const std::string &ArchName) {
+ const auto &I = BinaryForPath.find(Path);
+ Binary *Bin = nullptr;
+ if (I == BinaryForPath.end()) {
+ ErrorOr<OwningBinary<Binary>> BinOrErr = createBinary(Path);
+ if (auto EC = BinOrErr.getError()) {
+ BinaryForPath.insert(std::make_pair(Path, EC));
+ return EC;
+ }
+ Bin = BinOrErr->getBinary();
+ BinaryForPath.insert(std::make_pair(Path, std::move(BinOrErr.get())));
+ } else if (auto EC = I->second.getError()) {
+ return EC;
+ } else {
+ Bin = I->second->getBinary();
+ }
+
+ assert(Bin != nullptr);
+
+ if (MachOUniversalBinary *UB = dyn_cast<MachOUniversalBinary>(Bin)) {
+ const auto &I = ObjectForUBPathAndArch.find(std::make_pair(Path, ArchName));
+ if (I != ObjectForUBPathAndArch.end()) {
+ if (auto EC = I->second.getError())
+ return EC;
+ return I->second->get();
+ }
+ ErrorOr<std::unique_ptr<ObjectFile>> ObjOrErr =
+ UB->getObjectForArch(ArchName);
+ if (auto EC = ObjOrErr.getError()) {
+ ObjectForUBPathAndArch.insert(
+ std::make_pair(std::make_pair(Path, ArchName), EC));
+ return EC;
+ }
+ ObjectFile *Res = ObjOrErr->get();
+ ObjectForUBPathAndArch.insert(std::make_pair(std::make_pair(Path, ArchName),
+ std::move(ObjOrErr.get())));
+ return Res;
+ }
+ if (Bin->isObject()) {
+ return cast<ObjectFile>(Bin);
+ }
+ return object_error::arch_not_found;
+}
+
+ErrorOr<SymbolizableModule *>
+LLVMSymbolizer::getOrCreateModuleInfo(const std::string &ModuleName) {
+ const auto &I = Modules.find(ModuleName);
+ if (I != Modules.end()) {
+ auto &InfoOrErr = I->second;
+ if (auto EC = InfoOrErr.getError())
+ return EC;
+ return InfoOrErr->get();
+ }
+ std::string BinaryName = ModuleName;
+ std::string ArchName = Opts.DefaultArch;
+ size_t ColonPos = ModuleName.find_last_of(':');
+ // Verify that substring after colon form a valid arch name.
+ if (ColonPos != std::string::npos) {
+ std::string ArchStr = ModuleName.substr(ColonPos + 1);
+ if (Triple(ArchStr).getArch() != Triple::UnknownArch) {
+ BinaryName = ModuleName.substr(0, ColonPos);
+ ArchName = ArchStr;
+ }
+ }
+ auto ObjectsOrErr = getOrCreateObjectPair(BinaryName, ArchName);
+ if (auto EC = ObjectsOrErr.getError()) {
+ // Failed to find valid object file.
+ Modules.insert(std::make_pair(ModuleName, EC));
+ return EC;
+ }
+ ObjectPair Objects = ObjectsOrErr.get();
+
+ std::unique_ptr<DIContext> Context;
+ if (auto CoffObject = dyn_cast<COFFObjectFile>(Objects.first)) {
+ // If this is a COFF object, assume it contains PDB debug information. If
+ // we don't find any we will fall back to the DWARF case.
+ std::unique_ptr<IPDBSession> Session;
+ PDB_ErrorCode Error = loadDataForEXE(PDB_ReaderType::DIA,
+ Objects.first->getFileName(), Session);
+ if (Error == PDB_ErrorCode::Success) {
+ Context.reset(new PDBContext(*CoffObject, std::move(Session)));
+ }
+ }
+ if (!Context)
+ Context.reset(new DWARFContextInMemory(*Objects.second));
+ assert(Context);
+ auto InfoOrErr =
+ SymbolizableObjectFile::create(Objects.first, std::move(Context));
+ auto InsertResult =
+ Modules.insert(std::make_pair(ModuleName, std::move(InfoOrErr)));
+ assert(InsertResult.second);
+ if (auto EC = InsertResult.first->second.getError())
+ return EC;
+ return InsertResult.first->second->get();
+}
+
+// Undo these various manglings for Win32 extern "C" functions:
+// cdecl - _foo
+// stdcall - _foo@12
+// fastcall - @foo@12
+// vectorcall - foo@@12
+// These are all different linkage names for 'foo'.
+static StringRef demanglePE32ExternCFunc(StringRef SymbolName) {
+ // Remove any '_' or '@' prefix.
+ char Front = SymbolName.empty() ? '\0' : SymbolName[0];
+ if (Front == '_' || Front == '@')
+ SymbolName = SymbolName.drop_front();
+
+ // Remove any '@[0-9]+' suffix.
+ if (Front != '?') {
+ size_t AtPos = SymbolName.rfind('@');
+ if (AtPos != StringRef::npos &&
+ std::all_of(SymbolName.begin() + AtPos + 1, SymbolName.end(),
+ [](char C) { return C >= '0' && C <= '9'; })) {
+ SymbolName = SymbolName.substr(0, AtPos);
+ }
+ }
+
+ // Remove any ending '@' for vectorcall.
+ if (SymbolName.endswith("@"))
+ SymbolName = SymbolName.drop_back();
+
+ return SymbolName;
+}
+
+#if !defined(_MSC_VER)
+// Assume that __cxa_demangle is provided by libcxxabi (except for Windows).
+extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer,
+ size_t *length, int *status);
+#endif
+
+std::string LLVMSymbolizer::DemangleName(const std::string &Name,
+ const SymbolizableModule *ModInfo) {
+#if !defined(_MSC_VER)
+ // We can spoil names of symbols with C linkage, so use an heuristic
+ // approach to check if the name should be demangled.
+ if (Name.substr(0, 2) == "_Z") {
+ int status = 0;
+ char *DemangledName = __cxa_demangle(Name.c_str(), nullptr, nullptr, &status);
+ if (status != 0)
+ return Name;
+ std::string Result = DemangledName;
+ free(DemangledName);
+ return Result;
+ }
+#else
+ if (!Name.empty() && Name.front() == '?') {
+ // Only do MSVC C++ demangling on symbols starting with '?'.
+ char DemangledName[1024] = {0};
+ DWORD result = ::UnDecorateSymbolName(
+ Name.c_str(), DemangledName, 1023,
+ UNDNAME_NO_ACCESS_SPECIFIERS | // Strip public, private, protected
+ UNDNAME_NO_ALLOCATION_LANGUAGE | // Strip __thiscall, __stdcall, etc
+ UNDNAME_NO_THROW_SIGNATURES | // Strip throw() specifications
+ UNDNAME_NO_MEMBER_TYPE | // Strip virtual, static, etc specifiers
+ UNDNAME_NO_MS_KEYWORDS | // Strip all MS extension keywords
+ UNDNAME_NO_FUNCTION_RETURNS); // Strip function return types
+ return (result == 0) ? Name : std::string(DemangledName);
+ }
+#endif
+ if (ModInfo && ModInfo->isWin32Module())
+ return std::string(demanglePE32ExternCFunc(Name));
+ return Name;
+}
+
+} // namespace symbolize
+} // namespace llvm
OpenPOWER on IntegriCloud