From ebe69fe11e48d322045d5949c83283927a0d790b Mon Sep 17 00:00:00 2001 From: Stephen Hines Date: Mon, 23 Mar 2015 12:10:34 -0700 Subject: Update aosp/master LLVM for rebase to r230699. Change-Id: I2b5be30509658cb8266be782de0ab24f9099f9b9 --- lib/DebugInfo/Android.mk | 53 - lib/DebugInfo/CMakeLists.txt | 22 +- lib/DebugInfo/DIContext.cpp | 18 - lib/DebugInfo/DWARF/Android.mk | 54 + lib/DebugInfo/DWARF/CMakeLists.txt | 22 + lib/DebugInfo/DWARF/DIContext.cpp | 18 + .../DWARF/DWARFAbbreviationDeclaration.cpp | 97 ++ lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp | 132 +++ lib/DebugInfo/DWARF/DWARFCompileUnit.cpp | 32 + lib/DebugInfo/DWARF/DWARFContext.cpp | 696 +++++++++++++ lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp | 115 ++ lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp | 104 ++ lib/DebugInfo/DWARF/DWARFDebugAranges.cpp | 129 +++ lib/DebugInfo/DWARF/DWARFDebugFrame.cpp | 511 +++++++++ lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp | 459 ++++++++ lib/DebugInfo/DWARF/DWARFDebugLine.cpp | 698 +++++++++++++ lib/DebugInfo/DWARF/DWARFDebugLoc.cpp | 128 +++ lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp | 69 ++ lib/DebugInfo/DWARF/DWARFFormValue.cpp | 565 ++++++++++ lib/DebugInfo/DWARF/DWARFTypeUnit.cpp | 39 + lib/DebugInfo/DWARF/DWARFUnit.cpp | 377 +++++++ lib/DebugInfo/DWARF/LLVMBuild.txt | 22 + lib/DebugInfo/DWARF/Makefile | 14 + lib/DebugInfo/DWARF/SyntaxHighlighting.cpp | 37 + lib/DebugInfo/DWARF/SyntaxHighlighting.h | 39 + lib/DebugInfo/DWARF/module.modulemap | 1 + lib/DebugInfo/DWARFAbbreviationDeclaration.cpp | 97 -- lib/DebugInfo/DWARFAbbreviationDeclaration.h | 60 -- lib/DebugInfo/DWARFAcceleratorTable.cpp | 133 --- lib/DebugInfo/DWARFAcceleratorTable.h | 51 - lib/DebugInfo/DWARFCompileUnit.cpp | 32 - lib/DebugInfo/DWARFCompileUnit.h | 31 - lib/DebugInfo/DWARFContext.cpp | 697 ------------- lib/DebugInfo/DWARFContext.h | 292 ------ lib/DebugInfo/DWARFDebugAbbrev.cpp | 115 -- lib/DebugInfo/DWARFDebugAbbrev.h | 63 -- lib/DebugInfo/DWARFDebugArangeSet.cpp | 104 -- lib/DebugInfo/DWARFDebugArangeSet.h | 70 -- lib/DebugInfo/DWARFDebugAranges.cpp | 129 --- lib/DebugInfo/DWARFDebugAranges.h | 87 -- lib/DebugInfo/DWARFDebugFrame.cpp | 374 ------- lib/DebugInfo/DWARFDebugFrame.h | 43 - lib/DebugInfo/DWARFDebugInfoEntry.cpp | 451 -------- lib/DebugInfo/DWARFDebugInfoEntry.h | 160 --- lib/DebugInfo/DWARFDebugLine.cpp | 698 ------------- lib/DebugInfo/DWARFDebugLine.h | 238 ----- lib/DebugInfo/DWARFDebugLoc.cpp | 128 --- lib/DebugInfo/DWARFDebugLoc.h | 81 -- lib/DebugInfo/DWARFDebugRangeList.cpp | 69 -- lib/DebugInfo/DWARFDebugRangeList.h | 77 -- lib/DebugInfo/DWARFFormValue.cpp | 557 ---------- lib/DebugInfo/DWARFRelocMap.h | 22 - lib/DebugInfo/DWARFSection.h | 24 - lib/DebugInfo/DWARFTypeUnit.cpp | 39 - lib/DebugInfo/DWARFTypeUnit.h | 38 - lib/DebugInfo/DWARFUnit.cpp | 377 ------- lib/DebugInfo/DWARFUnit.h | 245 ----- lib/DebugInfo/LLVMBuild.txt | 8 +- lib/DebugInfo/Makefile | 9 +- lib/DebugInfo/PDB/Android.mk | 75 ++ lib/DebugInfo/PDB/CMakeLists.txt | 76 ++ lib/DebugInfo/PDB/DIA/DIADataStream.cpp | 73 ++ lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp | 53 + lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp | 50 + lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp | 50 + lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp | 54 + lib/DebugInfo/PDB/DIA/DIALineNumber.cpp | 75 ++ lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp | 1095 ++++++++++++++++++++ lib/DebugInfo/PDB/DIA/DIASession.cpp | 117 +++ lib/DebugInfo/PDB/DIA/DIASourceFile.cpp | 67 ++ lib/DebugInfo/PDB/IPDBSourceFile.cpp | 32 + lib/DebugInfo/PDB/LLVMBuild.txt | 23 + lib/DebugInfo/PDB/Makefile | 14 + lib/DebugInfo/PDB/PDB.cpp | 30 + lib/DebugInfo/PDB/PDBExtras.cpp | 346 +++++++ lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp | 28 + lib/DebugInfo/PDB/PDBSymDumper.cpp | 177 ++++ lib/DebugInfo/PDB/PDBSymbol.cpp | 151 +++ lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolBlock.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolCompiland.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp | 32 + lib/DebugInfo/PDB/PDBSymbolCustom.cpp | 31 + lib/DebugInfo/PDB/PDBSymbolData.cpp | 30 + lib/DebugInfo/PDB/PDBSymbolExe.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolFunc.cpp | 104 ++ lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolLabel.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolThunk.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp | 30 + lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp | 27 + lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp | 89 ++ lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp | 30 + lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp | 25 + lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolUnknown.cpp | 26 + lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp | 26 + lib/DebugInfo/module.modulemap | 1 - 110 files changed, 7918 insertions(+), 5679 deletions(-) delete mode 100644 lib/DebugInfo/Android.mk delete mode 100644 lib/DebugInfo/DIContext.cpp create mode 100644 lib/DebugInfo/DWARF/Android.mk create mode 100644 lib/DebugInfo/DWARF/CMakeLists.txt create mode 100644 lib/DebugInfo/DWARF/DIContext.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFCompileUnit.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFContext.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugAranges.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugFrame.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugLine.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugLoc.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFFormValue.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFTypeUnit.cpp create mode 100644 lib/DebugInfo/DWARF/DWARFUnit.cpp create mode 100644 lib/DebugInfo/DWARF/LLVMBuild.txt create mode 100644 lib/DebugInfo/DWARF/Makefile create mode 100644 lib/DebugInfo/DWARF/SyntaxHighlighting.cpp create mode 100644 lib/DebugInfo/DWARF/SyntaxHighlighting.h create mode 100644 lib/DebugInfo/DWARF/module.modulemap delete mode 100644 lib/DebugInfo/DWARFAbbreviationDeclaration.cpp delete mode 100644 lib/DebugInfo/DWARFAbbreviationDeclaration.h delete mode 100644 lib/DebugInfo/DWARFAcceleratorTable.cpp delete mode 100644 lib/DebugInfo/DWARFAcceleratorTable.h delete mode 100644 lib/DebugInfo/DWARFCompileUnit.cpp delete mode 100644 lib/DebugInfo/DWARFCompileUnit.h delete mode 100644 lib/DebugInfo/DWARFContext.cpp delete mode 100644 lib/DebugInfo/DWARFContext.h delete mode 100644 lib/DebugInfo/DWARFDebugAbbrev.cpp delete mode 100644 lib/DebugInfo/DWARFDebugAbbrev.h delete mode 100644 lib/DebugInfo/DWARFDebugArangeSet.cpp delete mode 100644 lib/DebugInfo/DWARFDebugArangeSet.h delete mode 100644 lib/DebugInfo/DWARFDebugAranges.cpp delete mode 100644 lib/DebugInfo/DWARFDebugAranges.h delete mode 100644 lib/DebugInfo/DWARFDebugFrame.cpp delete mode 100644 lib/DebugInfo/DWARFDebugFrame.h delete mode 100644 lib/DebugInfo/DWARFDebugInfoEntry.cpp delete mode 100644 lib/DebugInfo/DWARFDebugInfoEntry.h delete mode 100644 lib/DebugInfo/DWARFDebugLine.cpp delete mode 100644 lib/DebugInfo/DWARFDebugLine.h delete mode 100644 lib/DebugInfo/DWARFDebugLoc.cpp delete mode 100644 lib/DebugInfo/DWARFDebugLoc.h delete mode 100644 lib/DebugInfo/DWARFDebugRangeList.cpp delete mode 100644 lib/DebugInfo/DWARFDebugRangeList.h delete mode 100644 lib/DebugInfo/DWARFFormValue.cpp delete mode 100644 lib/DebugInfo/DWARFRelocMap.h delete mode 100644 lib/DebugInfo/DWARFSection.h delete mode 100644 lib/DebugInfo/DWARFTypeUnit.cpp delete mode 100644 lib/DebugInfo/DWARFTypeUnit.h delete mode 100644 lib/DebugInfo/DWARFUnit.cpp delete mode 100644 lib/DebugInfo/DWARFUnit.h create mode 100644 lib/DebugInfo/PDB/Android.mk create mode 100644 lib/DebugInfo/PDB/CMakeLists.txt create mode 100644 lib/DebugInfo/PDB/DIA/DIADataStream.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIALineNumber.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIASession.cpp create mode 100644 lib/DebugInfo/PDB/DIA/DIASourceFile.cpp create mode 100644 lib/DebugInfo/PDB/IPDBSourceFile.cpp create mode 100644 lib/DebugInfo/PDB/LLVMBuild.txt create mode 100644 lib/DebugInfo/PDB/Makefile create mode 100644 lib/DebugInfo/PDB/PDB.cpp create mode 100644 lib/DebugInfo/PDB/PDBExtras.cpp create mode 100644 lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymDumper.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbol.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolBlock.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolCompiland.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolCustom.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolData.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolExe.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolFunc.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolLabel.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolThunk.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolUnknown.cpp create mode 100644 lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp delete mode 100644 lib/DebugInfo/module.modulemap (limited to 'lib/DebugInfo') diff --git a/lib/DebugInfo/Android.mk b/lib/DebugInfo/Android.mk deleted file mode 100644 index e777e9c..0000000 --- a/lib/DebugInfo/Android.mk +++ /dev/null @@ -1,53 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -debuginfo_SRC_FILES := \ - DIContext.cpp \ - DWARFAbbreviationDeclaration.cpp \ - DWARFAcceleratorTable.cpp \ - DWARFCompileUnit.cpp \ - DWARFContext.cpp \ - DWARFDebugAbbrev.cpp \ - DWARFDebugArangeSet.cpp \ - DWARFDebugAranges.cpp \ - DWARFDebugFrame.cpp \ - DWARFDebugInfoEntry.cpp \ - DWARFDebugLine.cpp \ - DWARFDebugLoc.cpp \ - DWARFDebugRangeList.cpp \ - DWARFFormValue.cpp \ - DWARFTypeUnit.cpp \ - DWARFUnit.cpp \ - -# For the host -# ===================================================== -include $(CLEAR_VARS) - -REQUIRES_RTTI := 1 - -LOCAL_SRC_FILES := $(debuginfo_SRC_FILES) - -LOCAL_MODULE:= libLLVMDebugInfo - -LOCAL_MODULE_TAGS := optional - -include $(LLVM_HOST_BUILD_MK) -include $(LLVM_GEN_INTRINSICS_MK) -include $(BUILD_HOST_STATIC_LIBRARY) - -# For the device -# ===================================================== -ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS)) -include $(CLEAR_VARS) - -REQUIRES_RTTI := 1 - -LOCAL_SRC_FILES := $(debuginfo_SRC_FILES) - -LOCAL_MODULE:= libLLVMDebugInfo - -LOCAL_MODULE_TAGS := optional - -include $(LLVM_DEVICE_BUILD_MK) -include $(LLVM_GEN_INTRINSICS_MK) -include $(BUILD_STATIC_LIBRARY) -endif diff --git a/lib/DebugInfo/CMakeLists.txt b/lib/DebugInfo/CMakeLists.txt index 81fc84d..645d92f 100644 --- a/lib/DebugInfo/CMakeLists.txt +++ b/lib/DebugInfo/CMakeLists.txt @@ -1,18 +1,4 @@ -add_llvm_library(LLVMDebugInfo - DIContext.cpp - DWARFAbbreviationDeclaration.cpp - DWARFAcceleratorTable.cpp - DWARFCompileUnit.cpp - DWARFContext.cpp - DWARFDebugAbbrev.cpp - DWARFDebugArangeSet.cpp - DWARFDebugAranges.cpp - DWARFDebugFrame.cpp - DWARFDebugInfoEntry.cpp - DWARFDebugLine.cpp - DWARFDebugLoc.cpp - DWARFDebugRangeList.cpp - DWARFFormValue.cpp - DWARFTypeUnit.cpp - DWARFUnit.cpp - ) + +add_subdirectory(DWARF) +add_subdirectory(PDB) + diff --git a/lib/DebugInfo/DIContext.cpp b/lib/DebugInfo/DIContext.cpp deleted file mode 100644 index 01aecf8..0000000 --- a/lib/DebugInfo/DIContext.cpp +++ /dev/null @@ -1,18 +0,0 @@ -//===-- DIContext.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/DIContext.h" -#include "DWARFContext.h" -using namespace llvm; - -DIContext::~DIContext() {} - -DIContext *DIContext::getDWARFContext(const object::ObjectFile &Obj) { - return new DWARFContextInMemory(Obj); -} diff --git a/lib/DebugInfo/DWARF/Android.mk b/lib/DebugInfo/DWARF/Android.mk new file mode 100644 index 0000000..3c8222f --- /dev/null +++ b/lib/DebugInfo/DWARF/Android.mk @@ -0,0 +1,54 @@ +LOCAL_PATH:= $(call my-dir) + +debuginfo_dwarf_SRC_FILES := \ + DIContext.cpp \ + DWARFAbbreviationDeclaration.cpp \ + DWARFAcceleratorTable.cpp \ + DWARFCompileUnit.cpp \ + DWARFContext.cpp \ + DWARFDebugAbbrev.cpp \ + DWARFDebugArangeSet.cpp \ + DWARFDebugAranges.cpp \ + DWARFDebugFrame.cpp \ + DWARFDebugInfoEntry.cpp \ + DWARFDebugLine.cpp \ + DWARFDebugLoc.cpp \ + DWARFDebugRangeList.cpp \ + DWARFFormValue.cpp \ + DWARFTypeUnit.cpp \ + DWARFUnit.cpp \ + SyntaxHighlighting.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +REQUIRES_RTTI := 1 + +LOCAL_SRC_FILES := $(debuginfo_dwarf_SRC_FILES) + +LOCAL_MODULE:= libLLVMDebugInfoDWARF + +LOCAL_MODULE_TAGS := optional + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS)) +include $(CLEAR_VARS) + +REQUIRES_RTTI := 1 + +LOCAL_SRC_FILES := $(debuginfo_dwarf_SRC_FILES) + +LOCAL_MODULE:= libLLVMDebugInfoDWARF + +LOCAL_MODULE_TAGS := optional + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/DebugInfo/DWARF/CMakeLists.txt b/lib/DebugInfo/DWARF/CMakeLists.txt new file mode 100644 index 0000000..8c6d495 --- /dev/null +++ b/lib/DebugInfo/DWARF/CMakeLists.txt @@ -0,0 +1,22 @@ +add_llvm_library(LLVMDebugInfoDWARF + DIContext.cpp + DWARFAbbreviationDeclaration.cpp + DWARFAcceleratorTable.cpp + DWARFCompileUnit.cpp + DWARFContext.cpp + DWARFDebugAbbrev.cpp + DWARFDebugArangeSet.cpp + DWARFDebugAranges.cpp + DWARFDebugFrame.cpp + DWARFDebugInfoEntry.cpp + DWARFDebugLine.cpp + DWARFDebugLoc.cpp + DWARFDebugRangeList.cpp + DWARFFormValue.cpp + DWARFTypeUnit.cpp + DWARFUnit.cpp + SyntaxHighlighting.cpp + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/DWARF + ) diff --git a/lib/DebugInfo/DWARF/DIContext.cpp b/lib/DebugInfo/DWARF/DIContext.cpp new file mode 100644 index 0000000..a1c6ca4 --- /dev/null +++ b/lib/DebugInfo/DWARF/DIContext.cpp @@ -0,0 +1,18 @@ +//===-- DIContext.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/DIContext.h" +#include "llvm/DebugInfo/DWARF/DWARFContext.h" +using namespace llvm; + +DIContext::~DIContext() {} + +DIContext *DIContext::getDWARFContext(const object::ObjectFile &Obj) { + return new DWARFContextInMemory(Obj); +} diff --git a/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp b/lib/DebugInfo/DWARF/DWARFAbbreviationDeclaration.cpp new file mode 100644 index 0000000..9314c9e --- /dev/null +++ b/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/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp b/lib/DebugInfo/DWARF/DWARFAcceleratorTable.cpp new file mode 100644 index 0000000..8ae0543 --- /dev/null +++ b/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 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/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp new file mode 100644 index 0000000..01e7247 --- /dev/null +++ b/lib/DebugInfo/DWARF/DWARFCompileUnit.cpp @@ -0,0 +1,32 @@ +//===-- 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"; + + const DWARFDebugInfoEntryMinimal *CU = getCompileUnitDIE(false); + assert(CU && "Null Compile Unit?"); + CU->dump(OS, this, -1U); +} + +// VTable anchor. +DWARFCompileUnit::~DWARFCompileUnit() { +} diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp new file mode 100644 index 0000000..3b42700 --- /dev/null +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -0,0 +1,696 @@ +//===-- 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/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 +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); + } + + 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(); + unsigned stmtOffset = + CU->getCompileUnitDIE()->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_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 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 DWARFLineTable * +DWARFContext::getLineTableForUnit(DWARFUnit *cu) { + if (!Line) + Line.reset(new DWARFDebugLine(&getLineSection().Relocs)); + + unsigned stmtOffset = + cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset( + cu, DW_AT_stmt_list, -1U); + if (stmtOffset == -1U) + return nullptr; // No line table for this compile unit. + + // See if the line table is cached. + if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset)) + return lt; + + // We have to parse it first. + DataExtractor lineData(getLineSection().Data, isLittleEndian(), + cu->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.push_back(DWARFUnitSection()); + 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.push_back(DWARFUnitSection()); + 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 = ""; + 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 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) + : 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.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(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_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) + // 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; + } + + section_iterator RelocatedSection = Section.getRelocatedSection(); + if (RelocatedSection == Obj.section_end()) + continue; + + StringRef RelSecName; + RelocatedSection->getName(RelSecName); + 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(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(Address); + uint64_t Type; + Reloc.getType(Type); + uint64_t SymAddr = 0; + object::symbol_iterator Sym = Reloc.getSymbol(); + if (Sym != Obj.symbol_end()) + Sym->getAddress(SymAddr); + + object::RelocVisitor V(Obj); + object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); + if (V.error()) { + SmallString<32> Name; + std::error_code ec(Reloc.getTypeName(Name)); + if (ec) { + errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; + } + 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/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp b/lib/DebugInfo/DWARF/DWARFDebugAbbrev.cpp new file mode 100644 index 0000000..e63e289 --- /dev/null +++ b/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/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp b/lib/DebugInfo/DWARF/DWARFDebugArangeSet.cpp new file mode 100644 index 0000000..67589cd --- /dev/null +++ b/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 +#include +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/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARF/DWARFDebugAranges.cpp new file mode 100644 index 0000000..27a02c4 --- /dev/null +++ b/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 +#include +#include +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 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 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/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp new file mode 100644 index 0000000..7d77290 --- /dev/null +++ b/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -0,0 +1,511 @@ +//===-- 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/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 +#include + +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 Operands; + struct Instruction { + Instruction(uint8_t Opcode) + : Opcode(Opcode) + {} + + uint8_t Opcode; + Operands Ops; + }; + + std::vector 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, uint64_t CodeAlignmentFactor, + int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister) + : FrameEntry(FK_CIE, Offset, Length), Version(Version), + Augmentation(std::move(Augmentation)), + CodeAlignmentFactor(CodeAlignmentFactor), + DataAlignmentFactor(DataAlignmentFactor), + ReturnAddressRegister(ReturnAddressRegister) {} + + ~CIE() { + } + + 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"; + 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 v3 + uint8_t Version; + SmallString<8> Augmentation; + 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() { + } + + 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 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(&OpTypes[0], DW_CFA_restore+1); +} + +static ArrayRef 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(this); + + if (!Cie) + Cie = cast(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 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(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) { + // Note: this is specifically DWARFv3 CIE header structure. It was + // changed in DWARFv4. We currently don't support reading DWARFv4 + // here because LLVM itself does not emit it (and LLDB doesn't + // support it either). + uint8_t Version = Data.getU8(&Offset); + const char *Augmentation = Data.getCStr(&Offset); + uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); + int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); + uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); + + auto Cie = make_unique(StartOffset, Length, Version, + StringRef(Augmentation), 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/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp new file mode 100644 index 0000000..e963b7c --- /dev/null +++ b/lib/DebugInfo/DWARF/DWARFDebugInfoEntry.cpp @@ -0,0 +1,459 @@ +//===-- 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 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) && + // The signature references aren't handled. + formValue.getForm() != DW_FORM_ref_sig8) { + uint32_t Ref = formValue.getAsReference(u).getValue(); + DWARFDebugInfoEntryMinimal DIE; + if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &Ref)) + if (const char *Ref = DIE.getName(RefU, DINameKind::LinkageName)) + OS << " \"" << Ref << '\"'; + } else if (attr == DW_AT_APPLE_property_attribute) { + if (Optional 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 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 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 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 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 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 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/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp new file mode 100644 index 0000000..b63af6a --- /dev/null +++ b/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -0,0 +1,698 @@ +//===-- 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 +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; + StandardOpcodeLengths.clear(); + IncludeDirectories.clear(); + FileNames.clear(); +} + +void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { + OS << "Line table prologue:\n" + << format(" total_length: 0x%8.8x\n", TotalLength) + << format(" version: %u\n", Version) + << format(" prologue_length: 0x%8.8x\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 uint32_t prologue_offset = *offset_ptr; + + clear(); + TotalLength = debug_line_data.getU32(offset_ptr); + Version = debug_line_data.getU16(offset_ptr); + if (Version < 2) + return false; + + PrologueLength = debug_line_data.getU32(offset_ptr); + const uint32_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.8x should" + " have ended at 0x%8.8x but it ended at 0x%8.8x\n", + prologue_offset, end_prologue_offset, *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 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 + + sizeof(Prologue.TotalLength); + + 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 &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::lookupAddress(uint64_t address) const { + uint32_t unknown_index = UINT32_MAX; + if (Sequences.empty()) + return unknown_index; + // 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 unknown_index; + found_seq = *(seq_pos - 1); + } + if (!found_seq.containsPC(address)) + return unknown_index; + // 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() + found_seq.FirstRowIndex; + RowIter last_row = Rows.begin() + found_seq.LastRowIndex; + RowIter row_pos = std::lower_bound(first_row, last_row, row, + DWARFDebugLine::Row::orderByAddress); + if (row_pos == last_row) { + return found_seq.LastRowIndex - 1; + } + uint32_t index = found_seq.FirstRowIndex + (row_pos - first_row); + if (row_pos->Address > address) { + if (row_pos == first_row) + return unknown_index; + else + index--; + } + return index; +} + +bool DWARFDebugLine::LineTable::lookupAddressRange( + uint64_t address, uint64_t size, std::vector &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) { + DWARFDebugLine::Sequence cur_seq = *seq_pos; + uint32_t first_row_index; + uint32_t last_row_index; + if (seq_pos == start_pos) { + // For the first sequence, we need to find which row in the sequence is the + // first in our range. 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() + cur_seq.FirstRowIndex; + RowIter last_row = Rows.begin() + cur_seq.LastRowIndex; + RowIter row_pos = std::upper_bound(first_row, last_row, row, + DWARFDebugLine::Row::orderByAddress); + // The 'row_pos' iterator references the first row that is greater than + // our start address. Unless that's the first row, we want to start at + // the row before that. + first_row_index = cur_seq.FirstRowIndex + (row_pos - first_row); + if (row_pos != first_row) + --first_row_index; + } else + first_row_index = cur_seq.FirstRowIndex; + + // For the last sequence in our range, we need to figure out the last row in + // range. For all other sequences we can go to the end of the sequence. + if (cur_seq.HighPC > end_addr) { + DWARFDebugLine::Row row; + row.Address = end_addr; + RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex; + RowIter last_row = Rows.begin() + cur_seq.LastRowIndex; + RowIter row_pos = std::upper_bound(first_row, last_row, row, + DWARFDebugLine::Row::orderByAddress); + // The 'row_pos' iterator references the first row that is greater than + // our end address. The row before that is the last row we want. + last_row_index = cur_seq.FirstRowIndex + (row_pos - first_row) - 1; + } else + // Contrary to what you might expect, DWARFDebugLine::SequenceLastRowIndex + // isn't a valid index within the current sequence. It's that plus one. + last_row_index = cur_seq.LastRowIndex - 1; + + 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/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp new file mode 100644 index 0000000..fdb6dd2 --- /dev/null +++ b/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -0,0 +1,128 @@ +//===-- 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.reserve(str.size()); + std::copy(str.begin(), str.end(), std::back_inserter(E.Loc)); + 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( + 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/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp b/lib/DebugInfo/DWARF/DWARFDebugRangeList.cpp new file mode 100644 index 0000000..d5df688 --- /dev/null +++ b/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 \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/lib/DebugInfo/DWARF/DWARFFormValue.cpp b/lib/DebugInfo/DWARF/DWARFFormValue.cpp new file mode 100644 index 0000000..45bd197 --- /dev/null +++ b/lib/DebugInfo/DWARF/DWARFFormValue.cpp @@ -0,0 +1,565 @@ +//===-- 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 +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 +ArrayRef 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 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 < ArrayRef(DWARF4FormClasses).size() && + DWARF4FormClasses[Form] == FC) + return true; + // Check DW_FORM_ref_sig8 from DWARF4. + if (Form == DW_FORM_ref_sig8) + return (FC == FC_Reference); + // Check for some DWARF5 forms. + if (Form == DW_FORM_GNU_addr_index) + return (FC == FC_Address); + if (Form == DW_FORM_GNU_str_index) + 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. + if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) && + FC == FC_SectionOffset) + return true; + return false; +} + +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 &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_strp: { + 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_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: { + // 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(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) { + 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 += cu->getAddressByteSize(); + return true; + case DW_FORM_ref_addr: + *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); + 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_strp: + 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: + *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 << ""; + 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); + Optional DbgStr = getAsCString(cu); + if (DbgStr.hasValue()) { + raw_ostream &COS = WithColor(OS, syntax::String); + COS << '"'; + COS.write_escaped(DbgStr.getValue()); + COS << '"'; + } + break; + } + case DW_FORM_GNU_str_index: { + OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); + Optional DbgStr = getAsCString(cu); + if (DbgStr.hasValue()) { + raw_ostream &COS = WithColor(OS, syntax::String); + COS << '"'; + COS.write_escaped(DbgStr.getValue()); + COS << '"'; + } + 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; + + // 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 << "}"; + } +} + +Optional DWARFFormValue::getAsCString(const DWARFUnit *U) const { + if (!isFormClass(FC_String)) + return None; + if (Form == DW_FORM_string) + return Value.cstr; + if (!U) + 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 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 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 + default: + return Value.uval; + } +} + +Optional DWARFFormValue::getAsSectionOffset() const { + if (!isFormClass(FC_SectionOffset)) + return None; + return Value.uval; +} + +Optional DWARFFormValue::getAsUnsignedConstant() const { + if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) + || Form == DW_FORM_sdata) + return None; + return Value.uval; +} + +Optional> DWARFFormValue::getAsBlock() const { + if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc)) + return None; + return ArrayRef(Value.data, Value.uval); +} + diff --git a/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp b/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp new file mode 100644 index 0000000..65c7bff --- /dev/null +++ b/lib/DebugInfo/DWARF/DWARFTypeUnit.cpp @@ -0,0 +1,39 @@ +//===-- 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"; + + const DWARFDebugInfoEntryMinimal *CU = getCompileUnitDIE(false); + assert(CU && "Null Compile Unit?"); + CU->dump(OS, this, -1U); +} diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp new file mode 100644 index 0000000..d4ecd69 --- /dev/null +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -0,0 +1,377 @@ +//===-- 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 + +using 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.isLittleEndian()); +} + +void DWARFUnitSectionBase::parseDWO(DWARFContext &C, + const DWARFSection &DWOSection) { + parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(), + C.getStringDWOSection(), C.getStringOffsetDWOSection(), + C.getAddrSection(), C.isLittleEndian()); +} + +DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, + const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, + StringRef SOS, StringRef AOS, bool LE, + const DWARFUnitSectionBase &UnitSection) + : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS), + StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), + isLittleEndian(LE), UnitSection(UnitSection) { + 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); + 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); + if (Abbrevs == nullptr) + return false; + + return true; +} + +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 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 &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(DIContext::getDWARFContext(*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(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 TmpArray; + DieArray.swap(TmpArray); + // Save at least the compile unit DIE + if (KeepCUDie) + DieArray.push_back(TmpArray.front()); + } +} + +void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { + // First, check if CU DIE describes address ranges for the unit. + const auto &CUDIERanges = getCompileUnitDIE()->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); +} diff --git a/lib/DebugInfo/DWARF/LLVMBuild.txt b/lib/DebugInfo/DWARF/LLVMBuild.txt new file mode 100644 index 0000000..9f8b104 --- /dev/null +++ b/lib/DebugInfo/DWARF/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./lib/DebugInfo/DWARF/LLVMBuild.txt ----------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = DebugInfoDWARF +parent = DebugInfo +required_libraries = Object Support diff --git a/lib/DebugInfo/DWARF/Makefile b/lib/DebugInfo/DWARF/Makefile new file mode 100644 index 0000000..8633373 --- /dev/null +++ b/lib/DebugInfo/DWARF/Makefile @@ -0,0 +1,14 @@ +##===- lib/DebugInfo/DWARF/Makefile ------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMDebugInfoDWARF +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common diff --git a/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp b/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp new file mode 100644 index 0000000..a6b4c65 --- /dev/null +++ b/lib/DebugInfo/DWARF/SyntaxHighlighting.cpp @@ -0,0 +1,37 @@ +//===-- 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 + 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; + } + } +} + +WithColor::~WithColor() { + if (UseColor == cl::BOU_UNSET ? OS.has_colors() : UseColor == cl::BOU_TRUE) + OS.resetColor(); +} diff --git a/lib/DebugInfo/DWARF/SyntaxHighlighting.h b/lib/DebugInfo/DWARF/SyntaxHighlighting.h new file mode 100644 index 0000000..946a313 --- /dev/null +++ b/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 }; + +/// 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/lib/DebugInfo/DWARF/module.modulemap b/lib/DebugInfo/DWARF/module.modulemap new file mode 100644 index 0000000..c2f624f --- /dev/null +++ b/lib/DebugInfo/DWARF/module.modulemap @@ -0,0 +1 @@ +module DebugInfoDWARF { requires cplusplus umbrella "." module * { export * } } diff --git a/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp b/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp deleted file mode 100644 index c3e570e..0000000 --- a/lib/DebugInfo/DWARFAbbreviationDeclaration.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//===-- DWARFAbbreviationDeclaration.cpp ----------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "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/lib/DebugInfo/DWARFAbbreviationDeclaration.h b/lib/DebugInfo/DWARFAbbreviationDeclaration.h deleted file mode 100644 index bb05c30..0000000 --- a/lib/DebugInfo/DWARFAbbreviationDeclaration.h +++ /dev/null @@ -1,60 +0,0 @@ -//===-- DWARFAbbreviationDeclaration.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_DWARFABBREVIATIONDECLARATION_H -#define LLVM_LIB_DEBUGINFO_DWARFABBREVIATIONDECLARATION_H - -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/DataExtractor.h" - -namespace llvm { - -class raw_ostream; - -class DWARFAbbreviationDeclaration { - uint32_t Code; - uint32_t Tag; - bool HasChildren; - - struct AttributeSpec { - AttributeSpec(uint16_t Attr, uint16_t Form) : Attr(Attr), Form(Form) {} - uint16_t Attr; - uint16_t Form; - }; - typedef SmallVector AttributeSpecVector; - AttributeSpecVector AttributeSpecs; -public: - DWARFAbbreviationDeclaration(); - - uint32_t getCode() const { return Code; } - uint32_t getTag() const { return Tag; } - bool hasChildren() const { return HasChildren; } - - typedef iterator_range - attr_iterator_range; - - attr_iterator_range attributes() const { - return attr_iterator_range(AttributeSpecs.begin(), AttributeSpecs.end()); - } - - uint16_t getFormByIndex(uint32_t idx) const { - return idx < AttributeSpecs.size() ? AttributeSpecs[idx].Form : 0; - } - - uint32_t findAttributeIndex(uint16_t attr) const; - bool extract(DataExtractor Data, uint32_t* OffsetPtr); - void dump(raw_ostream &OS) const; - -private: - void clear(); -}; - -} - -#endif diff --git a/lib/DebugInfo/DWARFAcceleratorTable.cpp b/lib/DebugInfo/DWARFAcceleratorTable.cpp deleted file mode 100644 index 703274d..0000000 --- a/lib/DebugInfo/DWARFAcceleratorTable.cpp +++ /dev/null @@ -1,133 +0,0 @@ -//===--- DWARFAcceleratorTable.cpp ----------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "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 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/lib/DebugInfo/DWARFAcceleratorTable.h b/lib/DebugInfo/DWARFAcceleratorTable.h deleted file mode 100644 index 7dc9591..0000000 --- a/lib/DebugInfo/DWARFAcceleratorTable.h +++ /dev/null @@ -1,51 +0,0 @@ -//===--- DWARFAcceleratorTable.h --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFRelocMap.h" - -#include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/DWARFFormValue.h" - -#include - -namespace llvm { - -class DWARFAcceleratorTable { - - struct Header { - uint32_t Magic; - uint16_t Version; - uint16_t HashFunction; - uint32_t NumBuckets; - uint32_t NumHashes; - uint32_t HeaderDataLength; - }; - - struct HeaderData { - typedef uint16_t AtomType; - typedef uint16_t Form; - uint32_t DIEOffsetBase; - SmallVector, 3> Atoms; - }; - - struct Header Hdr; - struct HeaderData HdrData; - DataExtractor AccelSection; - DataExtractor StringSection; - const RelocAddrMap& Relocs; -public: - DWARFAcceleratorTable(DataExtractor AccelSection, DataExtractor StringSection, - const RelocAddrMap &Relocs) - : AccelSection(AccelSection), StringSection(StringSection), Relocs(Relocs) {} - - bool extract(); - void dump(raw_ostream &OS) const; -}; - -} diff --git a/lib/DebugInfo/DWARFCompileUnit.cpp b/lib/DebugInfo/DWARFCompileUnit.cpp deleted file mode 100644 index 33869d8..0000000 --- a/lib/DebugInfo/DWARFCompileUnit.cpp +++ /dev/null @@ -1,32 +0,0 @@ -//===-- DWARFCompileUnit.cpp ----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "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"; - - const DWARFDebugInfoEntryMinimal *CU = getCompileUnitDIE(false); - assert(CU && "Null Compile Unit?"); - CU->dump(OS, this, -1U); -} - -// VTable anchor. -DWARFCompileUnit::~DWARFCompileUnit() { -} diff --git a/lib/DebugInfo/DWARFCompileUnit.h b/lib/DebugInfo/DWARFCompileUnit.h deleted file mode 100644 index b3190b18..0000000 --- a/lib/DebugInfo/DWARFCompileUnit.h +++ /dev/null @@ -1,31 +0,0 @@ -//===-- DWARFCompileUnit.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_DWARFCOMPILEUNIT_H -#define LLVM_LIB_DEBUGINFO_DWARFCOMPILEUNIT_H - -#include "DWARFUnit.h" - -namespace llvm { - -class DWARFCompileUnit : public DWARFUnit { -public: - DWARFCompileUnit(DWARFContext &Context, const DWARFSection &Section, - const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, - StringRef SOS, StringRef AOS, bool LE, - const DWARFUnitSectionBase &UnitSection) - : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} - void dump(raw_ostream &OS); - // VTable anchor. - ~DWARFCompileUnit() override; -}; - -} - -#endif diff --git a/lib/DebugInfo/DWARFContext.cpp b/lib/DebugInfo/DWARFContext.cpp deleted file mode 100644 index 9a2c7cc..0000000 --- a/lib/DebugInfo/DWARFContext.cpp +++ /dev/null @@ -1,697 +0,0 @@ -//===-- DWARFContext.cpp --------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFContext.h" -#include "DWARFDebugArangeSet.h" -#include "DWARFAcceleratorTable.h" - -#include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringSwitch.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 -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); - } - - 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(); - unsigned stmtOffset = - CU->getCompileUnitDIE()->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_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 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 DWARFLineTable * -DWARFContext::getLineTableForUnit(DWARFUnit *cu) { - if (!Line) - Line.reset(new DWARFDebugLine(&getLineSection().Relocs)); - - unsigned stmtOffset = - cu->getCompileUnitDIE()->getAttributeValueAsSectionOffset( - cu, DW_AT_stmt_list, -1U); - if (stmtOffset == -1U) - return nullptr; // No line table for this compile unit. - - // See if the line table is cached. - if (const DWARFLineTable *lt = Line->getLineTable(stmtOffset)) - return lt; - - // We have to parse it first. - DataExtractor lineData(getLineSection().Data, isLittleEndian(), - cu->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.push_back(DWARFUnitSection()); - 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.push_back(DWARFUnitSection()); - 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 = ""; - 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 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) - : 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.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(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_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) - // 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; - } - - section_iterator RelocatedSection = Section.getRelocatedSection(); - if (RelocatedSection == Obj.section_end()) - continue; - - StringRef RelSecName; - RelocatedSection->getName(RelSecName); - 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(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(Address); - uint64_t Type; - Reloc.getType(Type); - uint64_t SymAddr = 0; - object::symbol_iterator Sym = Reloc.getSymbol(); - if (Sym != Obj.symbol_end()) - Sym->getAddress(SymAddr); - - object::RelocVisitor V(Obj); - object::RelocToApply R(V.visit(Type, Reloc, SymAddr)); - if (V.error()) { - SmallString<32> Name; - std::error_code ec(Reloc.getTypeName(Name)); - if (ec) { - errs() << "Aaaaaa! Nameless relocation! Aaaaaa!\n"; - } - 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/lib/DebugInfo/DWARFContext.h b/lib/DebugInfo/DWARFContext.h deleted file mode 100644 index dd3fcc7..0000000 --- a/lib/DebugInfo/DWARFContext.h +++ /dev/null @@ -1,292 +0,0 @@ -//===-- DWARFContext.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_DWARFCONTEXT_H -#define LLVM_LIB_DEBUGINFO_DWARFCONTEXT_H - -#include "DWARFCompileUnit.h" -#include "DWARFDebugAranges.h" -#include "DWARFDebugFrame.h" -#include "DWARFDebugLine.h" -#include "DWARFDebugLoc.h" -#include "DWARFDebugRangeList.h" -#include "DWARFSection.h" -#include "DWARFTypeUnit.h" -#include "llvm/ADT/MapVector.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/DIContext.h" -#include - -namespace llvm { - -/// DWARFContext -/// This data structure is the top level entity that deals with dwarf debug -/// information parsing. The actual data is supplied through pure virtual -/// methods that a concrete implementation provides. -class DWARFContext : public DIContext { - - DWARFUnitSection CUs; - std::vector> TUs; - std::unique_ptr Abbrev; - std::unique_ptr Loc; - std::unique_ptr Aranges; - std::unique_ptr Line; - std::unique_ptr DebugFrame; - - DWARFUnitSection DWOCUs; - std::vector> DWOTUs; - std::unique_ptr AbbrevDWO; - std::unique_ptr LocDWO; - - DWARFContext(DWARFContext &) LLVM_DELETED_FUNCTION; - DWARFContext &operator=(DWARFContext &) LLVM_DELETED_FUNCTION; - - /// Read compile units from the debug_info section (if necessary) - /// and store them in CUs. - void parseCompileUnits(); - - /// Read type units from the debug_types sections (if necessary) - /// and store them in TUs. - void parseTypeUnits(); - - /// Read compile units from the debug_info.dwo section (if necessary) - /// and store them in DWOCUs. - void parseDWOCompileUnits(); - - /// Read type units from the debug_types.dwo section (if necessary) - /// and store them in DWOTUs. - void parseDWOTypeUnits(); - -public: - DWARFContext() : DIContext(CK_DWARF) {} - - static bool classof(const DIContext *DICtx) { - return DICtx->getKind() == CK_DWARF; - } - - void dump(raw_ostream &OS, DIDumpType DumpType = DIDT_All) override; - - typedef DWARFUnitSection::iterator_range cu_iterator_range; - typedef DWARFUnitSection::iterator_range tu_iterator_range; - typedef iterator_range>::iterator> tu_section_iterator_range; - - /// Get compile units in this context. - cu_iterator_range compile_units() { - parseCompileUnits(); - return cu_iterator_range(CUs.begin(), CUs.end()); - } - - /// Get type units in this context. - tu_section_iterator_range type_unit_sections() { - parseTypeUnits(); - return tu_section_iterator_range(TUs.begin(), TUs.end()); - } - - /// Get compile units in the DWO context. - cu_iterator_range dwo_compile_units() { - parseDWOCompileUnits(); - return cu_iterator_range(DWOCUs.begin(), DWOCUs.end()); - } - - /// Get type units in the DWO context. - tu_section_iterator_range dwo_type_unit_sections() { - parseDWOTypeUnits(); - return tu_section_iterator_range(DWOTUs.begin(), DWOTUs.end()); - } - - /// Get the number of compile units in this context. - unsigned getNumCompileUnits() { - parseCompileUnits(); - return CUs.size(); - } - - /// Get the number of compile units in this context. - unsigned getNumTypeUnits() { - parseTypeUnits(); - return TUs.size(); - } - - /// Get the number of compile units in the DWO context. - unsigned getNumDWOCompileUnits() { - parseDWOCompileUnits(); - return DWOCUs.size(); - } - - /// Get the number of compile units in the DWO context. - unsigned getNumDWOTypeUnits() { - parseDWOTypeUnits(); - return DWOTUs.size(); - } - - /// Get the compile unit at the specified index for this compile unit. - DWARFCompileUnit *getCompileUnitAtIndex(unsigned index) { - parseCompileUnits(); - return CUs[index].get(); - } - - /// Get the compile unit at the specified index for the DWO compile units. - DWARFCompileUnit *getDWOCompileUnitAtIndex(unsigned index) { - parseDWOCompileUnits(); - return DWOCUs[index].get(); - } - - /// Get a pointer to the parsed DebugAbbrev object. - const DWARFDebugAbbrev *getDebugAbbrev(); - - /// Get a pointer to the parsed DebugLoc object. - const DWARFDebugLoc *getDebugLoc(); - - /// Get a pointer to the parsed dwo abbreviations object. - const DWARFDebugAbbrev *getDebugAbbrevDWO(); - - /// Get a pointer to the parsed DebugLoc object. - const DWARFDebugLocDWO *getDebugLocDWO(); - - /// Get a pointer to the parsed DebugAranges object. - const DWARFDebugAranges *getDebugAranges(); - - /// Get a pointer to the parsed frame information object. - const DWARFDebugFrame *getDebugFrame(); - - /// Get a pointer to a parsed line table corresponding to a compile unit. - const DWARFDebugLine::LineTable *getLineTableForUnit(DWARFUnit *cu); - - DILineInfo getLineInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; - DILineInfoTable getLineInfoForAddressRange(uint64_t Address, uint64_t Size, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; - DIInliningInfo getInliningInfoForAddress(uint64_t Address, - DILineInfoSpecifier Specifier = DILineInfoSpecifier()) override; - - virtual bool isLittleEndian() const = 0; - virtual uint8_t getAddressSize() const = 0; - virtual const DWARFSection &getInfoSection() = 0; - typedef MapVector> TypeSectionMap; - virtual const TypeSectionMap &getTypesSections() = 0; - virtual StringRef getAbbrevSection() = 0; - virtual const DWARFSection &getLocSection() = 0; - virtual StringRef getARangeSection() = 0; - virtual StringRef getDebugFrameSection() = 0; - virtual const DWARFSection &getLineSection() = 0; - virtual StringRef getStringSection() = 0; - virtual StringRef getRangeSection() = 0; - virtual StringRef getPubNamesSection() = 0; - virtual StringRef getPubTypesSection() = 0; - virtual StringRef getGnuPubNamesSection() = 0; - virtual StringRef getGnuPubTypesSection() = 0; - - // Sections for DWARF5 split dwarf proposal. - virtual const DWARFSection &getInfoDWOSection() = 0; - virtual const TypeSectionMap &getTypesDWOSections() = 0; - virtual StringRef getAbbrevDWOSection() = 0; - virtual const DWARFSection &getLineDWOSection() = 0; - virtual const DWARFSection &getLocDWOSection() = 0; - virtual StringRef getStringDWOSection() = 0; - virtual StringRef getStringOffsetDWOSection() = 0; - virtual StringRef getRangeDWOSection() = 0; - virtual StringRef getAddrSection() = 0; - virtual const DWARFSection& getAppleNamesSection() = 0; - virtual const DWARFSection& getAppleTypesSection() = 0; - virtual const DWARFSection& getAppleNamespacesSection() = 0; - virtual const DWARFSection& getAppleObjCSection() = 0; - - static bool isSupportedVersion(unsigned version) { - return version == 2 || version == 3 || version == 4; - } -private: - /// Return the compile unit that includes an offset (relative to .debug_info). - DWARFCompileUnit *getCompileUnitForOffset(uint32_t Offset); - - /// Return the compile unit which contains instruction with provided - /// address. - DWARFCompileUnit *getCompileUnitForAddress(uint64_t Address); -}; - -/// DWARFContextInMemory is the simplest possible implementation of a -/// DWARFContext. It assumes all content is available in memory and stores -/// pointers to it. -class DWARFContextInMemory : public DWARFContext { - virtual void anchor(); - bool IsLittleEndian; - uint8_t AddressSize; - DWARFSection InfoSection; - TypeSectionMap TypesSections; - StringRef AbbrevSection; - DWARFSection LocSection; - StringRef ARangeSection; - StringRef DebugFrameSection; - DWARFSection LineSection; - StringRef StringSection; - StringRef RangeSection; - StringRef PubNamesSection; - StringRef PubTypesSection; - StringRef GnuPubNamesSection; - StringRef GnuPubTypesSection; - - // Sections for DWARF5 split dwarf proposal. - DWARFSection InfoDWOSection; - TypeSectionMap TypesDWOSections; - StringRef AbbrevDWOSection; - DWARFSection LineDWOSection; - DWARFSection LocDWOSection; - StringRef StringDWOSection; - StringRef StringOffsetDWOSection; - StringRef RangeDWOSection; - StringRef AddrSection; - DWARFSection AppleNamesSection; - DWARFSection AppleTypesSection; - DWARFSection AppleNamespacesSection; - DWARFSection AppleObjCSection; - - SmallVector, 4> UncompressedSections; - -public: - DWARFContextInMemory(const object::ObjectFile &Obj); - bool isLittleEndian() const override { return IsLittleEndian; } - uint8_t getAddressSize() const override { return AddressSize; } - const DWARFSection &getInfoSection() override { return InfoSection; } - const TypeSectionMap &getTypesSections() override { return TypesSections; } - StringRef getAbbrevSection() override { return AbbrevSection; } - const DWARFSection &getLocSection() override { return LocSection; } - StringRef getARangeSection() override { return ARangeSection; } - StringRef getDebugFrameSection() override { return DebugFrameSection; } - const DWARFSection &getLineSection() override { return LineSection; } - StringRef getStringSection() override { return StringSection; } - StringRef getRangeSection() override { return RangeSection; } - StringRef getPubNamesSection() override { return PubNamesSection; } - StringRef getPubTypesSection() override { return PubTypesSection; } - StringRef getGnuPubNamesSection() override { return GnuPubNamesSection; } - StringRef getGnuPubTypesSection() override { return GnuPubTypesSection; } - const DWARFSection& getAppleNamesSection() override { return AppleNamesSection; } - const DWARFSection& getAppleTypesSection() override { return AppleTypesSection; } - const DWARFSection& getAppleNamespacesSection() override { return AppleNamespacesSection; } - const DWARFSection& getAppleObjCSection() override { return AppleObjCSection; } - - // Sections for DWARF5 split dwarf proposal. - const DWARFSection &getInfoDWOSection() override { return InfoDWOSection; } - const TypeSectionMap &getTypesDWOSections() override { - return TypesDWOSections; - } - StringRef getAbbrevDWOSection() override { return AbbrevDWOSection; } - const DWARFSection &getLineDWOSection() override { return LineDWOSection; } - const DWARFSection &getLocDWOSection() override { return LocDWOSection; } - StringRef getStringDWOSection() override { return StringDWOSection; } - StringRef getStringOffsetDWOSection() override { - return StringOffsetDWOSection; - } - StringRef getRangeDWOSection() override { return RangeDWOSection; } - StringRef getAddrSection() override { - return AddrSection; - } -}; - -} - -#endif diff --git a/lib/DebugInfo/DWARFDebugAbbrev.cpp b/lib/DebugInfo/DWARFDebugAbbrev.cpp deleted file mode 100644 index c1a088e..0000000 --- a/lib/DebugInfo/DWARFDebugAbbrev.cpp +++ /dev/null @@ -1,115 +0,0 @@ -//===-- DWARFDebugAbbrev.cpp ----------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "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/lib/DebugInfo/DWARFDebugAbbrev.h b/lib/DebugInfo/DWARFDebugAbbrev.h deleted file mode 100644 index 4b3b814..0000000 --- a/lib/DebugInfo/DWARFDebugAbbrev.h +++ /dev/null @@ -1,63 +0,0 @@ -//===-- DWARFDebugAbbrev.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_DWARFDEBUGABBREV_H -#define LLVM_LIB_DEBUGINFO_DWARFDEBUGABBREV_H - -#include "DWARFAbbreviationDeclaration.h" -#include -#include -#include - -namespace llvm { - -class DWARFAbbreviationDeclarationSet { - uint32_t Offset; - /// Code of the first abbreviation, if all abbreviations in the set have - /// consecutive codes. UINT32_MAX otherwise. - uint32_t FirstAbbrCode; - std::vector Decls; - -public: - DWARFAbbreviationDeclarationSet(); - - uint32_t getOffset() const { return Offset; } - void dump(raw_ostream &OS) const; - bool extract(DataExtractor Data, uint32_t *OffsetPtr); - - const DWARFAbbreviationDeclaration * - getAbbreviationDeclaration(uint32_t AbbrCode) const; - -private: - void clear(); -}; - -class DWARFDebugAbbrev { - typedef std::map - DWARFAbbreviationDeclarationSetMap; - - DWARFAbbreviationDeclarationSetMap AbbrDeclSets; - mutable DWARFAbbreviationDeclarationSetMap::const_iterator PrevAbbrOffsetPos; - -public: - DWARFDebugAbbrev(); - - const DWARFAbbreviationDeclarationSet * - getAbbreviationDeclarationSet(uint64_t CUAbbrOffset) const; - - void dump(raw_ostream &OS) const; - void extract(DataExtractor Data); - -private: - void clear(); -}; - -} - -#endif diff --git a/lib/DebugInfo/DWARFDebugArangeSet.cpp b/lib/DebugInfo/DWARFDebugArangeSet.cpp deleted file mode 100644 index c0a33ce..0000000 --- a/lib/DebugInfo/DWARFDebugArangeSet.cpp +++ /dev/null @@ -1,104 +0,0 @@ -//===-- DWARFDebugArangeSet.cpp -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFDebugArangeSet.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -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/lib/DebugInfo/DWARFDebugArangeSet.h b/lib/DebugInfo/DWARFDebugArangeSet.h deleted file mode 100644 index 837a8e6..0000000 --- a/lib/DebugInfo/DWARFDebugArangeSet.h +++ /dev/null @@ -1,70 +0,0 @@ -//===-- DWARFDebugArangeSet.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_DWARFDEBUGARANGESET_H -#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGESET_H - -#include "llvm/ADT/iterator_range.h" -#include "llvm/Support/DataExtractor.h" -#include - -namespace llvm { - -class raw_ostream; - -class DWARFDebugArangeSet { -public: - struct Header { - // The total length of the entries for that set, not including the length - // field itself. - uint32_t Length; - // The offset from the beginning of the .debug_info section of the - // compilation unit entry referenced by the table. - uint32_t CuOffset; - // The DWARF version number. - uint16_t Version; - // The size in bytes of an address on the target architecture. For segmented - // addressing, this is the size of the offset portion of the address. - uint8_t AddrSize; - // The size in bytes of a segment descriptor on the target architecture. - // If the target system uses a flat address space, this value is 0. - uint8_t SegSize; - }; - - struct Descriptor { - uint64_t Address; - uint64_t Length; - uint64_t getEndAddress() const { return Address + Length; } - }; - -private: - typedef std::vector DescriptorColl; - typedef iterator_range desc_iterator_range; - - uint32_t Offset; - Header HeaderData; - DescriptorColl ArangeDescriptors; - -public: - DWARFDebugArangeSet() { clear(); } - void clear(); - bool extract(DataExtractor data, uint32_t *offset_ptr); - void dump(raw_ostream &OS) const; - - uint32_t getCompileUnitDIEOffset() const { return HeaderData.CuOffset; } - - desc_iterator_range descriptors() const { - return desc_iterator_range(ArangeDescriptors.begin(), - ArangeDescriptors.end()); - } -}; - -} - -#endif diff --git a/lib/DebugInfo/DWARFDebugAranges.cpp b/lib/DebugInfo/DWARFDebugAranges.cpp deleted file mode 100644 index fe7e46d..0000000 --- a/lib/DebugInfo/DWARFDebugAranges.cpp +++ /dev/null @@ -1,129 +0,0 @@ -//===-- 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 "DWARFDebugAranges.h" -#include "DWARFCompileUnit.h" -#include "DWARFContext.h" -#include "DWARFDebugArangeSet.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include -#include -#include -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 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 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/lib/DebugInfo/DWARFDebugAranges.h b/lib/DebugInfo/DWARFDebugAranges.h deleted file mode 100644 index 791f010..0000000 --- a/lib/DebugInfo/DWARFDebugAranges.h +++ /dev/null @@ -1,87 +0,0 @@ -//===-- DWARFDebugAranges.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_DWARFDEBUGARANGES_H -#define LLVM_LIB_DEBUGINFO_DWARFDEBUGARANGES_H - -#include "llvm/ADT/DenseSet.h" -#include "llvm/Support/DataExtractor.h" -#include - -namespace llvm { - -class DWARFContext; - -class DWARFDebugAranges { -public: - void generate(DWARFContext *CTX); - uint32_t findAddress(uint64_t Address) const; - -private: - void clear(); - void extract(DataExtractor DebugArangesData); - - // Call appendRange multiple times and then call construct. - void appendRange(uint32_t CUOffset, uint64_t LowPC, uint64_t HighPC); - void construct(); - - struct Range { - explicit Range(uint64_t LowPC = -1ULL, uint64_t HighPC = -1ULL, - uint32_t CUOffset = -1U) - : LowPC(LowPC), Length(HighPC - LowPC), CUOffset(CUOffset) {} - - void setHighPC(uint64_t HighPC) { - if (HighPC == -1ULL || HighPC <= LowPC) - Length = 0; - else - Length = HighPC - LowPC; - } - uint64_t HighPC() const { - if (Length) - return LowPC + Length; - return -1ULL; - } - - bool containsAddress(uint64_t Address) const { - return LowPC <= Address && Address < HighPC(); - } - bool operator<(const Range &other) const { - return LowPC < other.LowPC; - } - - uint64_t LowPC; // Start of address range. - uint32_t Length; // End of address range (not including this address). - uint32_t CUOffset; // Offset of the compile unit or die. - }; - - struct RangeEndpoint { - uint64_t Address; - uint32_t CUOffset; - bool IsRangeStart; - - RangeEndpoint(uint64_t Address, uint32_t CUOffset, bool IsRangeStart) - : Address(Address), CUOffset(CUOffset), IsRangeStart(IsRangeStart) {} - - bool operator<(const RangeEndpoint &Other) const { - return Address < Other.Address; - } - }; - - - typedef std::vector RangeColl; - typedef RangeColl::const_iterator RangeCollIterator; - - std::vector Endpoints; - RangeColl Aranges; - DenseSet ParsedCUOffsets; -}; - -} - -#endif diff --git a/lib/DebugInfo/DWARFDebugFrame.cpp b/lib/DebugInfo/DWARFDebugFrame.cpp deleted file mode 100644 index dfa7e82..0000000 --- a/lib/DebugInfo/DWARFDebugFrame.cpp +++ /dev/null @@ -1,374 +0,0 @@ -//===-- 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 "DWARFDebugFrame.h" -#include "llvm/ADT/SmallString.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 -#include - -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 Operands; - struct Instruction { - Instruction(uint8_t Opcode) - : Opcode(Opcode) - {} - - uint8_t Opcode; - Operands Ops; - }; - - std::vector 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!"); - } - } - } -} - - -void FrameEntry::dumpInstructions(raw_ostream &OS) const { - // TODO: at the moment only instruction names are dumped. Expand this to - // dump operands as well. - 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) << ":\n"; - } -} - - -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, uint64_t CodeAlignmentFactor, - int64_t DataAlignmentFactor, uint64_t ReturnAddressRegister) - : FrameEntry(FK_CIE, Offset, Length), Version(Version), - Augmentation(std::move(Augmentation)), - CodeAlignmentFactor(CodeAlignmentFactor), - DataAlignmentFactor(DataAlignmentFactor), - ReturnAddressRegister(ReturnAddressRegister) {} - - ~CIE() { - } - - 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"; - 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 v3 - uint8_t Version; - SmallString<8> Augmentation; - 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) - : FrameEntry(FK_FDE, Offset, Length), LinkedCIEOffset(LinkedCIEOffset), - InitialLocation(InitialLocation), AddressRange(AddressRange), - LinkedCIE(nullptr) {} - - ~FDE() { - } - - 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); - if (LinkedCIE) { - OS << format("%p\n", LinkedCIE); - } - } - - 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; -}; -} // end anonymous namespace - - -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; - - 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(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) { - // Note: this is specifically DWARFv3 CIE header structure. It was - // changed in DWARFv4. We currently don't support reading DWARFv4 - // here because LLVM itself does not emit it (and LLDB doesn't - // support it either). - uint8_t Version = Data.getU8(&Offset); - const char *Augmentation = Data.getCStr(&Offset); - uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset); - int64_t DataAlignmentFactor = Data.getSLEB128(&Offset); - uint64_t ReturnAddressRegister = Data.getULEB128(&Offset); - - Entries.emplace_back(new CIE(StartOffset, Length, Version, - StringRef(Augmentation), CodeAlignmentFactor, - DataAlignmentFactor, ReturnAddressRegister)); - } 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)); - } - - 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/lib/DebugInfo/DWARFDebugFrame.h b/lib/DebugInfo/DWARFDebugFrame.h deleted file mode 100644 index be925cb..0000000 --- a/lib/DebugInfo/DWARFDebugFrame.h +++ /dev/null @@ -1,43 +0,0 @@ -//===-- 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. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H -#define LLVM_LIB_DEBUGINFO_DWARFDEBUGFRAME_H - -#include "llvm/Support/DataExtractor.h" -#include "llvm/Support/raw_ostream.h" -#include -#include - -namespace llvm { - -class FrameEntry; - -/// \brief A parsed .debug_frame section -/// -class DWARFDebugFrame { -public: - DWARFDebugFrame(); - ~DWARFDebugFrame(); - - /// \brief Dump the section data into the given stream. - void dump(raw_ostream &OS) const; - - /// \brief Parse the section from raw data. - /// data is assumed to be pointing to the beginning of the section. - void parse(DataExtractor Data); - -private: - std::vector> Entries; -}; - - -} // namespace llvm - -#endif diff --git a/lib/DebugInfo/DWARFDebugInfoEntry.cpp b/lib/DebugInfo/DWARFDebugInfoEntry.cpp deleted file mode 100644 index 583e700..0000000 --- a/lib/DebugInfo/DWARFDebugInfoEntry.cpp +++ /dev/null @@ -1,451 +0,0 @@ -//===-- DWARFDebugInfoEntry.cpp -------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFDebugInfoEntry.h" -#include "DWARFCompileUnit.h" -#include "DWARFContext.h" -#include "DWARFDebugAbbrev.h" -#include "llvm/DebugInfo/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; - -// 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); - - OS << format("\n0x%8.8x: ", Offset); - if (abbrCode) { - if (AbbrevDecl) { - const char *tagString = TagString(getTag()); - if (tagString) - OS.indent(indent) << tagString; - else - OS.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 Bit = 1ULL << countTrailingZeros(Val); - 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) - OS << attrString; - else - OS << 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; - if (attr == DW_AT_decl_file || attr == DW_AT_call_file) { - 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 Val = formValue.getAsUnsignedConstant()) - Name = AttributeValueString(attr, *Val); - - if (Name) { - OS << 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) && - // The signature references aren't handled. - formValue.getForm() != DW_FORM_ref_sig8) { - uint32_t Ref = formValue.getAsReference(u).getValue(); - DWARFDebugInfoEntryMinimal DIE; - if (const DWARFUnit *RefU = findUnitAndExtractFast(DIE, u, &Ref)) - if (const char *Ref = DIE.getName(RefU, DINameKind::LinkageName)) - OS << " \"" << Ref << '\"'; - } else if (attr == DW_AT_APPLE_property_attribute) { - if (Optional 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 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 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 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 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 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 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/lib/DebugInfo/DWARFDebugInfoEntry.h b/lib/DebugInfo/DWARFDebugInfoEntry.h deleted file mode 100644 index 7e7efb9..0000000 --- a/lib/DebugInfo/DWARFDebugInfoEntry.h +++ /dev/null @@ -1,160 +0,0 @@ -//===-- DWARFDebugInfoEntry.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_DWARFDEBUGINFOENTRY_H -#define LLVM_LIB_DEBUGINFO_DWARFDEBUGINFOENTRY_H - -#include "DWARFAbbreviationDeclaration.h" -#include "DWARFDebugRangeList.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/DebugInfo/DIContext.h" -#include "llvm/Support/DataTypes.h" - -namespace llvm { - -class DWARFDebugAranges; -class DWARFCompileUnit; -class DWARFUnit; -class DWARFContext; -class DWARFFormValue; -struct DWARFDebugInfoEntryInlinedChain; - -/// DWARFDebugInfoEntryMinimal - A DIE with only the minimum required data. -class DWARFDebugInfoEntryMinimal { - /// Offset within the .debug_info of the start of this entry. - uint32_t Offset; - - /// How many to add to "this" to get the sibling. - uint32_t SiblingIdx; - - const DWARFAbbreviationDeclaration *AbbrevDecl; -public: - DWARFDebugInfoEntryMinimal() - : Offset(0), SiblingIdx(0), AbbrevDecl(nullptr) {} - - void dump(raw_ostream &OS, DWARFUnit *u, unsigned recurseDepth, - unsigned indent = 0) const; - void dumpAttribute(raw_ostream &OS, DWARFUnit *u, uint32_t *offset_ptr, - uint16_t attr, uint16_t form, unsigned indent = 0) const; - - /// Extracts a debug info entry, which is a child of a given unit, - /// starting at a given offset. If DIE can't be extracted, returns false and - /// doesn't change OffsetPtr. - bool extractFast(const DWARFUnit *U, uint32_t *OffsetPtr); - - uint32_t getTag() const { return AbbrevDecl ? AbbrevDecl->getTag() : 0; } - bool isNULL() const { return AbbrevDecl == nullptr; } - - /// Returns true if DIE represents a subprogram (not inlined). - bool isSubprogramDIE() const; - /// Returns true if DIE represents a subprogram or an inlined - /// subroutine. - bool isSubroutineDIE() const; - - uint32_t getOffset() const { return Offset; } - bool hasChildren() const { return !isNULL() && AbbrevDecl->hasChildren(); } - - // We know we are kept in a vector of contiguous entries, so we know - // our sibling will be some index after "this". - const DWARFDebugInfoEntryMinimal *getSibling() const { - return SiblingIdx > 0 ? this + SiblingIdx : nullptr; - } - - // We know we are kept in a vector of contiguous entries, so we know - // we don't need to store our child pointer, if we have a child it will - // be the next entry in the list... - const DWARFDebugInfoEntryMinimal *getFirstChild() const { - return hasChildren() ? this + 1 : nullptr; - } - - void setSibling(const DWARFDebugInfoEntryMinimal *Sibling) { - if (Sibling) { - // We know we are kept in a vector of contiguous entries, so we know - // our sibling will be some index after "this". - SiblingIdx = Sibling - this; - } else - SiblingIdx = 0; - } - - const DWARFAbbreviationDeclaration *getAbbreviationDeclarationPtr() const { - return AbbrevDecl; - } - - bool getAttributeValue(const DWARFUnit *U, const uint16_t Attr, - DWARFFormValue &FormValue) const; - - const char *getAttributeValueAsString(const DWARFUnit *U, const uint16_t Attr, - const char *FailValue) const; - - uint64_t getAttributeValueAsAddress(const DWARFUnit *U, const uint16_t Attr, - uint64_t FailValue) const; - - uint64_t getAttributeValueAsUnsignedConstant(const DWARFUnit *U, - const uint16_t Attr, - uint64_t FailValue) const; - - uint64_t getAttributeValueAsReference(const DWARFUnit *U, const uint16_t Attr, - uint64_t FailValue) const; - - uint64_t getAttributeValueAsSectionOffset(const DWARFUnit *U, - const uint16_t Attr, - uint64_t FailValue) const; - - uint64_t getRangesBaseAttribute(const DWARFUnit *U, uint64_t FailValue) const; - - /// Retrieves DW_AT_low_pc and DW_AT_high_pc from CU. - /// Returns true if both attributes are present. - bool getLowAndHighPC(const DWARFUnit *U, uint64_t &LowPC, - uint64_t &HighPC) const; - - DWARFAddressRangesVector getAddressRanges(const DWARFUnit *U) const; - - void collectChildrenAddressRanges(const DWARFUnit *U, - DWARFAddressRangesVector &Ranges) const; - - bool addressRangeContainsAddress(const DWARFUnit *U, - const uint64_t Address) const; - - /// If a DIE represents a subprogram (or inlined subroutine), - /// returns its mangled name (or short name, if mangled is missing). - /// This name may be fetched from specification or abstract origin - /// for this subprogram. Returns null if no name is found. - const char *getSubroutineName(const DWARFUnit *U, DINameKind Kind) const; - - /// Return the DIE name resolving DW_AT_sepcification or - /// DW_AT_abstract_origin references if necessary. - /// Returns null if no name is found. - const char *getName(const DWARFUnit *U, DINameKind Kind) const; - - /// Retrieves values of DW_AT_call_file, DW_AT_call_line and - /// DW_AT_call_column from DIE (or zeroes if they are missing). - void getCallerFrame(const DWARFUnit *U, uint32_t &CallFile, - uint32_t &CallLine, uint32_t &CallColumn) const; - - /// Get inlined chain for a given address, rooted at the current DIE. - /// Returns empty chain if address is not contained in address range - /// of current DIE. - DWARFDebugInfoEntryInlinedChain - getInlinedChainForAddress(const DWARFUnit *U, const uint64_t Address) const; -}; - -/// DWARFDebugInfoEntryInlinedChain - represents a chain of inlined_subroutine -/// DIEs, (possibly ending with subprogram DIE), all of which are contained -/// in some concrete inlined instance tree. Address range for each DIE -/// (except the last DIE) in this chain is contained in address -/// range for next DIE in the chain. -struct DWARFDebugInfoEntryInlinedChain { - DWARFDebugInfoEntryInlinedChain() : U(nullptr) {} - SmallVector DIEs; - const DWARFUnit *U; -}; - -} - -#endif diff --git a/lib/DebugInfo/DWARFDebugLine.cpp b/lib/DebugInfo/DWARFDebugLine.cpp deleted file mode 100644 index a6ee461..0000000 --- a/lib/DebugInfo/DWARFDebugLine.cpp +++ /dev/null @@ -1,698 +0,0 @@ -//===-- DWARFDebugLine.cpp ------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFDebugLine.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/raw_ostream.h" -#include -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; - StandardOpcodeLengths.clear(); - IncludeDirectories.clear(); - FileNames.clear(); -} - -void DWARFDebugLine::Prologue::dump(raw_ostream &OS) const { - OS << "Line table prologue:\n" - << format(" total_length: 0x%8.8x\n", TotalLength) - << format(" version: %u\n", Version) - << format(" prologue_length: 0x%8.8x\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 uint32_t prologue_offset = *offset_ptr; - - clear(); - TotalLength = debug_line_data.getU32(offset_ptr); - Version = debug_line_data.getU16(offset_ptr); - if (Version < 2) - return false; - - PrologueLength = debug_line_data.getU32(offset_ptr); - const uint32_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.8x should" - " have ended at 0x%8.8x but it ended at 0x%8.8x\n", - prologue_offset, end_prologue_offset, *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 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 + - sizeof(Prologue.TotalLength); - - 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 &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::lookupAddress(uint64_t address) const { - uint32_t unknown_index = UINT32_MAX; - if (Sequences.empty()) - return unknown_index; - // 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 unknown_index; - found_seq = *(seq_pos - 1); - } - if (!found_seq.containsPC(address)) - return unknown_index; - // 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() + found_seq.FirstRowIndex; - RowIter last_row = Rows.begin() + found_seq.LastRowIndex; - RowIter row_pos = std::lower_bound(first_row, last_row, row, - DWARFDebugLine::Row::orderByAddress); - if (row_pos == last_row) { - return found_seq.LastRowIndex - 1; - } - uint32_t index = found_seq.FirstRowIndex + (row_pos - first_row); - if (row_pos->Address > address) { - if (row_pos == first_row) - return unknown_index; - else - index--; - } - return index; -} - -bool DWARFDebugLine::LineTable::lookupAddressRange( - uint64_t address, uint64_t size, std::vector &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) { - DWARFDebugLine::Sequence cur_seq = *seq_pos; - uint32_t first_row_index; - uint32_t last_row_index; - if (seq_pos == start_pos) { - // For the first sequence, we need to find which row in the sequence is the - // first in our range. 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() + cur_seq.FirstRowIndex; - RowIter last_row = Rows.begin() + cur_seq.LastRowIndex; - RowIter row_pos = std::upper_bound(first_row, last_row, row, - DWARFDebugLine::Row::orderByAddress); - // The 'row_pos' iterator references the first row that is greater than - // our start address. Unless that's the first row, we want to start at - // the row before that. - first_row_index = cur_seq.FirstRowIndex + (row_pos - first_row); - if (row_pos != first_row) - --first_row_index; - } else - first_row_index = cur_seq.FirstRowIndex; - - // For the last sequence in our range, we need to figure out the last row in - // range. For all other sequences we can go to the end of the sequence. - if (cur_seq.HighPC > end_addr) { - DWARFDebugLine::Row row; - row.Address = end_addr; - RowIter first_row = Rows.begin() + cur_seq.FirstRowIndex; - RowIter last_row = Rows.begin() + cur_seq.LastRowIndex; - RowIter row_pos = std::upper_bound(first_row, last_row, row, - DWARFDebugLine::Row::orderByAddress); - // The 'row_pos' iterator references the first row that is greater than - // our end address. The row before that is the last row we want. - last_row_index = cur_seq.FirstRowIndex + (row_pos - first_row) - 1; - } else - // Contrary to what you might expect, DWARFDebugLine::SequenceLastRowIndex - // isn't a valid index within the current sequence. It's that plus one. - last_row_index = cur_seq.LastRowIndex - 1; - - 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/lib/DebugInfo/DWARFDebugLine.h b/lib/DebugInfo/DWARFDebugLine.h deleted file mode 100644 index 7a6f1bd..0000000 --- a/lib/DebugInfo/DWARFDebugLine.h +++ /dev/null @@ -1,238 +0,0 @@ -//===-- DWARFDebugLine.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_DWARFDEBUGLINE_H -#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLINE_H - -#include "DWARFRelocMap.h" -#include "llvm/DebugInfo/DIContext.h" -#include "llvm/Support/DataExtractor.h" -#include -#include -#include - -namespace llvm { - -class raw_ostream; - -class DWARFDebugLine { -public: - DWARFDebugLine(const RelocAddrMap* LineInfoRelocMap) : RelocMap(LineInfoRelocMap) {} - struct FileNameEntry { - FileNameEntry() : Name(nullptr), DirIdx(0), ModTime(0), Length(0) {} - - const char *Name; - uint64_t DirIdx; - uint64_t ModTime; - uint64_t Length; - }; - - struct Prologue { - Prologue(); - - // The size in bytes of the statement information for this compilation unit - // (not including the total_length field itself). - uint32_t TotalLength; - // Version identifier for the statement information format. - uint16_t Version; - // The number of bytes following the prologue_length field to the beginning - // of the first byte of the statement program itself. - uint32_t PrologueLength; - // The size in bytes of the smallest target machine instruction. Statement - // program opcodes that alter the address register first multiply their - // operands by this value. - uint8_t MinInstLength; - // The maximum number of individual operations that may be encoded in an - // instruction. - uint8_t MaxOpsPerInst; - // The initial value of theis_stmtregister. - uint8_t DefaultIsStmt; - // This parameter affects the meaning of the special opcodes. See below. - int8_t LineBase; - // This parameter affects the meaning of the special opcodes. See below. - uint8_t LineRange; - // The number assigned to the first special opcode. - uint8_t OpcodeBase; - std::vector StandardOpcodeLengths; - std::vector IncludeDirectories; - std::vector FileNames; - - // Length of the prologue in bytes. - uint32_t getLength() const { - return PrologueLength + sizeof(TotalLength) + sizeof(Version) + - sizeof(PrologueLength); - } - // Length of the line table data in bytes (not including the prologue). - uint32_t getStatementTableLength() const { - return TotalLength + sizeof(TotalLength) - getLength(); - } - int32_t getMaxLineIncrementForSpecialOpcode() const { - return LineBase + (int8_t)LineRange - 1; - } - - void clear(); - void dump(raw_ostream &OS) const; - bool parse(DataExtractor debug_line_data, uint32_t *offset_ptr); - }; - - // Standard .debug_line state machine structure. - struct Row { - explicit Row(bool default_is_stmt = false); - - /// Called after a row is appended to the matrix. - void postAppend(); - void reset(bool default_is_stmt); - void dump(raw_ostream &OS) const; - - static bool orderByAddress(const Row& LHS, const Row& RHS) { - return LHS.Address < RHS.Address; - } - - // The program-counter value corresponding to a machine instruction - // generated by the compiler. - uint64_t Address; - // An unsigned integer indicating a source line number. Lines are numbered - // beginning at 1. The compiler may emit the value 0 in cases where an - // instruction cannot be attributed to any source line. - uint32_t Line; - // An unsigned integer indicating a column number within a source line. - // Columns are numbered beginning at 1. The value 0 is reserved to indicate - // that a statement begins at the 'left edge' of the line. - uint16_t Column; - // An unsigned integer indicating the identity of the source file - // corresponding to a machine instruction. - uint16_t File; - // An unsigned integer whose value encodes the applicable instruction set - // architecture for the current instruction. - uint8_t Isa; - // An unsigned integer representing the DWARF path discriminator value - // for this location. - uint32_t Discriminator; - // A boolean indicating that the current instruction is the beginning of a - // statement. - uint8_t IsStmt:1, - // A boolean indicating that the current instruction is the - // beginning of a basic block. - BasicBlock:1, - // A boolean indicating that the current address is that of the - // first byte after the end of a sequence of target machine - // instructions. - EndSequence:1, - // A boolean indicating that the current address is one (of possibly - // many) where execution should be suspended for an entry breakpoint - // of a function. - PrologueEnd:1, - // A boolean indicating that the current address is one (of possibly - // many) where execution should be suspended for an exit breakpoint - // of a function. - EpilogueBegin:1; - }; - - // Represents a series of contiguous machine instructions. Line table for each - // compilation unit may consist of multiple sequences, which are not - // guaranteed to be in the order of ascending instruction address. - struct Sequence { - // Sequence describes instructions at address range [LowPC, HighPC) - // and is described by line table rows [FirstRowIndex, LastRowIndex). - uint64_t LowPC; - uint64_t HighPC; - unsigned FirstRowIndex; - unsigned LastRowIndex; - bool Empty; - - Sequence(); - void reset(); - - static bool orderByLowPC(const Sequence& LHS, const Sequence& RHS) { - return LHS.LowPC < RHS.LowPC; - } - bool isValid() const { - return !Empty && (LowPC < HighPC) && (FirstRowIndex < LastRowIndex); - } - bool containsPC(uint64_t pc) const { - return (LowPC <= pc && pc < HighPC); - } - }; - - struct LineTable { - LineTable(); - - void appendRow(const DWARFDebugLine::Row &R) { - Rows.push_back(R); - } - void appendSequence(const DWARFDebugLine::Sequence &S) { - Sequences.push_back(S); - } - - // Returns the index of the row with file/line info for a given address, - // or -1 if there is no such row. - uint32_t lookupAddress(uint64_t address) const; - - bool lookupAddressRange(uint64_t address, uint64_t size, - std::vector &result) const; - - // Extracts filename by its index in filename table in prologue. - // Returns true on success. - bool getFileNameByIndex(uint64_t FileIndex, const char *CompDir, - DILineInfoSpecifier::FileLineInfoKind Kind, - std::string &Result) const; - - // Fills the Result argument with the file and line information - // corresponding to Address. Returns true on success. - bool getFileLineInfoForAddress(uint64_t Address, const char *CompDir, - DILineInfoSpecifier::FileLineInfoKind Kind, - DILineInfo &Result) const; - - void dump(raw_ostream &OS) const; - void clear(); - - /// Parse prologue and all rows. - bool parse(DataExtractor debug_line_data, const RelocAddrMap *RMap, - uint32_t *offset_ptr); - - struct Prologue Prologue; - typedef std::vector RowVector; - typedef RowVector::const_iterator RowIter; - typedef std::vector SequenceVector; - typedef SequenceVector::const_iterator SequenceIter; - RowVector Rows; - SequenceVector Sequences; - }; - - const LineTable *getLineTable(uint32_t offset) const; - const LineTable *getOrParseLineTable(DataExtractor debug_line_data, - uint32_t offset); - -private: - struct ParsingState { - ParsingState(struct LineTable *LT); - - void resetRowAndSequence(); - void appendRowToMatrix(uint32_t offset); - - // Line table we're currently parsing. - struct LineTable *LineTable; - // The row number that starts at zero for the prologue, and increases for - // each row added to the matrix. - unsigned RowNumber; - struct Row Row; - struct Sequence Sequence; - }; - - typedef std::map LineTableMapTy; - typedef LineTableMapTy::iterator LineTableIter; - typedef LineTableMapTy::const_iterator LineTableConstIter; - - const RelocAddrMap *RelocMap; - LineTableMapTy LineTableMap; -}; - -} - -#endif diff --git a/lib/DebugInfo/DWARFDebugLoc.cpp b/lib/DebugInfo/DWARFDebugLoc.cpp deleted file mode 100644 index e4aa5dc..0000000 --- a/lib/DebugInfo/DWARFDebugLoc.cpp +++ /dev/null @@ -1,128 +0,0 @@ -//===-- DWARFDebugLoc.cpp -------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFDebugLoc.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Dwarf.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.reserve(str.size()); - std::copy(str.begin(), str.end(), std::back_inserter(E.Loc)); - 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( - 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/lib/DebugInfo/DWARFDebugLoc.h b/lib/DebugInfo/DWARFDebugLoc.h deleted file mode 100644 index 50110b3..0000000 --- a/lib/DebugInfo/DWARFDebugLoc.h +++ /dev/null @@ -1,81 +0,0 @@ -//===-- DWARFDebugLoc.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_DWARFDEBUGLOC_H -#define LLVM_LIB_DEBUGINFO_DWARFDEBUGLOC_H - -#include "DWARFRelocMap.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/Support/DataExtractor.h" - -namespace llvm { - -class raw_ostream; - -class DWARFDebugLoc { - /// A single location within a location list. - struct Entry { - /// The beginning address of the instruction range. - uint64_t Begin; - /// The ending address of the instruction range. - uint64_t End; - /// The location of the variable within the specified range. - SmallVector Loc; - }; - - /// A list of locations that contain one variable. - struct LocationList { - /// The beginning offset where this location list is stored in the debug_loc - /// section. - unsigned Offset; - /// All the locations in which the variable is stored. - SmallVector Entries; - }; - - typedef SmallVector LocationLists; - - /// A list of all the variables in the debug_loc section, each one describing - /// the locations in which the variable is stored. - LocationLists Locations; - - /// A map used to resolve binary relocations. - const RelocAddrMap &RelocMap; - -public: - DWARFDebugLoc(const RelocAddrMap &LocRelocMap) : RelocMap(LocRelocMap) {} - /// Print the location lists found within the debug_loc section. - void dump(raw_ostream &OS) const; - /// Parse the debug_loc section accessible via the 'data' parameter using the - /// specified address size to interpret the address ranges. - void parse(DataExtractor data, unsigned AddressSize); -}; - -class DWARFDebugLocDWO { - struct Entry { - uint64_t Start; - uint32_t Length; - SmallVector Loc; - }; - - struct LocationList { - unsigned Offset; - SmallVector Entries; - }; - - typedef SmallVector LocationLists; - - LocationLists Locations; - -public: - void parse(DataExtractor data); - void dump(raw_ostream &OS) const; -}; -} - -#endif diff --git a/lib/DebugInfo/DWARFDebugRangeList.cpp b/lib/DebugInfo/DWARFDebugRangeList.cpp deleted file mode 100644 index 07b23b3..0000000 --- a/lib/DebugInfo/DWARFDebugRangeList.cpp +++ /dev/null @@ -1,69 +0,0 @@ -//===-- DWARFDebugRangesList.cpp ------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "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 \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/lib/DebugInfo/DWARFDebugRangeList.h b/lib/DebugInfo/DWARFDebugRangeList.h deleted file mode 100644 index 4ee3bda..0000000 --- a/lib/DebugInfo/DWARFDebugRangeList.h +++ /dev/null @@ -1,77 +0,0 @@ -//===-- DWARFDebugRangeList.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_DWARFDEBUGRANGELIST_H -#define LLVM_LIB_DEBUGINFO_DWARFDEBUGRANGELIST_H - -#include "llvm/Support/DataExtractor.h" -#include - -namespace llvm { - -class raw_ostream; - -/// DWARFAddressRangesVector - represents a set of absolute address ranges. -typedef std::vector> DWARFAddressRangesVector; - -class DWARFDebugRangeList { -public: - struct RangeListEntry { - // A beginning address offset. This address offset has the size of an - // address and is relative to the applicable base address of the - // compilation unit referencing this range list. It marks the beginning - // of an address range. - uint64_t StartAddress; - // An ending address offset. This address offset again has the size of - // an address and is relative to the applicable base address of the - // compilation unit referencing this range list. It marks the first - // address past the end of the address range. The ending address must - // be greater than or equal to the beginning address. - uint64_t EndAddress; - // The end of any given range 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. - bool isEndOfListEntry() const { - return (StartAddress == 0) && (EndAddress == 0); - } - // A base address selection entry consists of: - // 1. The value of the largest representable address offset - // (for example, 0xffffffff when the size of an address is 32 bits). - // 2. An address, which defines the appropriate base address for - // use in interpreting the beginning and ending address offsets of - // subsequent entries of the location list. - bool isBaseAddressSelectionEntry(uint8_t AddressSize) const { - assert(AddressSize == 4 || AddressSize == 8); - if (AddressSize == 4) - return StartAddress == -1U; - else - return StartAddress == -1ULL; - } - }; - -private: - // Offset in .debug_ranges section. - uint32_t Offset; - uint8_t AddressSize; - std::vector Entries; - -public: - DWARFDebugRangeList() { clear(); } - void clear(); - void dump(raw_ostream &OS) const; - bool extract(DataExtractor data, uint32_t *offset_ptr); - /// getAbsoluteRanges - Returns absolute address ranges defined by this range - /// list. Has to be passed base address of the compile unit referencing this - /// range list. - DWARFAddressRangesVector getAbsoluteRanges(uint64_t BaseAddress) const; -}; - -} // namespace llvm - -#endif // LLVM_DEBUGINFO_DWARFDEBUGRANGELIST_H diff --git a/lib/DebugInfo/DWARFFormValue.cpp b/lib/DebugInfo/DWARFFormValue.cpp deleted file mode 100644 index 69b9771..0000000 --- a/lib/DebugInfo/DWARFFormValue.cpp +++ /dev/null @@ -1,557 +0,0 @@ -//===-- DWARFFormValue.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/DWARFFormValue.h" -#include "DWARFCompileUnit.h" -#include "DWARFContext.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/Format.h" -#include "llvm/Support/raw_ostream.h" -#include -using namespace llvm; -using namespace dwarf; - -namespace { -uint8_t getRefAddrSize(uint8_t AddrSize, uint16_t Version) { - // FIXME: Support DWARF64. - return (Version == 2) ? AddrSize : 4; -} - -template -ArrayRef 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 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 < ArrayRef(DWARF4FormClasses).size() && - DWARF4FormClasses[Form] == FC) - return true; - // Check DW_FORM_ref_sig8 from DWARF4. - if (Form == DW_FORM_ref_sig8) - return (FC == FC_Reference); - // Check for some DWARF5 forms. - if (Form == DW_FORM_GNU_addr_index) - return (FC == FC_Address); - if (Form == DW_FORM_GNU_str_index) - 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. - if ((Form == DW_FORM_data4 || Form == DW_FORM_data8) && - FC == FC_SectionOffset) - return true; - return false; -} - -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 &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_strp: { - 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_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: { - // 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(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) { - 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 += cu->getAddressByteSize(); - return true; - case DW_FORM_ref_addr: - *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion()); - 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_strp: - 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: - *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 << ""; - 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); - Optional DbgStr = getAsCString(cu); - if (DbgStr.hasValue()) { - OS << '"'; - OS.write_escaped(DbgStr.getValue()); - OS << '"'; - } - break; - } - case DW_FORM_GNU_str_index: { - OS << format(" indexed (%8.8x) string = ", (uint32_t)uvalue); - Optional DbgStr = getAsCString(cu); - if (DbgStr.hasValue()) { - OS << '"'; - OS.write_escaped(DbgStr.getValue()); - OS << '"'; - } - 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; - - // 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 << format(" => {0x%8.8" PRIx64 "}", uvalue + (cu ? cu->getOffset() : 0)); -} - -Optional DWARFFormValue::getAsCString(const DWARFUnit *U) const { - if (!isFormClass(FC_String)) - return None; - if (Form == DW_FORM_string) - return Value.cstr; - if (!U) - 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 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 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 - default: - return Value.uval; - } -} - -Optional DWARFFormValue::getAsSectionOffset() const { - if (!isFormClass(FC_SectionOffset)) - return None; - return Value.uval; -} - -Optional DWARFFormValue::getAsUnsignedConstant() const { - if ((!isFormClass(FC_Constant) && !isFormClass(FC_Flag)) - || Form == DW_FORM_sdata) - return None; - return Value.uval; -} - -Optional> DWARFFormValue::getAsBlock() const { - if (!isFormClass(FC_Block) && !isFormClass(FC_Exprloc)) - return None; - return ArrayRef(Value.data, Value.uval); -} - diff --git a/lib/DebugInfo/DWARFRelocMap.h b/lib/DebugInfo/DWARFRelocMap.h deleted file mode 100644 index d7fe303..0000000 --- a/lib/DebugInfo/DWARFRelocMap.h +++ /dev/null @@ -1,22 +0,0 @@ -//===-- DWARFRelocMap.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_DWARFRELOCMAP_H -#define LLVM_LIB_DEBUGINFO_DWARFRELOCMAP_H - -#include "llvm/ADT/DenseMap.h" - -namespace llvm { - -typedef DenseMap > RelocAddrMap; - -} // namespace llvm - -#endif - diff --git a/lib/DebugInfo/DWARFSection.h b/lib/DebugInfo/DWARFSection.h deleted file mode 100644 index 3aaf0ff..0000000 --- a/lib/DebugInfo/DWARFSection.h +++ /dev/null @@ -1,24 +0,0 @@ -//===-- DWARFSection.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_DWARFSECTION_H -#define LLVM_LIB_DEBUGINFO_DWARFSECTION_H - -#include "DWARFRelocMap.h" - -namespace llvm { - -struct DWARFSection { - StringRef Data; - RelocAddrMap Relocs; -}; - -} - -#endif diff --git a/lib/DebugInfo/DWARFTypeUnit.cpp b/lib/DebugInfo/DWARFTypeUnit.cpp deleted file mode 100644 index 303bf70..0000000 --- a/lib/DebugInfo/DWARFTypeUnit.cpp +++ /dev/null @@ -1,39 +0,0 @@ -//===-- DWARFTypeUnit.cpp -------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "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"; - - const DWARFDebugInfoEntryMinimal *CU = getCompileUnitDIE(false); - assert(CU && "Null Compile Unit?"); - CU->dump(OS, this, -1U); -} diff --git a/lib/DebugInfo/DWARFTypeUnit.h b/lib/DebugInfo/DWARFTypeUnit.h deleted file mode 100644 index 7471b5a..0000000 --- a/lib/DebugInfo/DWARFTypeUnit.h +++ /dev/null @@ -1,38 +0,0 @@ -//===-- DWARFTypeUnit.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_DWARFTYPEUNIT_H -#define LLVM_LIB_DEBUGINFO_DWARFTYPEUNIT_H - -#include "DWARFUnit.h" - -namespace llvm { - -class DWARFTypeUnit : public DWARFUnit { -private: - uint64_t TypeHash; - uint32_t TypeOffset; -public: - DWARFTypeUnit(DWARFContext &Context, const DWARFSection &Section, - const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, - StringRef SOS, StringRef AOS, bool LE, - const DWARFUnitSectionBase &UnitSection) - : DWARFUnit(Context, Section, DA, RS, SS, SOS, AOS, LE, UnitSection) {} - uint32_t getHeaderSize() const override { - return DWARFUnit::getHeaderSize() + 12; - } - void dump(raw_ostream &OS); -protected: - bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) override; -}; - -} - -#endif - diff --git a/lib/DebugInfo/DWARFUnit.cpp b/lib/DebugInfo/DWARFUnit.cpp deleted file mode 100644 index 82c4529..0000000 --- a/lib/DebugInfo/DWARFUnit.cpp +++ /dev/null @@ -1,377 +0,0 @@ -//===-- DWARFUnit.cpp -----------------------------------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "DWARFUnit.h" -#include "DWARFContext.h" -#include "llvm/DebugInfo/DWARFFormValue.h" -#include "llvm/Support/Dwarf.h" -#include "llvm/Support/Path.h" -#include - -using 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.isLittleEndian()); -} - -void DWARFUnitSectionBase::parseDWO(DWARFContext &C, - const DWARFSection &DWOSection) { - parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(), - C.getStringDWOSection(), C.getStringOffsetDWOSection(), - C.getAddrSection(), C.isLittleEndian()); -} - -DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, - const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, - StringRef SOS, StringRef AOS, bool LE, - const DWARFUnitSectionBase &UnitSection) - : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS), - StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), - isLittleEndian(LE), UnitSection(UnitSection) { - 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); - 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); - if (Abbrevs == nullptr) - return false; - - return true; -} - -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 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 &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(DIContext::getDWARFContext(*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(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 TmpArray; - DieArray.swap(TmpArray); - // Save at least the compile unit DIE - if (KeepCUDie) - DieArray.push_back(TmpArray.front()); - } -} - -void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { - // First, check if CU DIE describes address ranges for the unit. - const auto &CUDIERanges = getCompileUnitDIE()->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); -} diff --git a/lib/DebugInfo/DWARFUnit.h b/lib/DebugInfo/DWARFUnit.h deleted file mode 100644 index 786f00f..0000000 --- a/lib/DebugInfo/DWARFUnit.h +++ /dev/null @@ -1,245 +0,0 @@ -//===-- DWARFUnit.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_DWARFUNIT_H -#define LLVM_LIB_DEBUGINFO_DWARFUNIT_H - -#include "DWARFDebugAbbrev.h" -#include "DWARFDebugInfoEntry.h" -#include "DWARFDebugRangeList.h" -#include "DWARFRelocMap.h" -#include "DWARFSection.h" -#include - -namespace llvm { - -namespace object { -class ObjectFile; -} - -class DWARFContext; -class DWARFDebugAbbrev; -class DWARFUnit; -class StringRef; -class raw_ostream; - -/// Base class for all DWARFUnitSection classes. This provides the -/// functionality common to all unit types. -class DWARFUnitSectionBase { -public: - /// Returns the Unit that contains the given section offset in the - /// same section this Unit originated from. - virtual DWARFUnit *getUnitForOffset(uint32_t Offset) const = 0; - - void parse(DWARFContext &C, const DWARFSection &Section); - void parseDWO(DWARFContext &C, const DWARFSection &DWOSection); - -protected: - virtual void parseImpl(DWARFContext &Context, const DWARFSection &Section, - const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, - StringRef SOS, StringRef AOS, bool isLittleEndian) = 0; - - ~DWARFUnitSectionBase() {} -}; - -/// Concrete instance of DWARFUnitSection, specialized for one Unit type. -template -class DWARFUnitSection final : public SmallVector, 1>, - public DWARFUnitSectionBase { - - struct UnitOffsetComparator { - bool operator()(uint32_t LHS, - const std::unique_ptr &RHS) const { - return LHS < RHS->getNextUnitOffset(); - } - }; - - bool Parsed; - -public: - DWARFUnitSection() : Parsed(false) {} - DWARFUnitSection(DWARFUnitSection &&DUS) : - SmallVector, 1>(std::move(DUS)), Parsed(DUS.Parsed) {} - - typedef llvm::SmallVectorImpl> UnitVector; - typedef typename UnitVector::iterator iterator; - typedef llvm::iterator_range iterator_range; - - UnitType *getUnitForOffset(uint32_t Offset) const override { - auto *CU = std::upper_bound(this->begin(), this->end(), Offset, - UnitOffsetComparator()); - if (CU != this->end()) - return CU->get(); - return nullptr; - } - -private: - void parseImpl(DWARFContext &Context, const DWARFSection &Section, - const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, - StringRef SOS, StringRef AOS, bool LE) override { - if (Parsed) - return; - DataExtractor Data(Section.Data, LE, 0); - uint32_t Offset = 0; - while (Data.isValidOffset(Offset)) { - auto U = llvm::make_unique(Context, Section, DA, RS, SS, SOS, - AOS, LE, *this); - if (!U->extract(Data, &Offset)) - break; - this->push_back(std::move(U)); - Offset = this->back()->getNextUnitOffset(); - } - Parsed = true; - } -}; - -class DWARFUnit { - DWARFContext &Context; - // Section containing this DWARFUnit. - const DWARFSection &InfoSection; - - const DWARFDebugAbbrev *Abbrev; - StringRef RangeSection; - uint32_t RangeSectionBase; - StringRef StringSection; - StringRef StringOffsetSection; - StringRef AddrOffsetSection; - uint32_t AddrOffsetSectionBase; - bool isLittleEndian; - const DWARFUnitSectionBase &UnitSection; - - uint32_t Offset; - uint32_t Length; - uint16_t Version; - const DWARFAbbreviationDeclarationSet *Abbrevs; - uint8_t AddrSize; - uint64_t BaseAddr; - // The compile unit debug information entry items. - std::vector DieArray; - - class DWOHolder { - object::OwningBinary DWOFile; - std::unique_ptr DWOContext; - DWARFUnit *DWOU; - public: - DWOHolder(StringRef DWOPath); - DWARFUnit *getUnit() const { return DWOU; } - }; - std::unique_ptr DWO; - -protected: - virtual bool extractImpl(DataExtractor debug_info, uint32_t *offset_ptr); - /// Size in bytes of the unit header. - virtual uint32_t getHeaderSize() const { return 11; } - -public: - DWARFUnit(DWARFContext &Context, const DWARFSection &Section, - const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, - StringRef SOS, StringRef AOS, bool LE, - const DWARFUnitSectionBase &UnitSection); - - virtual ~DWARFUnit(); - - DWARFContext& getContext() const { return Context; } - - StringRef getStringSection() const { return StringSection; } - StringRef getStringOffsetSection() const { return StringOffsetSection; } - void setAddrOffsetSection(StringRef AOS, uint32_t Base) { - AddrOffsetSection = AOS; - AddrOffsetSectionBase = Base; - } - void setRangesSection(StringRef RS, uint32_t Base) { - RangeSection = RS; - RangeSectionBase = Base; - } - - bool getAddrOffsetSectionItem(uint32_t Index, uint64_t &Result) const; - // FIXME: Result should be uint64_t in DWARF64. - bool getStringOffsetSectionItem(uint32_t Index, uint32_t &Result) const; - - DataExtractor getDebugInfoExtractor() const { - return DataExtractor(InfoSection.Data, isLittleEndian, AddrSize); - } - DataExtractor getStringExtractor() const { - return DataExtractor(StringSection, false, 0); - } - - const RelocAddrMap *getRelocMap() const { return &InfoSection.Relocs; } - - bool extract(DataExtractor debug_info, uint32_t* offset_ptr); - - /// extractRangeList - extracts the range list referenced by this compile - /// unit from .debug_ranges section. Returns true on success. - /// Requires that compile unit is already extracted. - bool extractRangeList(uint32_t RangeListOffset, - DWARFDebugRangeList &RangeList) const; - void clear(); - uint32_t getOffset() const { return Offset; } - uint32_t getNextUnitOffset() const { return Offset + Length + 4; } - uint32_t getLength() const { return Length; } - uint16_t getVersion() const { return Version; } - const DWARFAbbreviationDeclarationSet *getAbbreviations() const { - return Abbrevs; - } - uint8_t getAddressByteSize() const { return AddrSize; } - uint64_t getBaseAddress() const { return BaseAddr; } - - void setBaseAddress(uint64_t base_addr) { - BaseAddr = base_addr; - } - - const DWARFDebugInfoEntryMinimal * - getCompileUnitDIE(bool extract_cu_die_only = true) { - extractDIEsIfNeeded(extract_cu_die_only); - return DieArray.empty() ? nullptr : &DieArray[0]; - } - - const char *getCompilationDir(); - uint64_t getDWOId(); - - void collectAddressRanges(DWARFAddressRangesVector &CURanges); - - /// getInlinedChainForAddress - fetches inlined chain for a given address. - /// Returns empty chain if there is no subprogram containing address. The - /// chain is valid as long as parsed compile unit DIEs are not cleared. - DWARFDebugInfoEntryInlinedChain getInlinedChainForAddress(uint64_t Address); - - /// getUnitSection - Return the DWARFUnitSection containing this unit. - const DWARFUnitSectionBase &getUnitSection() const { return UnitSection; } - -private: - /// Size in bytes of the .debug_info data associated with this compile unit. - size_t getDebugInfoSize() const { return Length + 4 - getHeaderSize(); } - - /// extractDIEsIfNeeded - Parses a compile unit and indexes its DIEs if it - /// hasn't already been done. Returns the number of DIEs parsed at this call. - size_t extractDIEsIfNeeded(bool CUDieOnly); - /// extractDIEsToVector - Appends all parsed DIEs to a vector. - void extractDIEsToVector(bool AppendCUDie, bool AppendNonCUDIEs, - std::vector &DIEs) const; - /// setDIERelations - We read in all of the DIE entries into our flat list - /// of DIE entries and now we need to go back through all of them and set the - /// parent, sibling and child pointers for quick DIE navigation. - void setDIERelations(); - /// clearDIEs - Clear parsed DIEs to keep memory usage low. - void clearDIEs(bool KeepCUDie); - - /// parseDWO - Parses .dwo file for current compile unit. Returns true if - /// it was actually constructed. - bool parseDWO(); - - /// getSubprogramForAddress - Returns subprogram DIE with address range - /// encompassing the provided address. The pointer is alive as long as parsed - /// compile unit DIEs are not cleared. - const DWARFDebugInfoEntryMinimal *getSubprogramForAddress(uint64_t Address); -}; - -} - -#endif diff --git a/lib/DebugInfo/LLVMBuild.txt b/lib/DebugInfo/LLVMBuild.txt index f347d5e..7a8e8ba 100644 --- a/lib/DebugInfo/LLVMBuild.txt +++ b/lib/DebugInfo/LLVMBuild.txt @@ -15,8 +15,10 @@ ; ;===------------------------------------------------------------------------===; +[common] +subdirectories = DWARF PDB + [component_0] -type = Library +type = Group name = DebugInfo -parent = Libraries -required_libraries = Object Support +parent = $ROOT diff --git a/lib/DebugInfo/Makefile b/lib/DebugInfo/Makefile index 1292b57..27a5e1f 100644 --- a/lib/DebugInfo/Makefile +++ b/lib/DebugInfo/Makefile @@ -6,9 +6,10 @@ # License. See LICENSE.TXT for details. # ##===----------------------------------------------------------------------===## - LEVEL = ../.. -LIBRARYNAME = LLVMDebugInfo -BUILD_ARCHIVE := 1 -include $(LEVEL)/Makefile.common +include $(LEVEL)/Makefile.config + +PARALLEL_DIRS := DWARF PDB + +include $(LEVEL)/Makefile.common \ No newline at end of file diff --git a/lib/DebugInfo/PDB/Android.mk b/lib/DebugInfo/PDB/Android.mk new file mode 100644 index 0000000..c8d4fd1 --- /dev/null +++ b/lib/DebugInfo/PDB/Android.mk @@ -0,0 +1,75 @@ +LOCAL_PATH:= $(call my-dir) + +# No dia support +debuginfo_pdb_SRC_FILES := \ + IPDBSourceFile.cpp \ + PDB.cpp \ + PDBExtras.cpp \ + PDBInterfaceAnchors.cpp \ + PDBSymbolAnnotation.cpp \ + PDBSymbolBlock.cpp \ + PDBSymbolCompiland.cpp \ + PDBSymbolCompilandDetails.cpp \ + PDBSymbolCompilandEnv.cpp \ + PDBSymbol.cpp \ + PDBSymbolCustom.cpp \ + PDBSymbolData.cpp \ + PDBSymbolExe.cpp \ + PDBSymbolFunc.cpp \ + PDBSymbolFuncDebugEnd.cpp \ + PDBSymbolFuncDebugStart.cpp \ + PDBSymbolLabel.cpp \ + PDBSymbolPublicSymbol.cpp \ + PDBSymbolThunk.cpp \ + PDBSymbolTypeArray.cpp \ + PDBSymbolTypeBaseClass.cpp \ + PDBSymbolTypeBuiltin.cpp \ + PDBSymbolTypeCustom.cpp \ + PDBSymbolTypeDimension.cpp \ + PDBSymbolTypeEnum.cpp \ + PDBSymbolTypeFriend.cpp \ + PDBSymbolTypeFunctionArg.cpp \ + PDBSymbolTypeFunctionSig.cpp \ + PDBSymbolTypeManaged.cpp \ + PDBSymbolTypePointer.cpp \ + PDBSymbolTypeTypedef.cpp \ + PDBSymbolTypeUDT.cpp \ + PDBSymbolTypeVTable.cpp \ + PDBSymbolTypeVTableShape.cpp \ + PDBSymbolUnknown.cpp \ + PDBSymbolUsingNamespace.cpp \ + PDBSymDumper.cpp + +# For the host +# ===================================================== +include $(CLEAR_VARS) + +REQUIRES_RTTI := 1 + +LOCAL_SRC_FILES := $(debuginfo_pdb_SRC_FILES) + +LOCAL_MODULE:= libLLVMDebugInfoPDB + +LOCAL_MODULE_TAGS := optional + +include $(LLVM_HOST_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_HOST_STATIC_LIBRARY) + +# For the device +# ===================================================== +ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS)) +include $(CLEAR_VARS) + +REQUIRES_RTTI := 1 + +LOCAL_SRC_FILES := $(debuginfo_pdb_SRC_FILES) + +LOCAL_MODULE:= libLLVMDebugInfoPDB + +LOCAL_MODULE_TAGS := optional + +include $(LLVM_DEVICE_BUILD_MK) +include $(LLVM_GEN_INTRINSICS_MK) +include $(BUILD_STATIC_LIBRARY) +endif diff --git a/lib/DebugInfo/PDB/CMakeLists.txt b/lib/DebugInfo/PDB/CMakeLists.txt new file mode 100644 index 0000000..87e357e --- /dev/null +++ b/lib/DebugInfo/PDB/CMakeLists.txt @@ -0,0 +1,76 @@ +macro(add_pdb_impl_folder group) + list(APPEND PDB_IMPL_SOURCES ${ARGN}) + source_group(${group} FILES ${ARGN}) +endmacro() + +if(HAVE_DIA_SDK) + include_directories(${MSVC_DIA_SDK_DIR}/include) + set(LIBPDB_LINK_FOLDERS "${MSVC_DIA_SDK_DIR}\\lib") + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set(LIBPDB_LINK_FOLDERS "${LIBPDB_LINK_FOLDERS}\\amd64") + endif() + set(LIBPDB_ADDITIONAL_LIBRARIES "${LIBPDB_LINK_FOLDERS}\\diaguids.lib") + + add_pdb_impl_folder(DIA + DIA/DIADataStream.cpp + DIA/DIAEnumDebugStreams.cpp + DIA/DIAEnumLineNumbers.cpp + DIA/DIAEnumSourceFiles.cpp + DIA/DIAEnumSymbols.cpp + DIA/DIALineNumber.cpp + DIA/DIARawSymbol.cpp + DIA/DIASession.cpp + DIA/DIASourceFile.cpp + ) + + set(LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB/DIA") + +endif() + +list(APPEND LIBPDB_ADDITIONAL_HEADER_DIRS "${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/PDB") + +add_llvm_library(LLVMDebugInfoPDB + IPDBSourceFile.cpp + PDB.cpp + PDBExtras.cpp + PDBInterfaceAnchors.cpp + PDBSymbol.cpp + PDBSymbolAnnotation.cpp + PDBSymbolBlock.cpp + PDBSymbolCompiland.cpp + PDBSymbolCompilandDetails.cpp + PDBSymbolCompilandEnv.cpp + PDBSymbolCustom.cpp + PDBSymbolData.cpp + PDBSymbolExe.cpp + PDBSymbolFunc.cpp + PDBSymbolFuncDebugEnd.cpp + PDBSymbolFuncDebugStart.cpp + PDBSymbolLabel.cpp + PDBSymbolPublicSymbol.cpp + PDBSymbolThunk.cpp + PDBSymbolTypeArray.cpp + PDBSymbolTypeBaseClass.cpp + PDBSymbolTypeBuiltin.cpp + PDBSymbolTypeCustom.cpp + PDBSymbolTypeDimension.cpp + PDBSymbolTypeEnum.cpp + PDBSymbolTypeFriend.cpp + PDBSymbolTypeFunctionArg.cpp + PDBSymbolTypeFunctionSig.cpp + PDBSymbolTypeManaged.cpp + PDBSymbolTypePointer.cpp + PDBSymbolTypeTypedef.cpp + PDBSymbolTypeUDT.cpp + PDBSymbolTypeVTable.cpp + PDBSymbolTypeVTableShape.cpp + PDBSymbolUnknown.cpp + PDBSymbolUsingNamespace.cpp + PDBSymDumper.cpp + ${PDB_IMPL_SOURCES} + + ADDITIONAL_HEADER_DIRS + ${LIBPDB_ADDITIONAL_HEADER_DIRS} + ) + +target_link_libraries(LLVMDebugInfoPDB ${cmake_2_8_12_INTERFACE} "${LIBPDB_ADDITIONAL_LIBRARIES}") diff --git a/lib/DebugInfo/PDB/DIA/DIADataStream.cpp b/lib/DebugInfo/PDB/DIA/DIADataStream.cpp new file mode 100644 index 0000000..e0e1b27 --- /dev/null +++ b/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 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 Name16Bytes(reinterpret_cast(Name16.m_str), + Name16.ByteLength()); + if (!llvm::convertUTF16ToUTF8String(Name16Bytes, Name8)) + return std::string(); + return Name8; +} + +llvm::Optional +DIADataStream::getItemAtIndex(uint32_t Index) const { + RecordType Record; + DWORD RecordSize = 0; + StreamData->Item(Index, 0, &RecordSize, nullptr); + if (RecordSize == 0) + return llvm::Optional(); + + Record.resize(RecordSize); + if (S_OK != StreamData->Item(Index, RecordSize, &RecordSize, &Record[0])) + return llvm::Optional(); + 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 EnumeratorClone; + if (S_OK != StreamData->Clone(&EnumeratorClone)) + return nullptr; + + return new DIADataStream(EnumeratorClone); +} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumDebugStreams.cpp new file mode 100644 index 0000000..23c6489 --- /dev/null +++ b/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 DiaEnumerator) + : Enumerator(DiaEnumerator) {} + +uint32_t DIAEnumDebugStreams::getChildCount() const { + LONG Count = 0; + return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0; +} + +std::unique_ptr +DIAEnumDebugStreams::getChildAtIndex(uint32_t Index) const { + CComPtr Item; + VARIANT VarIndex; + VarIndex.vt = VT_I4; + VarIndex.lVal = Index; + if (S_OK != Enumerator->Item(VarIndex, &Item)) + return nullptr; + + return std::unique_ptr(new DIADataStream(Item)); +} + +std::unique_ptr DIAEnumDebugStreams::getNext() { + CComPtr Item; + ULONG NumFetched = 0; + if (S_OK != Enumerator->Next(1, &Item, &NumFetched)) + return nullptr; + + return std::unique_ptr(new DIADataStream(Item)); +} + +void DIAEnumDebugStreams::reset() { Enumerator->Reset(); } + +DIAEnumDebugStreams *DIAEnumDebugStreams::clone() const { + CComPtr EnumeratorClone; + if (S_OK != Enumerator->Clone(&EnumeratorClone)) + return nullptr; + return new DIAEnumDebugStreams(EnumeratorClone); +} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumLineNumbers.cpp new file mode 100644 index 0000000..32a9af2 --- /dev/null +++ b/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 DiaEnumerator) + : Enumerator(DiaEnumerator) {} + +uint32_t DIAEnumLineNumbers::getChildCount() const { + LONG Count = 0; + return (S_OK == Enumerator->get_Count(&Count)) ? Count : 0; +} + +std::unique_ptr +DIAEnumLineNumbers::getChildAtIndex(uint32_t Index) const { + CComPtr Item; + if (S_OK != Enumerator->Item(Index, &Item)) + return nullptr; + + return std::unique_ptr(new DIALineNumber(Item)); +} + +std::unique_ptr DIAEnumLineNumbers::getNext() { + CComPtr Item; + ULONG NumFetched = 0; + if (S_OK != Enumerator->Next(1, &Item, &NumFetched)) + return nullptr; + + return std::unique_ptr(new DIALineNumber(Item)); +} + +void DIAEnumLineNumbers::reset() { Enumerator->Reset(); } + +DIAEnumLineNumbers *DIAEnumLineNumbers::clone() const { + CComPtr EnumeratorClone; + if (S_OK != Enumerator->Clone(&EnumeratorClone)) + return nullptr; + return new DIAEnumLineNumbers(EnumeratorClone); +} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumSourceFiles.cpp new file mode 100644 index 0000000..1a94610 --- /dev/null +++ b/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 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 +DIAEnumSourceFiles::getChildAtIndex(uint32_t Index) const { + CComPtr Item; + if (S_OK != Enumerator->Item(Index, &Item)) + return nullptr; + + return std::unique_ptr(new DIASourceFile(Session, Item)); +} + +std::unique_ptr DIAEnumSourceFiles::getNext() { + CComPtr Item; + ULONG NumFetched = 0; + if (S_OK != Enumerator->Next(1, &Item, &NumFetched)) + return nullptr; + + return std::unique_ptr(new DIASourceFile(Session, Item)); +} + +void DIAEnumSourceFiles::reset() { Enumerator->Reset(); } + +DIAEnumSourceFiles *DIAEnumSourceFiles::clone() const { + CComPtr EnumeratorClone; + if (S_OK != Enumerator->Clone(&EnumeratorClone)) + return nullptr; + return new DIAEnumSourceFiles(Session, EnumeratorClone); +} diff --git a/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp b/lib/DebugInfo/PDB/DIA/DIAEnumSymbols.cpp new file mode 100644 index 0000000..6754d9a --- /dev/null +++ b/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 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 +DIAEnumSymbols::getChildAtIndex(uint32_t Index) const { + CComPtr Item; + if (S_OK != Enumerator->Item(Index, &Item)) + return nullptr; + + std::unique_ptr RawSymbol(new DIARawSymbol(Session, Item)); + return std::unique_ptr(PDBSymbol::create(Session, std::move(RawSymbol))); +} + +std::unique_ptr DIAEnumSymbols::getNext() { + CComPtr Item; + ULONG NumFetched = 0; + if (S_OK != Enumerator->Next(1, &Item, &NumFetched)) + return nullptr; + + std::unique_ptr RawSymbol(new DIARawSymbol(Session, Item)); + return std::unique_ptr( + PDBSymbol::create(Session, std::move(RawSymbol))); +} + +void DIAEnumSymbols::reset() { Enumerator->Reset(); } + +DIAEnumSymbols *DIAEnumSymbols::clone() const { + CComPtr EnumeratorClone; + if (S_OK != Enumerator->Clone(&EnumeratorClone)) + return nullptr; + return new DIAEnumSymbols(Session, EnumeratorClone); +} diff --git a/lib/DebugInfo/PDB/DIA/DIALineNumber.cpp b/lib/DebugInfo/PDB/DIA/DIALineNumber.cpp new file mode 100644 index 0000000..c5577f1 --- /dev/null +++ b/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 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/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp b/lib/DebugInfo/PDB/DIA/DIARawSymbol.cpp new file mode 100644 index 0000000..abe0ab5 --- /dev/null +++ b/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 +ArgType PrivateGetDIAValue(IDiaSymbol *Symbol, + HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) { + ArgType Value; + if (S_OK == (Symbol->*Method)(&Value)) + return static_cast(Value); + + return ArgType(); +} + +template +RetType PrivateGetDIAValue(IDiaSymbol *Symbol, + HRESULT (__stdcall IDiaSymbol::*Method)(ArgType *)) { + ArgType Value; + if (S_OK == (Symbol->*Method)(&Value)) + return static_cast(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(Result16.m_str); + llvm::ArrayRef 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 +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(Value); + ArrayRef 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(&Guid); + OS << *Id; + return OS; +} +} + +DIARawSymbol::DIARawSymbol(const DIASession &PDBSession, + CComPtr 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 +DIARawSymbol::findChildren(PDB_SymType Type) const { + enum SymTagEnum EnumVal = static_cast(Type); + + CComPtr DiaEnumerator; + if (S_OK != Symbol->findChildrenEx(EnumVal, nullptr, nsNone, &DiaEnumerator)) + return nullptr; + + return llvm::make_unique(Session, DiaEnumerator); +} + +std::unique_ptr +DIARawSymbol::findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const { + llvm::SmallVector Name16; + llvm::convertUTF8ToUTF16String(Name, Name16); + + enum SymTagEnum EnumVal = static_cast(Type); + DWORD CompareFlags = static_cast(Flags); + wchar_t *Name16Str = reinterpret_cast(Name16.data()); + + CComPtr DiaEnumerator; + if (S_OK != + Symbol->findChildrenEx(EnumVal, Name16Str, CompareFlags, &DiaEnumerator)) + return nullptr; + + return llvm::make_unique(Session, DiaEnumerator); +} + +std::unique_ptr +DIARawSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags, uint32_t RVA) const { + llvm::SmallVector Name16; + llvm::convertUTF8ToUTF16String(Name, Name16); + + enum SymTagEnum EnumVal = static_cast(Type); + DWORD CompareFlags = static_cast(Flags); + wchar_t *Name16Str = reinterpret_cast(Name16.data()); + + CComPtr DiaEnumerator; + if (S_OK != + Symbol->findChildrenExByRVA(EnumVal, Name16Str, CompareFlags, RVA, + &DiaEnumerator)) + return nullptr; + + return llvm::make_unique(Session, DiaEnumerator); +} + +std::unique_ptr +DIARawSymbol::findInlineFramesByRVA(uint32_t RVA) const { + CComPtr DiaEnumerator; + if (S_OK != Symbol->findInlineFramesByRVA(RVA, &DiaEnumerator)) + return nullptr; + + return llvm::make_unique(Session, DiaEnumerator); +} + +void DIARawSymbol::getDataBytes(llvm::SmallVector &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(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(Symbol, + &IDiaSymbol::get_baseType); +} + +uint32_t DIARawSymbol::getBitPosition() const { + return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_bitPosition); +} + +PDB_CallingConv DIARawSymbol::getCallingConvention() const { + return PrivateGetDIAValue( + 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(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( + 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(Symbol, &IDiaSymbol::get_platform); +} + +uint32_t DIARawSymbol::getRank() const { + return PrivateGetDIAValue(Symbol, &IDiaSymbol::get_rank); +} + +PDB_RegisterId DIARawSymbol::getRegisterId() const { + return PrivateGetDIAValue(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(Symbol, + &IDiaSymbol::get_dataKind); +} + +PDB_SymType DIARawSymbol::getSymTag() const { + return PrivateGetDIAValue(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(Symbol, + &IDiaSymbol::get_locationType); +} + +PDB_Machine DIARawSymbol::getMachineType() const { + return PrivateGetDIAValue(Symbol, + &IDiaSymbol::get_machineType); +} + +PDB_ThunkOrdinal DIARawSymbol::getThunkOrdinal() const { + return PrivateGetDIAValue( + 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(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/lib/DebugInfo/PDB/DIA/DIASession.cpp b/lib/DebugInfo/PDB/DIA/DIASession.cpp new file mode 100644 index 0000000..24791f2 --- /dev/null +++ b/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -0,0 +1,117 @@ +//===- 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/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 DiaSession) : Session(DiaSession) {} + +DIASession *DIASession::createFromPdb(StringRef Path) { + CComPtr DataSource; + CComPtr Session; + + // We assume that CoInitializeEx has already been called by the executable. + HRESULT Result = ::CoCreateInstance(CLSID_DiaSource, nullptr, + CLSCTX_INPROC_SERVER, IID_IDiaDataSource, + reinterpret_cast(&DataSource)); + if (FAILED(Result)) + return nullptr; + + llvm::SmallVector Path16; + if (!llvm::convertUTF8ToUTF16String(Path, Path16)) + return nullptr; + + const wchar_t *Path16Str = reinterpret_cast(Path16.data()); + if (FAILED(DataSource->loadDataFromPdb(Path16Str))) + return nullptr; + + if (FAILED(DataSource->openSession(&Session))) + return nullptr; + return new DIASession(Session); +} + +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 DIASession::getGlobalScope() const { + CComPtr GlobalScope; + if (S_OK != Session->get_globalScope(&GlobalScope)) + return nullptr; + + auto RawSymbol = llvm::make_unique(*this, GlobalScope); + auto PdbSymbol(PDBSymbol::create(*this, std::move(RawSymbol))); + std::unique_ptr ExeSymbol( + static_cast(PdbSymbol.release())); + return ExeSymbol; +} + +std::unique_ptr DIASession::getSymbolById(uint32_t SymbolId) const { + CComPtr LocatedSymbol; + if (S_OK != Session->symbolById(SymbolId, &LocatedSymbol)) + return nullptr; + + auto RawSymbol = llvm::make_unique(*this, LocatedSymbol); + return PDBSymbol::create(*this, std::move(RawSymbol)); +} + +std::unique_ptr DIASession::getAllSourceFiles() const { + CComPtr Files; + if (S_OK != Session->findFile(nullptr, nullptr, nsNone, &Files)) + return nullptr; + + return llvm::make_unique(*this, Files); +} + +std::unique_ptr DIASession::getSourceFilesForCompiland( + const PDBSymbolCompiland &Compiland) const { + CComPtr Files; + + const DIARawSymbol &RawSymbol = + static_cast(Compiland.getRawSymbol()); + if (S_OK != + Session->findFile(RawSymbol.getDiaSymbol(), nullptr, nsNone, &Files)) + return nullptr; + + return llvm::make_unique(*this, Files); +} + +std::unique_ptr +DIASession::getSourceFileById(uint32_t FileId) const { + CComPtr LocatedFile; + if (S_OK != Session->findFileById(FileId, &LocatedFile)) + return nullptr; + + return llvm::make_unique(*this, LocatedFile); +} + +std::unique_ptr DIASession::getDebugStreams() const { + CComPtr DiaEnumerator; + if (S_OK != Session->getEnumDebugStreams(&DiaEnumerator)) + return nullptr; + + return llvm::make_unique(DiaEnumerator); +} diff --git a/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp b/lib/DebugInfo/PDB/DIA/DIASourceFile.cpp new file mode 100644 index 0000000..0a9c444 --- /dev/null +++ b/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 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 FileNameBytes(reinterpret_cast(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 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(Type); +} + +std::unique_ptr DIASourceFile::getCompilands() const { + CComPtr DiaEnumerator; + HRESULT Result = SourceFile->get_compilands(&DiaEnumerator); + if (S_OK != Result) + return nullptr; + + return std::unique_ptr( + new DIAEnumSymbols(Session, DiaEnumerator)); +} diff --git a/lib/DebugInfo/PDB/IPDBSourceFile.cpp b/lib/DebugInfo/PDB/IPDBSourceFile.cpp new file mode 100644 index 0000000..3abe59d --- /dev/null +++ b/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/lib/DebugInfo/PDB/LLVMBuild.txt b/lib/DebugInfo/PDB/LLVMBuild.txt new file mode 100644 index 0000000..690598a --- /dev/null +++ b/lib/DebugInfo/PDB/LLVMBuild.txt @@ -0,0 +1,23 @@ +;===- ./lib/DebugInfo/PDB/LLVMBuild.txt ------------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Library +name = DebugInfoPDB +parent = DebugInfo +required_libraries = Support + diff --git a/lib/DebugInfo/PDB/Makefile b/lib/DebugInfo/PDB/Makefile new file mode 100644 index 0000000..444019e --- /dev/null +++ b/lib/DebugInfo/PDB/Makefile @@ -0,0 +1,14 @@ +##===- lib/DebugInfo/PDB/Makefile --------------------------*- Makefile -*-===## +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See LICENSE.TXT for details. +# +##===----------------------------------------------------------------------===## + +LEVEL = ../../.. +LIBRARYNAME = LLVMDebugInfoPDB +BUILD_ARCHIVE := 1 + +include $(LEVEL)/Makefile.common diff --git a/lib/DebugInfo/PDB/PDB.cpp b/lib/DebugInfo/PDB/PDB.cpp new file mode 100644 index 0000000..aa84c28 --- /dev/null +++ b/lib/DebugInfo/PDB/PDB.cpp @@ -0,0 +1,30 @@ +//===- 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; + +std::unique_ptr llvm::createPDBReader(PDB_ReaderType Type, + StringRef Path) { + // Create the correct concrete instance type based on the value of Type. +#if HAVE_DIA_SDK + return std::unique_ptr(DIASession::createFromPdb(Path)); +#endif + return nullptr; +} diff --git a/lib/DebugInfo/PDB/PDBExtras.cpp b/lib/DebugInfo/PDB/PDBExtras.cpp new file mode 100644 index 0000000..1002b2e --- /dev/null +++ b/lib/DebugInfo/PDB/PDBExtras.cpp @@ -0,0 +1,346 @@ +//===- 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(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_BuiltinType &Type) { + switch (Type) { + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Void, "void", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Char, "char", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, WCharT, "wchar_t", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Int, "int", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, UInt, "uint", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Float, "float", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, BCD, "BCD", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Bool, "bool", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Long, "long", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, ULong, "ulong", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Currency, "CURRENCY", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Date, "DATE", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Variant, "VARIANT", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Complex, "complex", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, Bitfield, "bitfield", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, BSTR, "BSTR", OS) + CASE_OUTPUT_ENUM_CLASS_STR(PDB_BuiltinType, HResult, "HRESULT", OS) + default: + break; + } + 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 GuidBytes(reinterpret_cast(&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 << 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 << Value.UInt8; + break; + default: + OS << Value.Type; + } + 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/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp b/lib/DebugInfo/PDB/PDBInterfaceAnchors.cpp new file mode 100644 index 0000000..7b6268d --- /dev/null +++ b/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/lib/DebugInfo/PDB/PDBSymDumper.cpp b/lib/DebugInfo/PDB/PDBSymDumper.cpp new file mode 100644 index 0000000..0f29c74 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymDumper.cpp @@ -0,0 +1,177 @@ +//===- 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, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolAnnotation) +} + +void PDBSymDumper::dump(const PDBSymbolBlock &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolBlock) +} + +void PDBSymDumper::dump(const PDBSymbolCompiland &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolCompiland) +} + +void PDBSymDumper::dump(const PDBSymbolCompilandDetails &Symbol, + raw_ostream &OS, int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolCompilandDetails) +} + +void PDBSymDumper::dump(const PDBSymbolCompilandEnv &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolCompilandEnv) +} + +void PDBSymDumper::dump(const PDBSymbolCustom &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolCustom) +} + +void PDBSymDumper::dump(const PDBSymbolData &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolData) +} + +void PDBSymDumper::dump(const PDBSymbolExe &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolExe) +} + +void PDBSymDumper::dump(const PDBSymbolFunc &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolFunc) +} + +void PDBSymDumper::dump(const PDBSymbolFuncDebugEnd &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolFuncDebugEnd) +} + +void PDBSymDumper::dump(const PDBSymbolFuncDebugStart &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolFuncDebugStart) +} + +void PDBSymDumper::dump(const PDBSymbolLabel &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolLabel) +} + +void PDBSymDumper::dump(const PDBSymbolPublicSymbol &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolPublicSymbol) +} + +void PDBSymDumper::dump(const PDBSymbolThunk &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolThunk) +} + +void PDBSymDumper::dump(const PDBSymbolTypeArray &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeArray) +} + +void PDBSymDumper::dump(const PDBSymbolTypeBaseClass &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeBaseClass) +} + +void PDBSymDumper::dump(const PDBSymbolTypeBuiltin &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeBuiltin) +} + +void PDBSymDumper::dump(const PDBSymbolTypeCustom &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeCustom) +} + +void PDBSymDumper::dump(const PDBSymbolTypeDimension &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeDimension) +} + +void PDBSymDumper::dump(const PDBSymbolTypeEnum &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeEnum) +} + +void PDBSymDumper::dump(const PDBSymbolTypeFriend &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeFriend) +} + +void PDBSymDumper::dump(const PDBSymbolTypeFunctionArg &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeFunctionArg) +} + +void PDBSymDumper::dump(const PDBSymbolTypeFunctionSig &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeFunctionSig) +} + +void PDBSymDumper::dump(const PDBSymbolTypeManaged &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeManaged) +} + +void PDBSymDumper::dump(const PDBSymbolTypePointer &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypePointer) +} + +void PDBSymDumper::dump(const PDBSymbolTypeTypedef &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeTypedef) +} + +void PDBSymDumper::dump(const PDBSymbolTypeUDT &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeUDT) +} + +void PDBSymDumper::dump(const PDBSymbolTypeVTable &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeVTable) +} + +void PDBSymDumper::dump(const PDBSymbolTypeVTableShape &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolTypeVTableShape) +} + +void PDBSymDumper::dump(const PDBSymbolUnknown &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolUnknown) +} + +void PDBSymDumper::dump(const PDBSymbolUsingNamespace &Symbol, raw_ostream &OS, + int Indent) { + PDB_SYMDUMP_UNREACHABLE(PDBSymbolUsingNamespace) +} diff --git a/lib/DebugInfo/PDB/PDBSymbol.cpp b/lib/DebugInfo/PDB/PDBSymbol.cpp new file mode 100644 index 0000000..f9aaf3a --- /dev/null +++ b/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 +#include + +#include +#include + +using namespace llvm; + +PDBSymbol::PDBSymbol(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : Session(PDBSession), RawSymbol(std::move(Symbol)) {} + +PDBSymbol::~PDBSymbol() {} + +#define FACTORY_SYMTAG_CASE(Tag, Type) \ + case PDB_SymType::Tag: \ + return std::unique_ptr(new Type(PDBSession, std::move(Symbol))); + +std::unique_ptr +PDBSymbol::create(const IPDBSession &PDBSession, + std::unique_ptr 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( + new PDBSymbolUnknown(PDBSession, std::move(Symbol))); + } +} + +#define TRY_DUMP_TYPE(Type) \ + if (const Type *DerivedThis = dyn_cast(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 PDBSymbol::findAllChildren() const { + return findAllChildren(PDB_SymType::None); +} + +std::unique_ptr +PDBSymbol::findAllChildren(PDB_SymType Type) const { + return RawSymbol->findChildren(Type); +} + +std::unique_ptr +PDBSymbol::findChildren(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags) const { + return RawSymbol->findChildren(Type, Name, Flags); +} + +std::unique_ptr +PDBSymbol::findChildrenByRVA(PDB_SymType Type, StringRef Name, + PDB_NameSearchFlags Flags, uint32_t RVA) const { + return RawSymbol->findChildrenByRVA(Type, Name, Flags, RVA); +} + +std::unique_ptr +PDBSymbol::findInlineFramesByRVA(uint32_t RVA) const { + return RawSymbol->findInlineFramesByRVA(RVA); +} + +std::unique_ptr +PDBSymbol::getChildStats(TagStats &Stats) const { + std::unique_ptr Result(findAllChildren()); + Stats.clear(); + while (auto Child = Result->getNext()) { + ++Stats[Child->getSymTag()]; + } + Result->reset(); + return Result; +} diff --git a/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp b/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp new file mode 100644 index 0000000..4c76e3b --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolAnnotation.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolAnnotation::PDBSymbolAnnotation(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolAnnotation::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolBlock.cpp b/lib/DebugInfo/PDB/PDBSymbolBlock.cpp new file mode 100644 index 0000000..bb159d5 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolBlock.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolBlock::PDBSymbolBlock(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolBlock::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp b/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp new file mode 100644 index 0000000..0c9b190 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolCompiland.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolCompiland::PDBSymbolCompiland(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolCompiland::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp b/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp new file mode 100644 index 0000000..208d68f --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolCompilandDetails.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolCompilandDetails::PDBSymbolCompilandDetails( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolCompilandDetails::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp b/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp new file mode 100644 index 0000000..c54b8fb --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolCompilandEnv.cpp @@ -0,0 +1,32 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolCompilandEnv::PDBSymbolCompilandEnv( + const IPDBSession &PDBSession, std::unique_ptr 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(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolCustom.cpp b/lib/DebugInfo/PDB/PDBSymbolCustom.cpp new file mode 100644 index 0000000..1b6b50b --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolCustom.cpp @@ -0,0 +1,31 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolCustom::PDBSymbolCustom(const IPDBSession &PDBSession, + std::unique_ptr CustomSymbol) + : PDBSymbol(PDBSession, std::move(CustomSymbol)) {} + +void PDBSymbolCustom::getDataBytes(llvm::SmallVector &bytes) { + RawSymbol->getDataBytes(bytes); +} + +void PDBSymbolCustom::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} \ No newline at end of file diff --git a/lib/DebugInfo/PDB/PDBSymbolData.cpp b/lib/DebugInfo/PDB/PDBSymbolData.cpp new file mode 100644 index 0000000..6bf7e0f --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolData.cpp @@ -0,0 +1,30 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolData::PDBSymbolData(const IPDBSession &PDBSession, + std::unique_ptr DataSymbol) + : PDBSymbol(PDBSession, std::move(DataSymbol)) {} + +std::unique_ptr PDBSymbolData::getType() const { + return Session.getSymbolById(getTypeId()); +} + +void PDBSymbolData::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} \ No newline at end of file diff --git a/lib/DebugInfo/PDB/PDBSymbolExe.cpp b/lib/DebugInfo/PDB/PDBSymbolExe.cpp new file mode 100644 index 0000000..ef09193 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolExe.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolExe::PDBSymbolExe(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolExe::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolFunc.cpp b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp new file mode 100644 index 0000000..e2d859f --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolFunc.cpp @@ -0,0 +1,104 @@ +//===- 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 +#include +#include + +using namespace llvm; + +namespace { +class FunctionArgEnumerator : public IPDBEnumChildren { +public: + typedef ConcreteSymbolEnumerator 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 SeenNames; + auto DataChildren = Func.findAllChildren(); + 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 { return Args.size(); } + + std::unique_ptr getChildAtIndex(uint32_t Index) const { + if (Index >= Args.size()) + return nullptr; + + return Session.getConcreteSymbolById( + Args[Index]->getSymIndexId()); + } + + std::unique_ptr getNext() { + if (CurIter == Args.end()) + return nullptr; + const auto &Result = **CurIter; + ++CurIter; + return Session.getConcreteSymbolById(Result.getSymIndexId()); + } + + void reset() { CurIter = Args.empty() ? Args.end() : Args.begin(); } + + FunctionArgEnumerator *clone() const { + return new FunctionArgEnumerator(Session, Func); + } + +private: + typedef std::vector> ArgListType; + const IPDBSession &Session; + const PDBSymbolFunc &Func; + ArgListType Args; + ArgListType::const_iterator CurIter; +}; +} + +PDBSymbolFunc::PDBSymbolFunc(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +std::unique_ptr PDBSymbolFunc::getSignature() const { + return Session.getConcreteSymbolById(getTypeId()); +} + +std::unique_ptr> +PDBSymbolFunc::getArguments() const { + return llvm::make_unique(Session, *this); +} + +std::unique_ptr PDBSymbolFunc::getClassParent() const { + return Session.getConcreteSymbolById(getClassParentId()); +} + +void PDBSymbolFunc::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp b/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp new file mode 100644 index 0000000..c207488 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolFuncDebugEnd.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolFuncDebugEnd::PDBSymbolFuncDebugEnd( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolFuncDebugEnd::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp b/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp new file mode 100644 index 0000000..83df22e --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolFuncDebugStart.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolFuncDebugStart::PDBSymbolFuncDebugStart( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolFuncDebugStart::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolLabel.cpp b/lib/DebugInfo/PDB/PDBSymbolLabel.cpp new file mode 100644 index 0000000..ce569e2 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolLabel.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolLabel::PDBSymbolLabel(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolLabel::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp b/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp new file mode 100644 index 0000000..a7f156c --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolPublicSymbol.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolPublicSymbol::PDBSymbolPublicSymbol( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolPublicSymbol::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolThunk.cpp b/lib/DebugInfo/PDB/PDBSymbolThunk.cpp new file mode 100644 index 0000000..edade83 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolThunk.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolThunk::PDBSymbolThunk(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolThunk::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp new file mode 100644 index 0000000..ffe6c80 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeArray.cpp @@ -0,0 +1,30 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeArray::PDBSymbolTypeArray(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +std::unique_ptr PDBSymbolTypeArray::getElementType() const { + return Session.getSymbolById(getTypeId()); +} + +void PDBSymbolTypeArray::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp new file mode 100644 index 0000000..c44cc52 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeBaseClass.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeBaseClass::PDBSymbolTypeBaseClass( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeBaseClass::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp new file mode 100644 index 0000000..f0c94c7 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeBuiltin::PDBSymbolTypeBuiltin( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeBuiltin::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp new file mode 100644 index 0000000..0fa8f45 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeCustom.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeCustom::PDBSymbolTypeCustom(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeCustom::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp new file mode 100644 index 0000000..47fb08d --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeDimension.cpp @@ -0,0 +1,27 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeDimension::PDBSymbolTypeDimension( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeDimension::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp new file mode 100644 index 0000000..121d41e --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeEnum.cpp @@ -0,0 +1,25 @@ +//===- 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/PDBSymDumper.h" + +#include + +using namespace llvm; + +PDBSymbolTypeEnum::PDBSymbolTypeEnum(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeEnum::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp new file mode 100644 index 0000000..b2bf72e --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFriend.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeFriend::PDBSymbolTypeFriend(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeFriend::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp new file mode 100644 index 0000000..f394c04 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionArg.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeFunctionArg::PDBSymbolTypeFunctionArg( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeFunctionArg::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp new file mode 100644 index 0000000..1ba397b --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeFunctionSig.cpp @@ -0,0 +1,89 @@ +//===- 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 + +using namespace llvm; + +namespace { +class FunctionArgEnumerator : public IPDBEnumSymbols { +public: + typedef ConcreteSymbolEnumerator ArgEnumeratorType; + + FunctionArgEnumerator(const IPDBSession &PDBSession, + const PDBSymbolTypeFunctionSig &Sig) + : Session(PDBSession), + Enumerator(Sig.findAllChildren()) {} + + FunctionArgEnumerator(const IPDBSession &PDBSession, + std::unique_ptr ArgEnumerator) + : Session(PDBSession), Enumerator(std::move(ArgEnumerator)) {} + + uint32_t getChildCount() const { return Enumerator->getChildCount(); } + + std::unique_ptr getChildAtIndex(uint32_t Index) const { + auto FunctionArgSymbol = Enumerator->getChildAtIndex(Index); + if (!FunctionArgSymbol) + return nullptr; + return Session.getSymbolById(FunctionArgSymbol->getTypeId()); + } + + std::unique_ptr getNext() { + auto FunctionArgSymbol = Enumerator->getNext(); + if (!FunctionArgSymbol) + return nullptr; + return Session.getSymbolById(FunctionArgSymbol->getTypeId()); + } + + void reset() { Enumerator->reset(); } + + MyType *clone() const { + std::unique_ptr Clone(Enumerator->clone()); + return new FunctionArgEnumerator(Session, std::move(Clone)); + } + +private: + const IPDBSession &Session; + std::unique_ptr Enumerator; +}; +} + +PDBSymbolTypeFunctionSig::PDBSymbolTypeFunctionSig( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +std::unique_ptr PDBSymbolTypeFunctionSig::getReturnType() const { + return Session.getSymbolById(getTypeId()); +} + +std::unique_ptr +PDBSymbolTypeFunctionSig::getArguments() const { + return llvm::make_unique(Session, *this); +} + +std::unique_ptr PDBSymbolTypeFunctionSig::getClassParent() const { + uint32_t ClassId = getClassParentId(); + if (ClassId == 0) + return nullptr; + return Session.getSymbolById(ClassId); +} + +void PDBSymbolTypeFunctionSig::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp new file mode 100644 index 0000000..e04fb66 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeManaged.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeManaged::PDBSymbolTypeManaged( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeManaged::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp new file mode 100644 index 0000000..d274bf5 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypePointer.cpp @@ -0,0 +1,30 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypePointer::PDBSymbolTypePointer( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +std::unique_ptr PDBSymbolTypePointer::getPointeeType() const { + return Session.getSymbolById(getTypeId()); +} + +void PDBSymbolTypePointer::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp new file mode 100644 index 0000000..12e3ead --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeTypedef.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeTypedef::PDBSymbolTypeTypedef( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeTypedef::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp new file mode 100644 index 0000000..8a72368 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeUDT.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeUDT::PDBSymbolTypeUDT(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeUDT::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp new file mode 100644 index 0000000..a100526 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeVTable.cpp @@ -0,0 +1,25 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeVTable::PDBSymbolTypeVTable(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeVTable::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp b/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp new file mode 100644 index 0000000..6aaa668 --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolTypeVTableShape.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolTypeVTableShape::PDBSymbolTypeVTableShape( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolTypeVTableShape::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp b/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp new file mode 100644 index 0000000..9cfb88a --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolUnknown.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolUnknown::PDBSymbolUnknown(const IPDBSession &PDBSession, + std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolUnknown::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp b/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp new file mode 100644 index 0000000..9176dfb --- /dev/null +++ b/lib/DebugInfo/PDB/PDBSymbolUsingNamespace.cpp @@ -0,0 +1,26 @@ +//===- 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 + +using namespace llvm; + +PDBSymbolUsingNamespace::PDBSymbolUsingNamespace( + const IPDBSession &PDBSession, std::unique_ptr Symbol) + : PDBSymbol(PDBSession, std::move(Symbol)) {} + +void PDBSymbolUsingNamespace::dump(raw_ostream &OS, int Indent, + PDBSymDumper &Dumper) const { + Dumper.dump(*this, OS, Indent); +} diff --git a/lib/DebugInfo/module.modulemap b/lib/DebugInfo/module.modulemap deleted file mode 100644 index 1fe5ab1..0000000 --- a/lib/DebugInfo/module.modulemap +++ /dev/null @@ -1 +0,0 @@ -module DebugInfo { requires cplusplus umbrella "." module * { export * } } -- cgit v1.1