Author: Sterling-Augustine Date: 2025-06-26T11:23:46-07:00 New Revision: cbf781f0bdf2f680abbe784faedeefd6f84c246e
URL: https://github.com/llvm/llvm-project/commit/cbf781f0bdf2f680abbe784faedeefd6f84c246e DIFF: https://github.com/llvm/llvm-project/commit/cbf781f0bdf2f680abbe784faedeefd6f84c246e.diff LOG: [NFC][DebugInfo][DWARF] Create new low-level dwarf library (#145081) This is the culmination of a series of changes described in [1]. Although somewhat large by line count, it is almost entirely mechanical, creating a new library in DebugInfo/DWARF/LowLevel. This new library has very minimal dependencies, allowing it to be used from more places than the normal DebugInfo/DWARF library--in particular from MC. I am happy to put it in another location, or to structure it differently if that makes sense. Some have suggested in BinaryFormat, but it is not a great fit there. But if that makes more sense to the reviewers, I can do that. Another possibility would be to use pass-through headers to allow clients who don't care to depend only on DebugInfo/DWARF. This would be a much less invasive change, and perhaps easier for clients. But also a system that hides details. Either way, I'm open. 1. https://discourse.llvm.org/t/rfc-debuginfo-dwarf-refactor-into-to-lower-and-higher-level-libraries/86665/2 Added: llvm/include/llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp llvm/lib/DebugInfo/DWARF/LowLevel/CMakeLists.txt llvm/lib/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.cpp llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp Modified: bolt/include/bolt/Core/DIEBuilder.h bolt/lib/Core/CMakeLists.txt bolt/lib/Core/DIEBuilder.cpp bolt/lib/Core/DebugNames.cpp bolt/lib/Rewrite/CMakeLists.txt bolt/lib/Rewrite/DWARFRewriter.cpp lldb/source/Expression/DWARFExpression.cpp lldb/source/Symbol/UnwindPlan.cpp lldb/unittests/Symbol/PostfixExpressionTest.cpp lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp llvm/include/llvm/DWARFLinker/AddressesMap.h llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp llvm/lib/DWARFLinker/Classic/CMakeLists.txt llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp llvm/lib/DebugInfo/DWARF/CMakeLists.txt llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp llvm/lib/DebugInfo/DWARF/DWARFDie.cpp llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp llvm/lib/ProfileData/CMakeLists.txt llvm/lib/ProfileData/InstrProfCorrelator.cpp llvm/tools/dsymutil/CMakeLists.txt llvm/tools/dsymutil/DwarfLinkerForBinary.cpp llvm/tools/llvm-dwarfdump/CMakeLists.txt llvm/tools/llvm-dwarfdump/Statistics.cpp llvm/tools/llvm-dwarfutil/CMakeLists.txt llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp llvm/tools/llvm-objdump/CMakeLists.txt llvm/tools/llvm-objdump/SourcePrinter.cpp llvm/unittests/DebugInfo/DWARF/CMakeLists.txt llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp utils/bazel/llvm-project-overlay/bolt/BUILD.bazel utils/bazel/llvm-project-overlay/llvm/BUILD.bazel Removed: llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp ################################################################################ diff --git a/bolt/include/bolt/Core/DIEBuilder.h b/bolt/include/bolt/Core/DIEBuilder.h index 32e455ad3030a..e4a4fc6b2f258 100644 --- a/bolt/include/bolt/Core/DIEBuilder.h +++ b/bolt/include/bolt/Core/DIEBuilder.h @@ -20,8 +20,8 @@ #include "llvm/CodeGen/DIE.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/Allocator.h" #include <list> diff --git a/bolt/lib/Core/CMakeLists.txt b/bolt/lib/Core/CMakeLists.txt index 8c1f5d0bb37b5..fc72dc023c590 100644 --- a/bolt/lib/Core/CMakeLists.txt +++ b/bolt/lib/Core/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS DebugInfoDWARF + DebugInfoDWARFLowLevel Demangle MC MCDisassembler diff --git a/bolt/lib/Core/DIEBuilder.cpp b/bolt/lib/Core/DIEBuilder.cpp index d36dbb3459249..b041dc5ea1cce 100644 --- a/bolt/lib/Core/DIEBuilder.cpp +++ b/bolt/lib/Core/DIEBuilder.cpp @@ -14,11 +14,11 @@ #include "llvm/CodeGen/DIE.h" #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" diff --git a/bolt/lib/Core/DebugNames.cpp b/bolt/lib/Core/DebugNames.cpp index aa1c8f3d42d4b..a9d98a6ba879b 100644 --- a/bolt/lib/Core/DebugNames.cpp +++ b/bolt/lib/Core/DebugNames.cpp @@ -8,8 +8,8 @@ #include "bolt/Core/DebugNames.h" #include "bolt/Core/BinaryContext.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/EndianStream.h" #include "llvm/Support/LEB128.h" #include <cstdint> diff --git a/bolt/lib/Rewrite/CMakeLists.txt b/bolt/lib/Rewrite/CMakeLists.txt index c83cf36982167..775036063dd5a 100644 --- a/bolt/lib/Rewrite/CMakeLists.txt +++ b/bolt/lib/Rewrite/CMakeLists.txt @@ -1,6 +1,7 @@ set(LLVM_LINK_COMPONENTS Core DebugInfoDWARF + DebugInfoDWARFLowLevel JITLink MC Object diff --git a/bolt/lib/Rewrite/DWARFRewriter.cpp b/bolt/lib/Rewrite/DWARFRewriter.cpp index 9c9bdefe08429..0c1a1bac6c72e 100644 --- a/bolt/lib/Rewrite/DWARFRewriter.cpp +++ b/bolt/lib/Rewrite/DWARFRewriter.cpp @@ -24,10 +24,10 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCObjectWriter.h" diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 661324338e801..2df27513a0b3f 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -36,7 +36,8 @@ #include "lldb/Target/StackID.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" using namespace lldb; using namespace lldb_private; @@ -81,7 +82,7 @@ void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level, llvm::DIDumpOptions DumpOpts; DumpOpts.GetNameForDWARFReg = GetRegName; llvm::DWARFExpression E(m_data.GetAsLLVM(), m_data.GetAddressByteSize()); - llvm::DWARFExpressionPrinter::print(&E, s->AsRawOstream(), DumpOpts, nullptr); + llvm::printDwarfExpression(&E, s->AsRawOstream(), DumpOpts, nullptr); } RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; } diff --git a/lldb/source/Symbol/UnwindPlan.cpp b/lldb/source/Symbol/UnwindPlan.cpp index e9ac6b6cde295..9245e52732061 100644 --- a/lldb/source/Symbol/UnwindPlan.cpp +++ b/lldb/source/Symbol/UnwindPlan.cpp @@ -17,7 +17,8 @@ #include "lldb/Utility/Log.h" #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include <optional> using namespace lldb; @@ -89,8 +90,7 @@ static void DumpDWARFExpr(Stream &s, llvm::ArrayRef<uint8_t> expr, Thread *threa order_and_width->second); llvm::DWARFExpression E(data, order_and_width->second, llvm::dwarf::DWARF32); - llvm::DWARFExpressionPrinter::print(&E, s.AsRawOstream(), - llvm::DIDumpOptions(), nullptr); + printDwarfExpression(&E, s.AsRawOstream(), llvm::DIDumpOptions(), nullptr); } else s.PutCString("dwarf-expr"); } diff --git a/lldb/unittests/Symbol/PostfixExpressionTest.cpp b/lldb/unittests/Symbol/PostfixExpressionTest.cpp index 1e437da5133d9..f60b5d2c389ed 100644 --- a/lldb/unittests/Symbol/PostfixExpressionTest.cpp +++ b/lldb/unittests/Symbol/PostfixExpressionTest.cpp @@ -11,7 +11,8 @@ #include "lldb/Utility/StreamString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/raw_ostream.h" #include "gmock/gmock.h" @@ -160,7 +161,7 @@ static std::string ParseAndGenerateDWARF(llvm::StringRef expr) { std::string result; llvm::raw_string_ostream os(result); llvm::DWARFExpression E(extractor, addr_size, llvm::dwarf::DWARF32); - llvm::DWARFExpressionPrinter::print(&E, os, llvm::DIDumpOptions(), nullptr); + llvm::printDwarfExpression(&E, os, llvm::DIDumpOptions(), nullptr); return result; } diff --git a/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp b/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp index d746e04f8a9fc..c60688ef22939 100644 --- a/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp +++ b/lldb/unittests/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpressionTests.cpp @@ -16,7 +16,8 @@ #include "lldb/Utility/StreamBuffer.h" #include "lldb/Utility/StreamString.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" using namespace lldb; using namespace lldb_private; @@ -40,7 +41,7 @@ CheckValidProgramTranslation(llvm::StringRef fpo_program, std::string result; llvm::raw_string_ostream os(result); llvm::DWARFExpression E(extractor, /*AddressSize=*/4, llvm::dwarf::DWARF32); - llvm::DWARFExpressionPrinter::print(&E, os, llvm::DIDumpOptions(), nullptr); + llvm::printDwarfExpression(&E, os, llvm::DIDumpOptions(), nullptr); // actual check ASSERT_EQ(expected_dwarf_expression, result); diff --git a/llvm/include/llvm/DWARFLinker/AddressesMap.h b/llvm/include/llvm/DWARFLinker/AddressesMap.h index a232aafadc5ce..e2215c70dc34e 100644 --- a/llvm/include/llvm/DWARFLinker/AddressesMap.h +++ b/llvm/include/llvm/DWARFLinker/AddressesMap.h @@ -12,8 +12,8 @@ #include "llvm/ADT/AddressRanges.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include <cstdint> namespace llvm { diff --git a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h index b12d96812108e..5b9535380aebf 100644 --- a/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h +++ b/llvm/include/llvm/DWARFLinker/Classic/DWARFLinker.h @@ -20,7 +20,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/Compiler.h" #include <map> diff --git a/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h index 17a18c4b029f4..99aeb0df076e6 100644 --- a/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h +++ b/llvm/include/llvm/DWARFLinker/DWARFLinkerBase.h @@ -16,7 +16,7 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/Compiler.h" #include <map> namespace llvm { diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h index 4723f00a4d241..7d4bf8d923097 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIPrinter.h @@ -9,7 +9,7 @@ #ifndef LLVM_DEBUGINFO_DWARF_DWARFCFIPRINTER_H #define LLVM_DEBUGINFO_DWARF_DWARFCFIPRINTER_H -#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h" #include "llvm/Support/Compiler.h" namespace llvm { diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h index 005ccd208cdda..def291046c7db 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractor.h @@ -10,10 +10,10 @@ #define LLVM_DEBUGINFO_DWARF_DWARFDATAEXTRACTOR_H #include "llvm/BinaryFormat/Dwarf.h" -#include "llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h" #include "llvm/DebugInfo/DWARF/DWARFObject.h" #include "llvm/DebugInfo/DWARF/DWARFRelocMap.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h" #include "llvm/Support/Compiler.h" namespace llvm { diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h index 3b367009a379d..e0d60f605964f 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFDebugFrame.h @@ -12,8 +12,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/iterator.h" -#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" #include "llvm/TargetParser/Triple.h" diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h new file mode 100644 index 0000000000000..0aad492d47551 --- /dev/null +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h @@ -0,0 +1,66 @@ +//===--- DWARFExpressionPRinter.h - DWARF Expression Printing ---*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_DWARF_DWARFEXPRESSIONPRINTER_H +#define LLVM_DEBUGINFO_DWARF_DWARFEXPRESSIONPRINTER_H + +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" +#include "llvm/Support/Compiler.h" + +namespace llvm { + +// This functionality is separated from the main data structure so that nothing +// in DWARFExpression.cpp needs build-time dependencies on DWARFUnit or other +// higher-level Dwarf structures. This approach creates better layering and +// allows DWARFExpression to be used from code which can't have dependencies on +// those higher-level structures. + +class DWARFUnit; +struct DIDumpOptions; +class raw_ostream; + +/// Print a Dwarf expression/ +/// \param E to be printed +/// \param OS to this stream +/// \param GetNameForDWARFReg callback to return dwarf register name +LLVM_ABI void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS, + DIDumpOptions DumpOpts, DWARFUnit *U, + bool IsEH = false); + +/// Print the expression in a format intended to be compact and useful to a +/// user, but not perfectly unambiguous, or capable of representing every +/// valid DWARF expression. Returns true if the expression was sucessfully +/// printed. +/// +/// \param E to be printed +/// \param OS to this stream +/// \param GetNameForDWARFReg callback to return dwarf register name +/// +/// \returns true if the expression was successfully printed +LLVM_ABI bool printDwarfExpressionCompact( + const DWARFExpression *E, raw_ostream &OS, + std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg = + nullptr); + +/// Pretty print a register opcode and operands. +/// \param U within the context of this Dwarf unit, if any. +/// \param OS to this stream +/// \param DumpOpts with these options +/// \param Opcode to print +/// \param Operands to the opcode +/// +/// returns true if the Op was successfully printed +LLVM_ABI bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, + DIDumpOptions DumpOpts, uint8_t Opcode, + ArrayRef<uint64_t> Operands); + +} // end namespace llvm + +#endif // LLVM_DEBUGINFO_DWARF_DWARFEXPRESSIONPRINTER_H diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h index 8e1b9589a5d76..f667496ab1059 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h +++ b/llvm/include/llvm/DebugInfo/DWARF/DWARFVerifier.h @@ -14,8 +14,8 @@ #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnitIndex.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/Compiler.h" #include <cstdint> #include <map> diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h b/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h similarity index 50% rename from llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h rename to llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h index 1d89ac3578c10..bdad0b5ad7a5a 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFCFIProgram.h +++ b/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h @@ -12,8 +12,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/iterator.h" -#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" #include "llvm/TargetParser/Triple.h" @@ -78,8 +78,150 @@ class CFIProgram { /// starting at *Offset and ending at EndOffset. *Offset is updated /// to EndOffset upon successful parsing, or indicates the offset /// where a problem occurred in case an error is returned. - LLVM_ABI Error parse(DWARFDataExtractor Data, uint64_t *Offset, - uint64_t EndOffset); + template <typename T> + LLVM_ABI Error parse(DWARFDataExtractorBase<T> &Data, uint64_t *Offset, + uint64_t EndOffset) { + // 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; + + DataExtractor::Cursor C(*Offset); + while (C && C.tell() < EndOffset) { + uint8_t Opcode = Data.getRelocatedValue(C, 1); + if (!C) + break; + + // Some instructions have a primary opcode encoded in the top bits. + if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) { + // 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) { + case DW_CFA_advance_loc: + case DW_CFA_restore: + addInstruction(Primary, Op1); + break; + case DW_CFA_offset: + addInstruction(Primary, Op1, Data.getULEB128(C)); + break; + default: + llvm_unreachable("invalid primary CFI opcode"); + } + continue; + } + + // Extended opcode - its value is Opcode itself. + switch (Opcode) { + default: + return createStringError(errc::illegal_byte_sequence, + "invalid extended CFI opcode 0x%" PRIx8, + Opcode); + case DW_CFA_nop: + case DW_CFA_remember_state: + case DW_CFA_restore_state: + case DW_CFA_GNU_window_save: + case DW_CFA_AARCH64_negate_ra_state_with_pc: + // No operands + addInstruction(Opcode); + break; + case DW_CFA_set_loc: + // Operands: Address + addInstruction(Opcode, Data.getRelocatedAddress(C)); + break; + case DW_CFA_advance_loc1: + // Operands: 1-byte delta + addInstruction(Opcode, Data.getRelocatedValue(C, 1)); + break; + case DW_CFA_advance_loc2: + // Operands: 2-byte delta + addInstruction(Opcode, Data.getRelocatedValue(C, 2)); + break; + case DW_CFA_advance_loc4: + // Operands: 4-byte delta + addInstruction(Opcode, Data.getRelocatedValue(C, 4)); + 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: + case DW_CFA_GNU_args_size: + // Operands: ULEB128 + addInstruction(Opcode, Data.getULEB128(C)); + break; + case DW_CFA_def_cfa_offset_sf: + // Operands: SLEB128 + addInstruction(Opcode, Data.getSLEB128(C)); + break; + case DW_CFA_LLVM_def_aspace_cfa: + case DW_CFA_LLVM_def_aspace_cfa_sf: { + auto RegNum = Data.getULEB128(C); + auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa + ? Data.getULEB128(C) + : Data.getSLEB128(C); + auto AddressSpace = Data.getULEB128(C); + addInstruction(Opcode, RegNum, CfaOffset, AddressSpace); + break; + } + case DW_CFA_offset_extended: + case DW_CFA_register: + case DW_CFA_def_cfa: + case DW_CFA_val_offset: { + // Operands: ULEB128, ULEB128 + // Note: We can not embed getULEB128 directly into function + // argument list. getULEB128 changes Offset and order of evaluation + // for arguments is unspecified. + uint64_t op1 = Data.getULEB128(C); + uint64_t op2 = Data.getULEB128(C); + addInstruction(Opcode, op1, op2); + break; + } + case DW_CFA_offset_extended_sf: + case DW_CFA_def_cfa_sf: + case DW_CFA_val_offset_sf: { + // Operands: ULEB128, SLEB128 + // Note: see comment for the previous case + uint64_t op1 = Data.getULEB128(C); + uint64_t op2 = (uint64_t)Data.getSLEB128(C); + addInstruction(Opcode, op1, op2); + break; + } + case DW_CFA_def_cfa_expression: { + uint64_t ExprLength = Data.getULEB128(C); + addInstruction(Opcode, 0); + StringRef Expression = Data.getBytes(C, ExprLength); + + DataExtractor Extractor(Expression, Data.isLittleEndian(), + Data.getAddressSize()); + // Note. We do not pass the DWARF format to DWARFExpression, because + // DW_OP_call_ref, the only operation which depends on the format, is + // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. + Instructions.back().Expression = + DWARFExpression(Extractor, Data.getAddressSize()); + break; + } + case DW_CFA_expression: + case DW_CFA_val_expression: { + uint64_t RegNum = Data.getULEB128(C); + addInstruction(Opcode, RegNum, 0); + + uint64_t BlockLength = Data.getULEB128(C); + StringRef Expression = Data.getBytes(C, BlockLength); + DataExtractor Extractor(Expression, Data.isLittleEndian(), + Data.getAddressSize()); + // Note. We do not pass the DWARF format to DWARFExpression, because + // DW_OP_call_ref, the only operation which depends on the format, is + // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. + Instructions.back().Expression = + DWARFExpression(Extractor, Data.getAddressSize()); + break; + } + } + } + + *Offset = C.tell(); + return C.takeError(); + } void addInstruction(const Instruction &I) { Instructions.push_back(I); } diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h b/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h similarity index 100% rename from llvm/include/llvm/DebugInfo/DWARF/DWARFDataExtractorSimple.h rename to llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h diff --git a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h b/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h similarity index 67% rename from llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h rename to llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h index ea414278c35d6..06840b20f9690 100644 --- a/llvm/include/llvm/DebugInfo/DWARF/DWARFExpression.h +++ b/llvm/include/llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h @@ -65,7 +65,7 @@ class DWARFExpression { /// Description of the encoding of one expression Op. struct Description { - DwarfVersion Version; ///< Dwarf version where the Op was introduced. + DwarfVersion Version; ///< Dwarf version where the Op was introduced. SmallVector<Encoding> Op; ///< Encoding for Op operands. template <typename... Ts> @@ -77,7 +77,6 @@ class DWARFExpression { private: friend class DWARFExpression::iterator; - friend class DWARFExpressionPrinter; friend class DWARFVerifier; uint8_t Opcode; ///< The Op Opcode, DW_OP_<something>. @@ -156,7 +155,6 @@ class DWARFExpression { StringRef getData() const { return Data.getData(); } - friend class DWARFExpressionPrinter; friend class DWARFVerifier; private: @@ -170,65 +168,6 @@ inline bool operator==(const DWARFExpression::iterator &LHS, return LHS.Expr == RHS.Expr && LHS.Offset == RHS.Offset; } -// This functionality is separated from the main data structure so that nothing -// in DWARFExpression.cpp needs build-time dependencies on DWARFUnit or other -// higher-level Dwarf structures. This approach creates better layering and -// allows DWARFExpression to be used from code which can't have dependencies on -// those higher-level structures. - -class DWARFUnit; -struct DIDumpOptions; -class raw_ostream; - -class DWARFExpressionPrinter { -public: - /// Print a Dwarf expression/ - /// \param E to be printed - /// \param OS to this stream - /// \param GetNameForDWARFReg callback to return dwarf register name - LLVM_ABI static void print(const DWARFExpression *E, raw_ostream &OS, - DIDumpOptions DumpOpts, DWARFUnit *U, - bool IsEH = false); - - /// Print the expression in a format intended to be compact and useful to a - /// user, but not perfectly unambiguous, or capable of representing every - /// valid DWARF expression. Returns true if the expression was sucessfully - /// printed. - /// - /// \param E to be printed - /// \param OS to this stream - /// \param GetNameForDWARFReg callback to return dwarf register name - /// - /// \returns true if the expression was successfully printed - LLVM_ABI static bool printCompact( - const DWARFExpression *E, raw_ostream &OS, - std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg = - nullptr); - - /// Pretty print a register opcode and operands. - /// \param U within the context of this Dwarf unit, if any. - /// \param OS to this stream - /// \param DumpOpts with these options - /// \param Opcode to print - /// \param Operands to the opcode - /// - /// returns true if the Op was successfully printed - LLVM_ABI static bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, - DIDumpOptions DumpOpts, - uint8_t Opcode, - ArrayRef<uint64_t> Operands); - -private: - static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS, - DIDumpOptions DumpOpts, const DWARFExpression *Expr, - DWARFUnit *U); - - static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS, - DIDumpOptions DumpOpts, - ArrayRef<uint64_t> Operands, - unsigned Operand); -}; - } // end namespace llvm #endif // LLVM_DEBUGINFO_DWARF_DWARFEXPRESSION_H diff --git a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt index 0fe4b905831ff..34969d7524890 100644 --- a/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt +++ b/llvm/lib/CodeGen/AsmPrinter/CMakeLists.txt @@ -38,6 +38,7 @@ add_llvm_component_library(LLVMAsmPrinter Core DebugInfoCodeView DebugInfoDWARF + DebugInfoDWARFLowLevel MC MCParser Remarks diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 0edfca78b0886..ca419a8db18ae 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -32,7 +32,7 @@ #include "llvm/CodeGen/TargetRegisterInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/Function.h" diff --git a/llvm/lib/DWARFLinker/Classic/CMakeLists.txt b/llvm/lib/DWARFLinker/Classic/CMakeLists.txt index 5d3b259e4a33a..4e5cb3c6dfb51 100644 --- a/llvm/lib/DWARFLinker/Classic/CMakeLists.txt +++ b/llvm/lib/DWARFLinker/Classic/CMakeLists.txt @@ -19,6 +19,7 @@ add_llvm_component_library(LLVMDWARFLinkerClassic CodeGen CodeGenTypes DebugInfoDWARF + DebugInfoDWARFLowLevel DWARFLinker MC Object diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp index ae4cc6d85c120..222dc88098102 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinker.cpp @@ -23,10 +23,10 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/MC/MCDwarf.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Error.h" diff --git a/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp b/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp index 66bf158e60f1d..027363aa394e0 100644 --- a/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp +++ b/llvm/lib/DWARFLinker/Classic/DWARFLinkerCompileUnit.cpp @@ -10,7 +10,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/DWARFLinker/Classic/DWARFLinkerDeclContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/FormatVariadic.h" namespace llvm { diff --git a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt index 86e74110b15ea..ce426aeba3f3f 100644 --- a/llvm/lib/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/lib/DebugInfo/DWARF/CMakeLists.txt @@ -1,9 +1,10 @@ +add_subdirectory(LowLevel) + add_llvm_component_library(LLVMDebugInfoDWARF DWARFAbbreviationDeclaration.cpp DWARFAddressRange.cpp DWARFAcceleratorTable.cpp DWARFCFIPrinter.cpp - DWARFCFIProgram.cpp DWARFCompileUnit.cpp DWARFContext.cpp DWARFDebugAbbrev.cpp @@ -19,7 +20,7 @@ add_llvm_component_library(LLVMDebugInfoDWARF DWARFDebugRangeList.cpp DWARFDebugRnglists.cpp DWARFDie.cpp - DWARFExpression.cpp + DWARFExpressionPrinter.cpp DWARFFormValue.cpp DWARFGdbIndex.cpp DWARFListTable.cpp @@ -35,6 +36,7 @@ add_llvm_component_library(LLVMDebugInfoDWARF LINK_COMPONENTS BinaryFormat + DebugInfoDWARFLowLevel Object Support TargetParser diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp index e52f671e4fa1c..2abab0277a9f6 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFCFIPrinter.cpp @@ -8,8 +8,9 @@ #include "llvm/DebugInfo/DWARF/DWARFCFIPrinter.h" #include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Errc.h" @@ -100,8 +101,7 @@ static void printOperand(raw_ostream &OS, const DIDumpOptions &DumpOpts, case CFIProgram::OT_Expression: assert(Instr.Expression && "missing DWARFExpression object"); OS << " "; - DWARFExpressionPrinter::print(&Instr.Expression.value(), OS, DumpOpts, - nullptr); + printDwarfExpression(&Instr.Expression.value(), OS, DumpOpts, nullptr); break; } } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp index 9184502adc7cf..2bf88c9574c2d 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugFrame.cpp @@ -13,9 +13,10 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFCFIPrinter.h" -#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h" #include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Errc.h" @@ -114,7 +115,7 @@ void UnwindLocation::dump(raw_ostream &OS, DIDumpOptions DumpOpts) const { break; case DWARFExpr: { if (Expr) - DWARFExpressionPrinter::print(&(*Expr), OS, DumpOpts, nullptr); + printDwarfExpression(&Expr.value(), OS, DumpOpts, nullptr); break; } case Constant: diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp index fc71be32fdd79..5bd2427da7d73 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp @@ -11,10 +11,11 @@ #include "llvm/BinaryFormat/Dwarf.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFAddressRange.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -117,7 +118,7 @@ static void dumpExpression(raw_ostream &OS, DIDumpOptions DumpOpts, if (U) Format = U->getFormat(); DWARFExpression E(Extractor, AddressSize, Format); - DWARFExpressionPrinter::print(&E, OS, DumpOpts, U); + printDwarfExpression(&E, OS, DumpOpts, U); } bool DWARFLocationTable::dumpLocationList( diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp index 08dd9d30812d1..edc69a36cdff2 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -15,11 +15,12 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFTypePrinter.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Format.h" @@ -99,7 +100,7 @@ static void dumpLocationExpr(raw_ostream &OS, const DWARFFormValue &FormValue, DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()), Ctx.isLittleEndian(), 0); DWARFExpression DE(Data, U->getAddressByteSize(), U->getFormParams().Format); - DWARFExpressionPrinter::print(&DE, OS, DumpOpts, U); + printDwarfExpression(&DE, OS, DumpOpts, U); } static DWARFDie resolveReferencedType(DWARFDie D, DWARFFormValue F) { diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp deleted file mode 100644 index 8255e013a2d79..0000000000000 --- a/llvm/lib/DebugInfo/DWARF/DWARFExpression.cpp +++ /dev/null @@ -1,538 +0,0 @@ -//===-- DWARFExpression.cpp -----------------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" -#include "llvm/ADT/SmallString.h" -#include "llvm/DebugInfo/DWARF/DWARFUnit.h" -#include "llvm/Support/Format.h" -#include <cassert> -#include <cstdint> -#include <vector> - -using namespace llvm; -using namespace dwarf; - -namespace llvm { - -typedef DWARFExpression::Operation Op; -typedef Op::Description Desc; - -static std::vector<Desc> getOpDescriptions() { - std::vector<Desc> Descriptions; - Descriptions.resize(0xff); - Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr); - Descriptions[DW_OP_deref] = Desc(Op::Dwarf2); - Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1); - Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1); - Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2); - Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2); - Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4); - Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4); - Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8); - Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8); - Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB); - Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB); - Descriptions[DW_OP_dup] = Desc(Op::Dwarf2); - Descriptions[DW_OP_drop] = Desc(Op::Dwarf2); - Descriptions[DW_OP_over] = Desc(Op::Dwarf2); - Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1); - Descriptions[DW_OP_swap] = Desc(Op::Dwarf2); - Descriptions[DW_OP_rot] = Desc(Op::Dwarf2); - Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2); - Descriptions[DW_OP_abs] = Desc(Op::Dwarf2); - Descriptions[DW_OP_and] = Desc(Op::Dwarf2); - Descriptions[DW_OP_div] = Desc(Op::Dwarf2); - Descriptions[DW_OP_minus] = Desc(Op::Dwarf2); - Descriptions[DW_OP_mod] = Desc(Op::Dwarf2); - Descriptions[DW_OP_mul] = Desc(Op::Dwarf2); - Descriptions[DW_OP_neg] = Desc(Op::Dwarf2); - Descriptions[DW_OP_not] = Desc(Op::Dwarf2); - Descriptions[DW_OP_or] = Desc(Op::Dwarf2); - Descriptions[DW_OP_plus] = Desc(Op::Dwarf2); - Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB); - Descriptions[DW_OP_shl] = Desc(Op::Dwarf2); - Descriptions[DW_OP_shr] = Desc(Op::Dwarf2); - Descriptions[DW_OP_shra] = Desc(Op::Dwarf2); - Descriptions[DW_OP_xor] = Desc(Op::Dwarf2); - Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2); - Descriptions[DW_OP_eq] = Desc(Op::Dwarf2); - Descriptions[DW_OP_ge] = Desc(Op::Dwarf2); - Descriptions[DW_OP_gt] = Desc(Op::Dwarf2); - Descriptions[DW_OP_le] = Desc(Op::Dwarf2); - Descriptions[DW_OP_lt] = Desc(Op::Dwarf2); - Descriptions[DW_OP_ne] = Desc(Op::Dwarf2); - Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2); - for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA) - Descriptions[LA] = Desc(Op::Dwarf2); - for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA) - Descriptions[LA] = Desc(Op::Dwarf2); - for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA) - Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB); - Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB); - Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB); - Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB); - Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB); - Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1); - Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1); - Descriptions[DW_OP_nop] = Desc(Op::Dwarf2); - Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3); - Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2); - Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4); - Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr); - Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3); - Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3); - Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB); - Descriptions[DW_OP_implicit_value] = - Desc(Op::Dwarf4, Op::SizeLEB, Op::SizeBlock); - Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf4); - Descriptions[DW_OP_implicit_pointer] = - Desc(Op::Dwarf5, Op::SizeRefAddr, Op::SignedSizeLEB); - Descriptions[DW_OP_addrx] = Desc(Op::Dwarf5, Op::SizeLEB); - Descriptions[DW_OP_constx] = Desc(Op::Dwarf5, Op::SizeLEB); - Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB); - Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef); - Descriptions[DW_OP_regval_type] = - Desc(Op::Dwarf5, Op::SizeLEB, Op::BaseTypeRef); - Descriptions[DW_OP_WASM_location] = - Desc(Op::Dwarf4, Op::SizeLEB, Op::WasmLocationArg); - Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3); - Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB); - Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB); - Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB); - Descriptions[DW_OP_GNU_implicit_pointer] = - Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB); - // This Description acts as a marker that getSubOpDesc must be called - // to fetch the final Description for the operation. Each such final - // Description must share the same first SizeSubOpLEB operand. - Descriptions[DW_OP_LLVM_user] = Desc(Op::Dwarf5, Op::SizeSubOpLEB); - return Descriptions; -} - -static Desc getDescImpl(ArrayRef<Desc> Descriptions, unsigned Opcode) { - // Handle possible corrupted or unsupported operation. - if (Opcode >= Descriptions.size()) - return {}; - return Descriptions[Opcode]; -} - -static Desc getOpDesc(unsigned Opcode) { - static std::vector<Desc> Descriptions = getOpDescriptions(); - return getDescImpl(Descriptions, Opcode); -} - -static std::vector<Desc> getSubOpDescriptions() { - static constexpr unsigned LlvmUserDescriptionsSize = 1 -#define HANDLE_DW_OP_LLVM_USEROP(ID, NAME) +1 -#include "llvm/BinaryFormat/Dwarf.def" - ; - std::vector<Desc> Descriptions; - Descriptions.resize(LlvmUserDescriptionsSize); - Descriptions[DW_OP_LLVM_nop] = Desc(Op::Dwarf5, Op::SizeSubOpLEB); - return Descriptions; -} - -static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode) { - assert(Opcode == DW_OP_LLVM_user); - static std::vector<Desc> Descriptions = getSubOpDescriptions(); - return getDescImpl(Descriptions, SubOpcode); -} - -bool DWARFExpression::Operation::extract(DataExtractor Data, - uint8_t AddressSize, uint64_t Offset, - std::optional<DwarfFormat> Format) { - EndOffset = Offset; - Opcode = Data.getU8(&Offset); - - Desc = getOpDesc(Opcode); - if (Desc.Version == Operation::DwarfNA) - return false; - - Operands.resize(Desc.Op.size()); - OperandEndOffsets.resize(Desc.Op.size()); - for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) { - unsigned Size = Desc.Op[Operand]; - unsigned Signed = Size & Operation::SignBit; - - switch (Size & ~Operation::SignBit) { - case Operation::SizeSubOpLEB: - assert(Operand == 0 && "SubOp operand must be the first operand"); - Operands[Operand] = Data.getULEB128(&Offset); - Desc = getSubOpDesc(Opcode, Operands[Operand]); - if (Desc.Version == Operation::DwarfNA) - return false; - assert(Desc.Op[Operand] == Operation::SizeSubOpLEB && - "SizeSubOpLEB Description must begin with SizeSubOpLEB operand"); - break; - case Operation::Size1: - Operands[Operand] = Data.getU8(&Offset); - if (Signed) - Operands[Operand] = (int8_t)Operands[Operand]; - break; - case Operation::Size2: - Operands[Operand] = Data.getU16(&Offset); - if (Signed) - Operands[Operand] = (int16_t)Operands[Operand]; - break; - case Operation::Size4: - Operands[Operand] = Data.getU32(&Offset); - if (Signed) - Operands[Operand] = (int32_t)Operands[Operand]; - break; - case Operation::Size8: - Operands[Operand] = Data.getU64(&Offset); - break; - case Operation::SizeAddr: - Operands[Operand] = Data.getUnsigned(&Offset, AddressSize); - break; - case Operation::SizeRefAddr: - if (!Format) - return false; - Operands[Operand] = - Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format)); - break; - case Operation::SizeLEB: - if (Signed) - Operands[Operand] = Data.getSLEB128(&Offset); - else - Operands[Operand] = Data.getULEB128(&Offset); - break; - case Operation::BaseTypeRef: - Operands[Operand] = Data.getULEB128(&Offset); - break; - case Operation::WasmLocationArg: - assert(Operand == 1); - switch (Operands[0]) { - case 0: - case 1: - case 2: - case 4: - Operands[Operand] = Data.getULEB128(&Offset); - break; - case 3: // global as uint32 - Operands[Operand] = Data.getU32(&Offset); - break; - default: - return false; // Unknown Wasm location - } - break; - case Operation::SizeBlock: - // We need a size, so this cannot be the first operand - if (Operand == 0) - return false; - // Store the offset of the block as the value. - Operands[Operand] = Offset; - Offset += Operands[Operand - 1]; - break; - default: - llvm_unreachable("Unknown DWARFExpression Op size"); - } - - OperandEndOffsets[Operand] = Offset; - } - - EndOffset = Offset; - return true; -} - -std::optional<unsigned> DWARFExpression::Operation::getSubCode() const { - if (!Desc.Op.size() || Desc.Op[0] != Operation::SizeSubOpLEB) - return std::nullopt; - return Operands[0]; -} - -bool DWARFExpression::operator==(const DWARFExpression &RHS) const { - if (AddressSize != RHS.AddressSize || Format != RHS.Format) - return false; - return Data.getData() == RHS.Data.getData(); -} - -void DWARFExpressionPrinter::prettyPrintBaseTypeRef(DWARFUnit *U, - raw_ostream &OS, - DIDumpOptions DumpOpts, - ArrayRef<uint64_t> Operands, - unsigned Operand) { - assert(Operand < Operands.size() && "operand out of bounds"); - if (!U) { - OS << format(" <base_type ref: 0x%" PRIx64 ">", Operands[Operand]); - return; - } - auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]); - if (Die && Die.getTag() == dwarf::DW_TAG_base_type) { - OS << " ("; - if (DumpOpts.Verbose) - OS << format("0x%08" PRIx64 " -> ", Operands[Operand]); - OS << format("0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]); - if (auto Name = dwarf::toString(Die.find(dwarf::DW_AT_name))) - OS << " \"" << *Name << "\""; - } else { - OS << format(" <invalid base_type ref: 0x%" PRIx64 ">", Operands[Operand]); - } -} - -bool DWARFExpressionPrinter::prettyPrintRegisterOp( - DWARFUnit *U, raw_ostream &OS, DIDumpOptions DumpOpts, uint8_t Opcode, - ArrayRef<uint64_t> Operands) { - if (!DumpOpts.GetNameForDWARFReg) - return false; - - uint64_t DwarfRegNum; - unsigned OpNum = 0; - - if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx || - Opcode == DW_OP_regval_type) - DwarfRegNum = Operands[OpNum++]; - else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx) - DwarfRegNum = Opcode - DW_OP_breg0; - else - DwarfRegNum = Opcode - DW_OP_reg0; - - auto RegName = DumpOpts.GetNameForDWARFReg(DwarfRegNum, DumpOpts.IsEH); - if (!RegName.empty()) { - if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) || - Opcode == DW_OP_bregx) - OS << ' ' << RegName << format("%+" PRId64, Operands[OpNum]); - else - OS << ' ' << RegName.data(); - - if (Opcode == DW_OP_regval_type) - prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1); - return true; - } - - return false; -} - -bool DWARFExpressionPrinter::printOp(const DWARFExpression::Operation *Op, - raw_ostream &OS, DIDumpOptions DumpOpts, - const DWARFExpression *Expr, - DWARFUnit *U) { - if (Op->Error) { - OS << "<decoding error>"; - return false; - } - - StringRef Name = OperationEncodingString(Op->Opcode); - assert(!Name.empty() && "DW_OP has no name!"); - OS << Name; - - if ((Op->Opcode >= DW_OP_breg0 && Op->Opcode <= DW_OP_breg31) || - (Op->Opcode >= DW_OP_reg0 && Op->Opcode <= DW_OP_reg31) || - Op->Opcode == DW_OP_bregx || Op->Opcode == DW_OP_regx || - Op->Opcode == DW_OP_regval_type) - if (prettyPrintRegisterOp(U, OS, DumpOpts, Op->Opcode, Op->Operands)) - return true; - - for (unsigned Operand = 0; Operand < Op->Desc.Op.size(); ++Operand) { - unsigned Size = Op->Desc.Op[Operand]; - unsigned Signed = Size & DWARFExpression::Operation::SignBit; - - if (Size == DWARFExpression::Operation::SizeSubOpLEB) { - StringRef SubName = - SubOperationEncodingString(Op->Opcode, Op->Operands[Operand]); - assert(!SubName.empty() && "DW_OP SubOp has no name!"); - OS << " " << SubName; - } else if (Size == DWARFExpression::Operation::BaseTypeRef && U) { - // For DW_OP_convert the operand may be 0 to indicate that conversion to - // the generic type should be done. The same holds for DW_OP_reinterpret, - // which is currently not supported. - if (Op->Opcode == DW_OP_convert && Op->Operands[Operand] == 0) - OS << " 0x0"; - else - prettyPrintBaseTypeRef(U, OS, DumpOpts, Op->Operands, Operand); - } else if (Size == DWARFExpression::Operation::WasmLocationArg) { - assert(Operand == 1); - switch (Op->Operands[0]) { - case 0: - case 1: - case 2: - case 3: // global as uint32 - case 4: - OS << format(" 0x%" PRIx64, Op->Operands[Operand]); - break; - default: assert(false); - } - } else if (Size == DWARFExpression::Operation::SizeBlock) { - uint64_t Offset = Op->Operands[Operand]; - for (unsigned i = 0; i < Op->Operands[Operand - 1]; ++i) - OS << format(" 0x%02x", Expr->Data.getU8(&Offset)); - } else { - if (Signed) - OS << format(" %+" PRId64, (int64_t)Op->Operands[Operand]); - else if (Op->Opcode != DW_OP_entry_value && - Op->Opcode != DW_OP_GNU_entry_value) - OS << format(" 0x%" PRIx64, Op->Operands[Operand]); - } - } - return true; -} - -void DWARFExpressionPrinter::print(const DWARFExpression *E, raw_ostream &OS, - DIDumpOptions DumpOpts, DWARFUnit *U, - bool IsEH) { - uint32_t EntryValExprSize = 0; - uint64_t EntryValStartOffset = 0; - if (E->Data.getData().empty()) - OS << "<empty>"; - - for (auto &Op : *E) { - DumpOpts.IsEH = IsEH; - if (!printOp(&Op, OS, DumpOpts, E, U)) { - uint64_t FailOffset = Op.getEndOffset(); - while (FailOffset < E->Data.getData().size()) - OS << format(" %02x", E->Data.getU8(&FailOffset)); - return; - } - - if (Op.getCode() == DW_OP_entry_value || - Op.getCode() == DW_OP_GNU_entry_value) { - OS << "("; - EntryValExprSize = Op.getRawOperand(0); - EntryValStartOffset = Op.getEndOffset(); - continue; - } - - if (EntryValExprSize) { - EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset; - if (EntryValExprSize == 0) - OS << ")"; - } - - if (Op.getEndOffset() < E->Data.getData().size()) - OS << ", "; - } -} - -/// A user-facing string representation of a DWARF expression. This might be an -/// Address expression, in which case it will be implicitly dereferenced, or a -/// Value expression. -struct PrintedExpr { - enum ExprKind { - Address, - Value, - }; - ExprKind Kind; - SmallString<16> String; - - PrintedExpr(ExprKind K = Address) : Kind(K) {} -}; - -static bool printCompactDWARFExpr( - raw_ostream &OS, DWARFExpression::iterator I, - const DWARFExpression::iterator E, - std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg = - nullptr) { - SmallVector<PrintedExpr, 4> Stack; - - while (I != E) { - const DWARFExpression::Operation &Op = *I; - uint8_t Opcode = Op.getCode(); - switch (Opcode) { - case dwarf::DW_OP_regx: { - // DW_OP_regx: A register, with the register num given as an operand. - // Printed as the plain register name. - uint64_t DwarfRegNum = Op.getRawOperand(0); - auto RegName = GetNameForDWARFReg(DwarfRegNum, false); - if (RegName.empty()) - return false; - raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); - S << RegName; - break; - } - case dwarf::DW_OP_bregx: { - int DwarfRegNum = Op.getRawOperand(0); - int64_t Offset = Op.getRawOperand(1); - auto RegName = GetNameForDWARFReg(DwarfRegNum, false); - if (RegName.empty()) - return false; - raw_svector_ostream S(Stack.emplace_back().String); - S << RegName; - if (Offset) - S << format("%+" PRId64, Offset); - break; - } - case dwarf::DW_OP_entry_value: - case dwarf::DW_OP_GNU_entry_value: { - // DW_OP_entry_value contains a sub-expression which must be rendered - // separately. - uint64_t SubExprLength = Op.getRawOperand(0); - DWARFExpression::iterator SubExprEnd = I.skipBytes(SubExprLength); - ++I; - raw_svector_ostream S(Stack.emplace_back().String); - S << "entry("; - printCompactDWARFExpr(S, I, SubExprEnd, GetNameForDWARFReg); - S << ")"; - I = SubExprEnd; - continue; - } - case dwarf::DW_OP_stack_value: { - // The top stack entry should be treated as the actual value of tne - // variable, rather than the address of the variable in memory. - assert(!Stack.empty()); - Stack.back().Kind = PrintedExpr::Value; - break; - } - case dwarf::DW_OP_nop: { - break; - } - case dwarf::DW_OP_LLVM_user: { - assert(Op.getSubCode() == dwarf::DW_OP_LLVM_nop); - break; - } - default: - if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) { - // DW_OP_reg<N>: A register, with the register num implied by the - // opcode. Printed as the plain register name. - uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0; - auto RegName = GetNameForDWARFReg(DwarfRegNum, false); - if (RegName.empty()) - return false; - raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); - S << RegName; - } else if (Opcode >= dwarf::DW_OP_breg0 && - Opcode <= dwarf::DW_OP_breg31) { - int DwarfRegNum = Opcode - dwarf::DW_OP_breg0; - int64_t Offset = Op.getRawOperand(0); - auto RegName = GetNameForDWARFReg(DwarfRegNum, false); - if (RegName.empty()) - return false; - raw_svector_ostream S(Stack.emplace_back().String); - S << RegName; - if (Offset) - S << format("%+" PRId64, Offset); - } else { - // If we hit an unknown operand, we don't know its effect on the stack, - // so bail out on the whole expression. - OS << "<unknown op " << dwarf::OperationEncodingString(Opcode) << " (" - << (int)Opcode << ")>"; - return false; - } - break; - } - ++I; - } - - if (Stack.size() != 1) { - OS << "<stack of size " << Stack.size() << ", expected 1>"; - return false; - } - - if (Stack.front().Kind == PrintedExpr::Address) - OS << "[" << Stack.front().String << "]"; - else - OS << Stack.front().String; - - return true; -} - -bool DWARFExpressionPrinter::printCompact( - const DWARFExpression *E, raw_ostream &OS, - std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) { - return printCompactDWARFExpr(OS, E->begin(), E->end(), GetNameForDWARFReg); -} - -} // namespace llvm diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp new file mode 100644 index 0000000000000..16133b637e875 --- /dev/null +++ b/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp @@ -0,0 +1,311 @@ +//===-- DWARFExpression.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" +#include "llvm/Support/Format.h" +#include <cassert> +#include <cstdint> +#include <vector> + +using namespace llvm; +using namespace dwarf; + +namespace llvm { + +typedef DWARFExpression::Operation Op; +typedef Op::Description Desc; + +static void prettyPrintBaseTypeRef(DWARFUnit *U, raw_ostream &OS, + DIDumpOptions DumpOpts, + ArrayRef<uint64_t> Operands, + unsigned Operand) { + assert(Operand < Operands.size() && "operand out of bounds"); + if (!U) { + OS << format(" <base_type ref: 0x%" PRIx64 ">", Operands[Operand]); + return; + } + auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]); + if (Die && Die.getTag() == dwarf::DW_TAG_base_type) { + OS << " ("; + if (DumpOpts.Verbose) + OS << format("0x%08" PRIx64 " -> ", Operands[Operand]); + OS << format("0x%08" PRIx64 ")", U->getOffset() + Operands[Operand]); + if (auto Name = dwarf::toString(Die.find(dwarf::DW_AT_name))) + OS << " \"" << *Name << "\""; + } else { + OS << format(" <invalid base_type ref: 0x%" PRIx64 ">", Operands[Operand]); + } +} + +static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS, + DIDumpOptions DumpOpts, const DWARFExpression *Expr, + DWARFUnit *U) { + if (Op->isError()) { + OS << "<decoding error>"; + return false; + } + + StringRef Name = OperationEncodingString(Op->getCode()); + assert(!Name.empty() && "DW_OP has no name!"); + OS << Name; + + if ((Op->getCode() >= DW_OP_breg0 && Op->getCode() <= DW_OP_breg31) || + (Op->getCode() >= DW_OP_reg0 && Op->getCode() <= DW_OP_reg31) || + Op->getCode() == DW_OP_bregx || Op->getCode() == DW_OP_regx || + Op->getCode() == DW_OP_regval_type) + if (prettyPrintRegisterOp(U, OS, DumpOpts, Op->getCode(), + Op->getRawOperands())) + return true; + + for (unsigned Operand = 0; Operand < Op->getDescription().Op.size(); + ++Operand) { + unsigned Size = Op->getDescription().Op[Operand]; + unsigned Signed = Size & DWARFExpression::Operation::SignBit; + + if (Size == DWARFExpression::Operation::SizeSubOpLEB) { + StringRef SubName = + SubOperationEncodingString(Op->getCode(), Op->getRawOperand(Operand)); + assert(!SubName.empty() && "DW_OP SubOp has no name!"); + OS << " " << SubName; + } else if (Size == DWARFExpression::Operation::BaseTypeRef && U) { + // For DW_OP_convert the operand may be 0 to indicate that conversion to + // the generic type should be done. The same holds for DW_OP_reinterpret, + // which is currently not supported. + if (Op->getCode() == DW_OP_convert && Op->getRawOperand(Operand) == 0) + OS << " 0x0"; + else + prettyPrintBaseTypeRef(U, OS, DumpOpts, Op->getRawOperands(), Operand); + } else if (Size == DWARFExpression::Operation::WasmLocationArg) { + assert(Operand == 1); + switch (Op->getRawOperand(0)) { + case 0: + case 1: + case 2: + case 3: // global as uint32 + case 4: + OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); + break; + default: + assert(false); + } + } else if (Size == DWARFExpression::Operation::SizeBlock) { + uint64_t Offset = Op->getRawOperand(Operand); + for (unsigned i = 0; i < Op->getRawOperand(Operand - 1); ++i) + OS << format(" 0x%02x", + static_cast<uint8_t>(Expr->getData()[Offset++])); + } else { + if (Signed) + OS << format(" %+" PRId64, (int64_t)Op->getRawOperand(Operand)); + else if (Op->getCode() != DW_OP_entry_value && + Op->getCode() != DW_OP_GNU_entry_value) + OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); + } + } + return true; +} + +void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS, + DIDumpOptions DumpOpts, DWARFUnit *U, bool IsEH) { + uint32_t EntryValExprSize = 0; + uint64_t EntryValStartOffset = 0; + if (E->getData().empty()) + OS << "<empty>"; + + for (auto &Op : *E) { + DumpOpts.IsEH = IsEH; + if (!printOp(&Op, OS, DumpOpts, E, U)) { + uint64_t FailOffset = Op.getEndOffset(); + while (FailOffset < E->getData().size()) + OS << format(" %02x", static_cast<uint8_t>(E->getData()[FailOffset++])); + return; + } + + if (Op.getCode() == DW_OP_entry_value || + Op.getCode() == DW_OP_GNU_entry_value) { + OS << "("; + EntryValExprSize = Op.getRawOperand(0); + EntryValStartOffset = Op.getEndOffset(); + continue; + } + + if (EntryValExprSize) { + EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset; + if (EntryValExprSize == 0) + OS << ")"; + } + + if (Op.getEndOffset() < E->getData().size()) + OS << ", "; + } +} + +/// A user-facing string representation of a DWARF expression. This might be an +/// Address expression, in which case it will be implicitly dereferenced, or a +/// Value expression. +struct PrintedExpr { + enum ExprKind { + Address, + Value, + }; + ExprKind Kind; + SmallString<16> String; + + PrintedExpr(ExprKind K = Address) : Kind(K) {} +}; + +static bool printCompactDWARFExpr( + raw_ostream &OS, DWARFExpression::iterator I, + const DWARFExpression::iterator E, + std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg = + nullptr) { + SmallVector<PrintedExpr, 4> Stack; + + while (I != E) { + const DWARFExpression::Operation &Op = *I; + uint8_t Opcode = Op.getCode(); + switch (Opcode) { + case dwarf::DW_OP_regx: { + // DW_OP_regx: A register, with the register num given as an operand. + // Printed as the plain register name. + uint64_t DwarfRegNum = Op.getRawOperand(0); + auto RegName = GetNameForDWARFReg(DwarfRegNum, false); + if (RegName.empty()) + return false; + raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); + S << RegName; + break; + } + case dwarf::DW_OP_bregx: { + int DwarfRegNum = Op.getRawOperand(0); + int64_t Offset = Op.getRawOperand(1); + auto RegName = GetNameForDWARFReg(DwarfRegNum, false); + if (RegName.empty()) + return false; + raw_svector_ostream S(Stack.emplace_back().String); + S << RegName; + if (Offset) + S << format("%+" PRId64, Offset); + break; + } + case dwarf::DW_OP_entry_value: + case dwarf::DW_OP_GNU_entry_value: { + // DW_OP_entry_value contains a sub-expression which must be rendered + // separately. + uint64_t SubExprLength = Op.getRawOperand(0); + DWARFExpression::iterator SubExprEnd = I.skipBytes(SubExprLength); + ++I; + raw_svector_ostream S(Stack.emplace_back().String); + S << "entry("; + printCompactDWARFExpr(S, I, SubExprEnd, GetNameForDWARFReg); + S << ")"; + I = SubExprEnd; + continue; + } + case dwarf::DW_OP_stack_value: { + // The top stack entry should be treated as the actual value of tne + // variable, rather than the address of the variable in memory. + assert(!Stack.empty()); + Stack.back().Kind = PrintedExpr::Value; + break; + } + case dwarf::DW_OP_nop: { + break; + } + case dwarf::DW_OP_LLVM_user: { + assert(Op.getSubCode() == dwarf::DW_OP_LLVM_nop); + break; + } + default: + if (Opcode >= dwarf::DW_OP_reg0 && Opcode <= dwarf::DW_OP_reg31) { + // DW_OP_reg<N>: A register, with the register num implied by the + // opcode. Printed as the plain register name. + uint64_t DwarfRegNum = Opcode - dwarf::DW_OP_reg0; + auto RegName = GetNameForDWARFReg(DwarfRegNum, false); + if (RegName.empty()) + return false; + raw_svector_ostream S(Stack.emplace_back(PrintedExpr::Value).String); + S << RegName; + } else if (Opcode >= dwarf::DW_OP_breg0 && + Opcode <= dwarf::DW_OP_breg31) { + int DwarfRegNum = Opcode - dwarf::DW_OP_breg0; + int64_t Offset = Op.getRawOperand(0); + auto RegName = GetNameForDWARFReg(DwarfRegNum, false); + if (RegName.empty()) + return false; + raw_svector_ostream S(Stack.emplace_back().String); + S << RegName; + if (Offset) + S << format("%+" PRId64, Offset); + } else { + // If we hit an unknown operand, we don't know its effect on the stack, + // so bail out on the whole expression. + OS << "<unknown op " << dwarf::OperationEncodingString(Opcode) << " (" + << (int)Opcode << ")>"; + return false; + } + break; + } + ++I; + } + + if (Stack.size() != 1) { + OS << "<stack of size " << Stack.size() << ", expected 1>"; + return false; + } + + if (Stack.front().Kind == PrintedExpr::Address) + OS << "[" << Stack.front().String << "]"; + else + OS << Stack.front().String; + + return true; +} + +bool printDwarfExpressionCompact( + const DWARFExpression *E, raw_ostream &OS, + std::function<StringRef(uint64_t RegNum, bool IsEH)> GetNameForDWARFReg) { + return printCompactDWARFExpr(OS, E->begin(), E->end(), GetNameForDWARFReg); +} + +bool prettyPrintRegisterOp(DWARFUnit *U, raw_ostream &OS, + DIDumpOptions DumpOpts, uint8_t Opcode, + ArrayRef<uint64_t> Operands) { + if (!DumpOpts.GetNameForDWARFReg) + return false; + + uint64_t DwarfRegNum; + unsigned OpNum = 0; + + if (Opcode == DW_OP_bregx || Opcode == DW_OP_regx || + Opcode == DW_OP_regval_type) + DwarfRegNum = Operands[OpNum++]; + else if (Opcode >= DW_OP_breg0 && Opcode < DW_OP_bregx) + DwarfRegNum = Opcode - DW_OP_breg0; + else + DwarfRegNum = Opcode - DW_OP_reg0; + + auto RegName = DumpOpts.GetNameForDWARFReg(DwarfRegNum, DumpOpts.IsEH); + if (!RegName.empty()) { + if ((Opcode >= DW_OP_breg0 && Opcode <= DW_OP_breg31) || + Opcode == DW_OP_bregx) + OS << ' ' << RegName << format("%+" PRId64, Operands[OpNum]); + else + OS << ' ' << RegName.data(); + + if (Opcode == DW_OP_regval_type) + prettyPrintBaseTypeRef(U, OS, DumpOpts, Operands, 1); + return true; + } + + return false; +} + +} // namespace llvm diff --git a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp index d719a47c84072..ef59c82fc6a01 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -19,12 +19,12 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRnglists.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFListTable.h" #include "llvm/DebugInfo/DWARF/DWARFObject.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Errc.h" diff --git a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp index c12786cac8686..8ec3f1729b974 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFVerifier.cpp @@ -19,13 +19,13 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" #include "llvm/DebugInfo/DWARF/DWARFObject.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFTypeUnit.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Object/Error.h" #include "llvm/Support/DJB.h" #include "llvm/Support/Error.h" diff --git a/llvm/lib/DebugInfo/DWARF/LowLevel/CMakeLists.txt b/llvm/lib/DebugInfo/DWARF/LowLevel/CMakeLists.txt new file mode 100644 index 0000000000000..c11a2589a552d --- /dev/null +++ b/llvm/lib/DebugInfo/DWARF/LowLevel/CMakeLists.txt @@ -0,0 +1,14 @@ +add_llvm_component_library(LLVMDebugInfoDWARFLowLevel + DWARFCFIProgram.cpp + DWARFExpression.cpp + + ADDITIONAL_HEADER_DIRS + ${LLVM_MAIN_INCLUDE_DIR}/llvm/DebugInfo/DWARF/LowLevel + + // This code should have almost no dependencies. Anything that needs + // more should use the higher-level DebugInfo/DWARF/ library. + LINK_COMPONENTS + BinaryFormat + Support + TargetParser + ) diff --git a/llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp b/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.cpp similarity index 60% rename from llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp rename to llvm/lib/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.cpp index 365b26b98a1e3..25a0ccb50c8a9 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFCFIProgram.cpp +++ b/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.cpp @@ -6,9 +6,8 @@ // //===----------------------------------------------------------------------===// -#include "llvm/DebugInfo/DWARF/DWARFCFIProgram.h" -#include "llvm/DebugInfo/DIContext.h" -#include "llvm/DebugInfo/DWARF/DWARFDataExtractor.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFCFIProgram.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFDataExtractorSimple.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataExtractor.h" #include "llvm/Support/Errc.h" @@ -23,149 +22,6 @@ using namespace llvm; using namespace dwarf; -// 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; - -Error CFIProgram::parse(DWARFDataExtractor Data, uint64_t *Offset, - uint64_t EndOffset) { - DataExtractor::Cursor C(*Offset); - while (C && C.tell() < EndOffset) { - uint8_t Opcode = Data.getRelocatedValue(C, 1); - if (!C) - break; - - // Some instructions have a primary opcode encoded in the top bits. - if (uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK) { - // 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) { - case DW_CFA_advance_loc: - case DW_CFA_restore: - addInstruction(Primary, Op1); - break; - case DW_CFA_offset: - addInstruction(Primary, Op1, Data.getULEB128(C)); - break; - default: - llvm_unreachable("invalid primary CFI opcode"); - } - continue; - } - - // Extended opcode - its value is Opcode itself. - switch (Opcode) { - default: - return createStringError(errc::illegal_byte_sequence, - "invalid extended CFI opcode 0x%" PRIx8, Opcode); - case DW_CFA_nop: - case DW_CFA_remember_state: - case DW_CFA_restore_state: - case DW_CFA_GNU_window_save: - case DW_CFA_AARCH64_negate_ra_state_with_pc: - // No operands - addInstruction(Opcode); - break; - case DW_CFA_set_loc: - // Operands: Address - addInstruction(Opcode, Data.getRelocatedAddress(C)); - break; - case DW_CFA_advance_loc1: - // Operands: 1-byte delta - addInstruction(Opcode, Data.getRelocatedValue(C, 1)); - break; - case DW_CFA_advance_loc2: - // Operands: 2-byte delta - addInstruction(Opcode, Data.getRelocatedValue(C, 2)); - break; - case DW_CFA_advance_loc4: - // Operands: 4-byte delta - addInstruction(Opcode, Data.getRelocatedValue(C, 4)); - 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: - case DW_CFA_GNU_args_size: - // Operands: ULEB128 - addInstruction(Opcode, Data.getULEB128(C)); - break; - case DW_CFA_def_cfa_offset_sf: - // Operands: SLEB128 - addInstruction(Opcode, Data.getSLEB128(C)); - break; - case DW_CFA_LLVM_def_aspace_cfa: - case DW_CFA_LLVM_def_aspace_cfa_sf: { - auto RegNum = Data.getULEB128(C); - auto CfaOffset = Opcode == DW_CFA_LLVM_def_aspace_cfa - ? Data.getULEB128(C) - : Data.getSLEB128(C); - auto AddressSpace = Data.getULEB128(C); - addInstruction(Opcode, RegNum, CfaOffset, AddressSpace); - break; - } - case DW_CFA_offset_extended: - case DW_CFA_register: - case DW_CFA_def_cfa: - case DW_CFA_val_offset: { - // Operands: ULEB128, ULEB128 - // Note: We can not embed getULEB128 directly into function - // argument list. getULEB128 changes Offset and order of evaluation - // for arguments is unspecified. - uint64_t op1 = Data.getULEB128(C); - uint64_t op2 = Data.getULEB128(C); - addInstruction(Opcode, op1, op2); - break; - } - case DW_CFA_offset_extended_sf: - case DW_CFA_def_cfa_sf: - case DW_CFA_val_offset_sf: { - // Operands: ULEB128, SLEB128 - // Note: see comment for the previous case - uint64_t op1 = Data.getULEB128(C); - uint64_t op2 = (uint64_t)Data.getSLEB128(C); - addInstruction(Opcode, op1, op2); - break; - } - case DW_CFA_def_cfa_expression: { - uint64_t ExprLength = Data.getULEB128(C); - addInstruction(Opcode, 0); - StringRef Expression = Data.getBytes(C, ExprLength); - - DataExtractor Extractor(Expression, Data.isLittleEndian(), - Data.getAddressSize()); - // Note. We do not pass the DWARF format to DWARFExpression, because - // DW_OP_call_ref, the only operation which depends on the format, is - // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. - Instructions.back().Expression = - DWARFExpression(Extractor, Data.getAddressSize()); - break; - } - case DW_CFA_expression: - case DW_CFA_val_expression: { - uint64_t RegNum = Data.getULEB128(C); - addInstruction(Opcode, RegNum, 0); - - uint64_t BlockLength = Data.getULEB128(C); - StringRef Expression = Data.getBytes(C, BlockLength); - DataExtractor Extractor(Expression, Data.isLittleEndian(), - Data.getAddressSize()); - // Note. We do not pass the DWARF format to DWARFExpression, because - // DW_OP_call_ref, the only operation which depends on the format, is - // prohibited in call frame instructions, see sec. 6.4.2 in DWARFv5. - Instructions.back().Expression = - DWARFExpression(Extractor, Data.getAddressSize()); - break; - } - } - } - - *Offset = C.tell(); - return C.takeError(); -} - StringRef CFIProgram::callFrameString(unsigned Opcode) const { return dwarf::CallFrameString(Opcode, Arch); } diff --git a/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp b/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp new file mode 100644 index 0000000000000..70724185463b0 --- /dev/null +++ b/llvm/lib/DebugInfo/DWARF/LowLevel/DWARFExpression.cpp @@ -0,0 +1,253 @@ +//===-- DWARFExpression.cpp -----------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/Format.h" +#include <cassert> +#include <cstdint> +#include <vector> + +using namespace llvm; +using namespace dwarf; + +namespace llvm { + +typedef DWARFExpression::Operation Op; +typedef Op::Description Desc; + +static std::vector<Desc> getOpDescriptions() { + std::vector<Desc> Descriptions; + Descriptions.resize(0xff); + Descriptions[DW_OP_addr] = Desc(Op::Dwarf2, Op::SizeAddr); + Descriptions[DW_OP_deref] = Desc(Op::Dwarf2); + Descriptions[DW_OP_const1u] = Desc(Op::Dwarf2, Op::Size1); + Descriptions[DW_OP_const1s] = Desc(Op::Dwarf2, Op::SignedSize1); + Descriptions[DW_OP_const2u] = Desc(Op::Dwarf2, Op::Size2); + Descriptions[DW_OP_const2s] = Desc(Op::Dwarf2, Op::SignedSize2); + Descriptions[DW_OP_const4u] = Desc(Op::Dwarf2, Op::Size4); + Descriptions[DW_OP_const4s] = Desc(Op::Dwarf2, Op::SignedSize4); + Descriptions[DW_OP_const8u] = Desc(Op::Dwarf2, Op::Size8); + Descriptions[DW_OP_const8s] = Desc(Op::Dwarf2, Op::SignedSize8); + Descriptions[DW_OP_constu] = Desc(Op::Dwarf2, Op::SizeLEB); + Descriptions[DW_OP_consts] = Desc(Op::Dwarf2, Op::SignedSizeLEB); + Descriptions[DW_OP_dup] = Desc(Op::Dwarf2); + Descriptions[DW_OP_drop] = Desc(Op::Dwarf2); + Descriptions[DW_OP_over] = Desc(Op::Dwarf2); + Descriptions[DW_OP_pick] = Desc(Op::Dwarf2, Op::Size1); + Descriptions[DW_OP_swap] = Desc(Op::Dwarf2); + Descriptions[DW_OP_rot] = Desc(Op::Dwarf2); + Descriptions[DW_OP_xderef] = Desc(Op::Dwarf2); + Descriptions[DW_OP_abs] = Desc(Op::Dwarf2); + Descriptions[DW_OP_and] = Desc(Op::Dwarf2); + Descriptions[DW_OP_div] = Desc(Op::Dwarf2); + Descriptions[DW_OP_minus] = Desc(Op::Dwarf2); + Descriptions[DW_OP_mod] = Desc(Op::Dwarf2); + Descriptions[DW_OP_mul] = Desc(Op::Dwarf2); + Descriptions[DW_OP_neg] = Desc(Op::Dwarf2); + Descriptions[DW_OP_not] = Desc(Op::Dwarf2); + Descriptions[DW_OP_or] = Desc(Op::Dwarf2); + Descriptions[DW_OP_plus] = Desc(Op::Dwarf2); + Descriptions[DW_OP_plus_uconst] = Desc(Op::Dwarf2, Op::SizeLEB); + Descriptions[DW_OP_shl] = Desc(Op::Dwarf2); + Descriptions[DW_OP_shr] = Desc(Op::Dwarf2); + Descriptions[DW_OP_shra] = Desc(Op::Dwarf2); + Descriptions[DW_OP_xor] = Desc(Op::Dwarf2); + Descriptions[DW_OP_bra] = Desc(Op::Dwarf2, Op::SignedSize2); + Descriptions[DW_OP_eq] = Desc(Op::Dwarf2); + Descriptions[DW_OP_ge] = Desc(Op::Dwarf2); + Descriptions[DW_OP_gt] = Desc(Op::Dwarf2); + Descriptions[DW_OP_le] = Desc(Op::Dwarf2); + Descriptions[DW_OP_lt] = Desc(Op::Dwarf2); + Descriptions[DW_OP_ne] = Desc(Op::Dwarf2); + Descriptions[DW_OP_skip] = Desc(Op::Dwarf2, Op::SignedSize2); + for (uint16_t LA = DW_OP_lit0; LA <= DW_OP_lit31; ++LA) + Descriptions[LA] = Desc(Op::Dwarf2); + for (uint16_t LA = DW_OP_reg0; LA <= DW_OP_reg31; ++LA) + Descriptions[LA] = Desc(Op::Dwarf2); + for (uint16_t LA = DW_OP_breg0; LA <= DW_OP_breg31; ++LA) + Descriptions[LA] = Desc(Op::Dwarf2, Op::SignedSizeLEB); + Descriptions[DW_OP_regx] = Desc(Op::Dwarf2, Op::SizeLEB); + Descriptions[DW_OP_fbreg] = Desc(Op::Dwarf2, Op::SignedSizeLEB); + Descriptions[DW_OP_bregx] = Desc(Op::Dwarf2, Op::SizeLEB, Op::SignedSizeLEB); + Descriptions[DW_OP_piece] = Desc(Op::Dwarf2, Op::SizeLEB); + Descriptions[DW_OP_deref_size] = Desc(Op::Dwarf2, Op::Size1); + Descriptions[DW_OP_xderef_size] = Desc(Op::Dwarf2, Op::Size1); + Descriptions[DW_OP_nop] = Desc(Op::Dwarf2); + Descriptions[DW_OP_push_object_address] = Desc(Op::Dwarf3); + Descriptions[DW_OP_call2] = Desc(Op::Dwarf3, Op::Size2); + Descriptions[DW_OP_call4] = Desc(Op::Dwarf3, Op::Size4); + Descriptions[DW_OP_call_ref] = Desc(Op::Dwarf3, Op::SizeRefAddr); + Descriptions[DW_OP_form_tls_address] = Desc(Op::Dwarf3); + Descriptions[DW_OP_call_frame_cfa] = Desc(Op::Dwarf3); + Descriptions[DW_OP_bit_piece] = Desc(Op::Dwarf3, Op::SizeLEB, Op::SizeLEB); + Descriptions[DW_OP_implicit_value] = + Desc(Op::Dwarf4, Op::SizeLEB, Op::SizeBlock); + Descriptions[DW_OP_stack_value] = Desc(Op::Dwarf4); + Descriptions[DW_OP_implicit_pointer] = + Desc(Op::Dwarf5, Op::SizeRefAddr, Op::SignedSizeLEB); + Descriptions[DW_OP_addrx] = Desc(Op::Dwarf5, Op::SizeLEB); + Descriptions[DW_OP_constx] = Desc(Op::Dwarf5, Op::SizeLEB); + Descriptions[DW_OP_entry_value] = Desc(Op::Dwarf5, Op::SizeLEB); + Descriptions[DW_OP_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef); + Descriptions[DW_OP_regval_type] = + Desc(Op::Dwarf5, Op::SizeLEB, Op::BaseTypeRef); + Descriptions[DW_OP_WASM_location] = + Desc(Op::Dwarf4, Op::SizeLEB, Op::WasmLocationArg); + Descriptions[DW_OP_GNU_push_tls_address] = Desc(Op::Dwarf3); + Descriptions[DW_OP_GNU_addr_index] = Desc(Op::Dwarf4, Op::SizeLEB); + Descriptions[DW_OP_GNU_const_index] = Desc(Op::Dwarf4, Op::SizeLEB); + Descriptions[DW_OP_GNU_entry_value] = Desc(Op::Dwarf4, Op::SizeLEB); + Descriptions[DW_OP_GNU_implicit_pointer] = + Desc(Op::Dwarf4, Op::SizeRefAddr, Op::SignedSizeLEB); + // This Description acts as a marker that getSubOpDesc must be called + // to fetch the final Description for the operation. Each such final + // Description must share the same first SizeSubOpLEB operand. + Descriptions[DW_OP_LLVM_user] = Desc(Op::Dwarf5, Op::SizeSubOpLEB); + return Descriptions; +} + +static Desc getDescImpl(ArrayRef<Desc> Descriptions, unsigned Opcode) { + // Handle possible corrupted or unsupported operation. + if (Opcode >= Descriptions.size()) + return {}; + return Descriptions[Opcode]; +} + +static Desc getOpDesc(unsigned Opcode) { + static std::vector<Desc> Descriptions = getOpDescriptions(); + return getDescImpl(Descriptions, Opcode); +} + +static std::vector<Desc> getSubOpDescriptions() { + static constexpr unsigned LlvmUserDescriptionsSize = 1 +#define HANDLE_DW_OP_LLVM_USEROP(ID, NAME) +1 +#include "llvm/BinaryFormat/Dwarf.def" + ; + std::vector<Desc> Descriptions; + Descriptions.resize(LlvmUserDescriptionsSize); + Descriptions[DW_OP_LLVM_nop] = Desc(Op::Dwarf5, Op::SizeSubOpLEB); + return Descriptions; +} + +static Desc getSubOpDesc(unsigned Opcode, unsigned SubOpcode) { + assert(Opcode == DW_OP_LLVM_user); + static std::vector<Desc> Descriptions = getSubOpDescriptions(); + return getDescImpl(Descriptions, SubOpcode); +} + +bool DWARFExpression::Operation::extract(DataExtractor Data, + uint8_t AddressSize, uint64_t Offset, + std::optional<DwarfFormat> Format) { + EndOffset = Offset; + Opcode = Data.getU8(&Offset); + + Desc = getOpDesc(Opcode); + if (Desc.Version == Operation::DwarfNA) + return false; + + Operands.resize(Desc.Op.size()); + OperandEndOffsets.resize(Desc.Op.size()); + for (unsigned Operand = 0; Operand < Desc.Op.size(); ++Operand) { + unsigned Size = Desc.Op[Operand]; + unsigned Signed = Size & Operation::SignBit; + + switch (Size & ~Operation::SignBit) { + case Operation::SizeSubOpLEB: + assert(Operand == 0 && "SubOp operand must be the first operand"); + Operands[Operand] = Data.getULEB128(&Offset); + Desc = getSubOpDesc(Opcode, Operands[Operand]); + if (Desc.Version == Operation::DwarfNA) + return false; + assert(Desc.Op[Operand] == Operation::SizeSubOpLEB && + "SizeSubOpLEB Description must begin with SizeSubOpLEB operand"); + break; + case Operation::Size1: + Operands[Operand] = Data.getU8(&Offset); + if (Signed) + Operands[Operand] = (int8_t)Operands[Operand]; + break; + case Operation::Size2: + Operands[Operand] = Data.getU16(&Offset); + if (Signed) + Operands[Operand] = (int16_t)Operands[Operand]; + break; + case Operation::Size4: + Operands[Operand] = Data.getU32(&Offset); + if (Signed) + Operands[Operand] = (int32_t)Operands[Operand]; + break; + case Operation::Size8: + Operands[Operand] = Data.getU64(&Offset); + break; + case Operation::SizeAddr: + Operands[Operand] = Data.getUnsigned(&Offset, AddressSize); + break; + case Operation::SizeRefAddr: + if (!Format) + return false; + Operands[Operand] = + Data.getUnsigned(&Offset, dwarf::getDwarfOffsetByteSize(*Format)); + break; + case Operation::SizeLEB: + if (Signed) + Operands[Operand] = Data.getSLEB128(&Offset); + else + Operands[Operand] = Data.getULEB128(&Offset); + break; + case Operation::BaseTypeRef: + Operands[Operand] = Data.getULEB128(&Offset); + break; + case Operation::WasmLocationArg: + assert(Operand == 1); + switch (Operands[0]) { + case 0: + case 1: + case 2: + case 4: + Operands[Operand] = Data.getULEB128(&Offset); + break; + case 3: // global as uint32 + Operands[Operand] = Data.getU32(&Offset); + break; + default: + return false; // Unknown Wasm location + } + break; + case Operation::SizeBlock: + // We need a size, so this cannot be the first operand + if (Operand == 0) + return false; + // Store the offset of the block as the value. + Operands[Operand] = Offset; + Offset += Operands[Operand - 1]; + break; + default: + llvm_unreachable("Unknown DWARFExpression Op size"); + } + + OperandEndOffsets[Operand] = Offset; + } + + EndOffset = Offset; + return true; +} + +std::optional<unsigned> DWARFExpression::Operation::getSubCode() const { + if (!Desc.Op.size() || Desc.Op[0] != Operation::SizeSubOpLEB) + return std::nullopt; + return Operands[0]; +} + +bool DWARFExpression::operator==(const DWARFExpression &RHS) const { + if (AddressSize != RHS.AddressSize || Format != RHS.Format) + return false; + return Data.getData() == RHS.Data.getData(); +} + +} // namespace llvm diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 95b7007d119bc..696e2bc948a2e 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp @@ -14,7 +14,8 @@ #include "llvm/DebugInfo/LogicalView/Readers/LVDWARFReader.h" #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/DebugInfo/LogicalView/Core/LVLine.h" #include "llvm/DebugInfo/LogicalView/Core/LVScope.h" #include "llvm/DebugInfo/LogicalView/Core/LVSymbol.h" @@ -594,8 +595,7 @@ std::string LVDWARFReader::getRegisterName(LVSmall Opcode, return {}; }; DumpOpts.GetNameForDWARFReg = GetRegName; - DWARFExpressionPrinter::prettyPrintRegisterOp(/*U=*/nullptr, Stream, DumpOpts, - Opcode, Operands); + prettyPrintRegisterOp(/*U=*/nullptr, Stream, DumpOpts, Opcode, Operands); return Stream.str(); } diff --git a/llvm/lib/ProfileData/CMakeLists.txt b/llvm/lib/ProfileData/CMakeLists.txt index d26af1c3d5547..c2366dc0ae03e 100644 --- a/llvm/lib/ProfileData/CMakeLists.txt +++ b/llvm/lib/ProfileData/CMakeLists.txt @@ -35,6 +35,7 @@ add_llvm_component_library(LLVMProfileData Demangle Symbolize DebugInfoDWARF + DebugInfoDWARFLowLevel TargetParser ) diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp index d92107f93dc56..07b69e9fad3ec 100644 --- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp +++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp @@ -10,10 +10,10 @@ #include "llvm/DebugInfo/DIContext.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Object/MachO.h" #include "llvm/Support/Debug.h" #include "llvm/Support/Format.h" diff --git a/llvm/tools/dsymutil/CMakeLists.txt b/llvm/tools/dsymutil/CMakeLists.txt index 366b63b2a8695..d3cdbe466de08 100644 --- a/llvm/tools/dsymutil/CMakeLists.txt +++ b/llvm/tools/dsymutil/CMakeLists.txt @@ -15,6 +15,7 @@ set(LLVM_LINK_COMPONENTS DWARFLinkerClassic DWARFLinkerParallel DebugInfoDWARF + DebugInfoDWARFLowLevel MC Object Option diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp index e88e076dca996..138c5d0a513ed 100644 --- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp +++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp @@ -39,10 +39,10 @@ #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h" #include "llvm/DebugInfo/DWARF/DWARFDebugRangeList.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" #include "llvm/DebugInfo/DWARF/DWARFSection.h" #include "llvm/DebugInfo/DWARF/DWARFUnit.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" diff --git a/llvm/tools/llvm-dwarfdump/CMakeLists.txt b/llvm/tools/llvm-dwarfdump/CMakeLists.txt index 7c68aaac05d98..aeb1b8f14d830 100644 --- a/llvm/tools/llvm-dwarfdump/CMakeLists.txt +++ b/llvm/tools/llvm-dwarfdump/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS DebugInfoDWARF + DebugInfoDWARFLowLevel AllTargetsDescs AllTargetsInfos MC diff --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp index af9a93ad35b9c..f92b2b55fa8dc 100644 --- a/llvm/tools/llvm-dwarfdump/Statistics.cpp +++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp @@ -12,7 +12,7 @@ #include "llvm/ADT/StringSet.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/JSON.h" diff --git a/llvm/tools/llvm-dwarfutil/CMakeLists.txt b/llvm/tools/llvm-dwarfutil/CMakeLists.txt index 23a526782dd7b..88335928b68dd 100644 --- a/llvm/tools/llvm-dwarfutil/CMakeLists.txt +++ b/llvm/tools/llvm-dwarfutil/CMakeLists.txt @@ -11,6 +11,7 @@ set(LLVM_LINK_COMPONENTS DWARFLinkerClassic DWARFLinkerParallel DebugInfoDWARF + DebugInfoDWARFLowLevel MC ObjCopy Object diff --git a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp index 285dcf75ecd9d..ccc1324bc66d7 100644 --- a/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp +++ b/llvm/tools/llvm-dwarfutil/DebugInfoLinker.cpp @@ -13,7 +13,7 @@ #include "llvm/DWARFLinker/Classic/DWARFStreamer.h" #include "llvm/DWARFLinker/Parallel/DWARFLinker.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Object/ObjectFile.h" #include <memory> #include <vector> diff --git a/llvm/tools/llvm-objdump/CMakeLists.txt b/llvm/tools/llvm-objdump/CMakeLists.txt index 0306736388979..7e3197f0a0bd3 100644 --- a/llvm/tools/llvm-objdump/CMakeLists.txt +++ b/llvm/tools/llvm-objdump/CMakeLists.txt @@ -5,6 +5,7 @@ set(LLVM_LINK_COMPONENTS BinaryFormat DebugInfoBTF DebugInfoDWARF + DebugInfoDWARFLowLevel Demangle MC MCDisassembler diff --git a/llvm/tools/llvm-objdump/SourcePrinter.cpp b/llvm/tools/llvm-objdump/SourcePrinter.cpp index bf3363795a4d9..3630502172977 100644 --- a/llvm/tools/llvm-objdump/SourcePrinter.cpp +++ b/llvm/tools/llvm-objdump/SourcePrinter.cpp @@ -15,7 +15,8 @@ #include "SourcePrinter.h" #include "llvm-objdump.h" #include "llvm/ADT/SmallSet.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/Support/FormatVariadic.h" #define DEBUG_TYPE "objdump" @@ -45,7 +46,7 @@ void LiveVariable::print(raw_ostream &OS, const MCRegisterInfo &MRI) const { return {}; }; - DWARFExpressionPrinter::printCompact(&Expression, OS, GetRegName); + printDwarfExpressionCompact(&Expression, OS, GetRegName); } void LiveVariablePrinter::addVariable(DWARFDie FuncDie, DWARFDie VarDie) { diff --git a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt index 0c5b3f28ca3d5..dc8240f904b4c 100644 --- a/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt +++ b/llvm/unittests/DebugInfo/DWARF/CMakeLists.txt @@ -4,6 +4,7 @@ set(LLVM_LINK_COMPONENTS BinaryFormat CodeGenTypes DebugInfoDWARF + DebugInfoDWARFLowLevel MC Object ObjectYAML diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp index 9225ab0125f2f..3e0cc8fed84c0 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCompactPrinterTest.cpp @@ -10,7 +10,8 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/DWARFExpressionPrinter.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/TargetRegistry.h" @@ -70,7 +71,7 @@ void DWARFExpressionCompactPrinterTest::TestExprPrinter( return {}; }; - DWARFExpressionPrinter::printCompact(&Expr, OS, GetRegName); + printDwarfExpressionCompact(&Expr, OS, GetRegName); EXPECT_EQ(OS.str(), Expected); } diff --git a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp index ec9c0dddcbc0c..78d383ed0b22e 100644 --- a/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp +++ b/llvm/unittests/DebugInfo/DWARF/DWARFExpressionCopyBytesTest.cpp @@ -11,7 +11,7 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugFrame.h" #include "llvm/DebugInfo/DWARF/DWARFDie.h" -#include "llvm/DebugInfo/DWARF/DWARFExpression.h" +#include "llvm/DebugInfo/DWARF/LowLevel/DWARFExpression.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCCodeEmitter.h" diff --git a/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel b/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel index b5cd6dbcbd4f9..97c25bcdece7b 100644 --- a/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/bolt/BUILD.bazel @@ -106,6 +106,7 @@ cc_library( "//llvm:DWARFLinker", "//llvm:DWP", "//llvm:DebugInfoDWARF", + "//llvm:DebugInfoDWARFLowLevel", "//llvm:Demangle", "//llvm:JITLink", "//llvm:MC", @@ -296,6 +297,7 @@ cc_library( "//llvm:BinaryFormat", "//llvm:CodeGen", "//llvm:DebugInfoDWARF", + "//llvm:DebugInfoDWARFLowLevel", "//llvm:Demangle", "//llvm:ExecutionEngine", "//llvm:MC", diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel index d5a7fdb747f86..c28d637cea656 100644 --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -493,6 +493,7 @@ cc_library( ":DebugInfo", ":DebugInfoCodeView", ":DebugInfoDWARF", + ":DebugInfoDWARFLowLevel", ":DebugInfoPDB", ":Demangle", ":MC", @@ -572,6 +573,7 @@ cc_library( deps = [ ":BinaryFormat", ":DebugInfo", + ":DebugInfoDWARFLowLevel", ":MC", ":Object", ":Support", @@ -579,6 +581,20 @@ cc_library( ], ) +cc_library( + name = "DebugInfoDWARFLowLevel", + srcs = glob([ + "lib/DebugInfo/DWARF/LowLevel/*.cpp", + ]), + hdrs = glob(["include/llvm/DebugInfo/DWARF/LowLevel/*.h"]), + copts = llvm_copts, + deps = [ + ":BinaryFormat", + ":Support", + ":TargetParser", + ], +) + cc_library( name = "DebugInfoGSYM", srcs = glob([ @@ -1154,6 +1170,7 @@ cc_library( ":Core", ":DebugInfo", ":DebugInfoDWARF", + ":DebugInfoDWARFLowLevel", ":Demangle", ":Object", ":Support", @@ -2081,6 +2098,7 @@ cc_library( ":Core", ":DebugInfoCodeView", ":DebugInfoDWARF", + ":DebugInfoDWARFLowLevel", ":IPO", ":IRPrinter", ":Instrumentation", @@ -3222,6 +3240,7 @@ cc_library( ":CodeGenTypes", ":DWARFLinkerBase", ":DebugInfoDWARF", + ":DebugInfoDWARFLowLevel", ":MC", ":Support", ":Target", @@ -3240,6 +3259,7 @@ cc_library( ":BinaryFormat", ":CodeGen", ":DebugInfoDWARF", + ":DebugInfoDWARFLowLevel", ":Support", ":Target", ], @@ -3540,6 +3560,7 @@ cc_library( ":DWARFLinkerParallel", ":DebugInfo", ":DebugInfoDWARF", + ":DebugInfoDWARFLowLevel", ":DsymutilTableGen", ":MC", ":Object", @@ -3957,6 +3978,7 @@ cc_binary( ":BinaryFormat", ":DebugInfo", ":DebugInfoDWARF", + ":DebugInfoDWARFLowLevel", ":MC", ":Object", ":Support", @@ -3988,6 +4010,7 @@ cc_binary( ":DWARFLinker", ":DWARFLinkerParallel", ":DebugInfoDWARF", + ":DebugInfoDWARFLowLevel", ":DwarfutilOptionsTableGen", ":MC", ":ObjCopy", @@ -4605,6 +4628,7 @@ cc_library( ":DebugInfo", ":DebugInfoBTF", ":DebugInfoDWARF", + ":DebugInfoDWARFLowLevel", ":Debuginfod", ":Demangle", ":MC", _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits