]> granicus.if.org Git - llvm/commitdiff
[DebugInfo] Prep llvm-dwarfdump for typed DW5 ops.
authorMarkus Lavin <markus.lavin@ericsson.com>
Thu, 21 Feb 2019 08:20:24 +0000 (08:20 +0000)
committerMarkus Lavin <markus.lavin@ericsson.com>
Thu, 21 Feb 2019 08:20:24 +0000 (08:20 +0000)
Adds llvm-dwarfdump support for pretty printing Dwarf5 expressions ops
that reference a base type (right now only DW_OP_convert is added).
Includes verification to verify that the ops operand is actually a
DW_TAG_base_type DIE.

Differential Revision: https://reviews.llvm.org/D58442

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354552 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/DebugInfo/DWARF/DWARFDebugLoc.h
include/llvm/DebugInfo/DWARF/DWARFExpression.h
lib/DebugInfo/DWARF/DWARFDebugFrame.cpp
lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
lib/DebugInfo/DWARF/DWARFDie.cpp
lib/DebugInfo/DWARF/DWARFExpression.cpp
lib/DebugInfo/DWARF/DWARFVerifier.cpp
test/tools/llvm-dwarfdump/X86/debug_expr_convert.s [new file with mode: 0644]

index dbed95944326e919b5880650d51b26e8e7176129..54ceb450a8deadc93e03ad305d33e9f0423a1740 100644 (file)
@@ -41,7 +41,7 @@ public:
     SmallVector<Entry, 2> Entries;
     /// Dump this list on OS.
     void dump(raw_ostream &OS, bool IsLittleEndian, unsigned AddressSize,
-              const MCRegisterInfo *MRI, uint64_t BaseAddress,
+              const MCRegisterInfo *MRI, DWARFUnit *U, uint64_t BaseAddress,
               unsigned Indent) const;
   };
 
index 8049094cc16fef251130cf45a94ee98386d53ece..00ade7a3eddf6195906176abb53f1d9ef8051ee0 100644 (file)
@@ -41,7 +41,8 @@ public:
       SizeAddr = 5,
       SizeRefAddr = 6,
       SizeBlock = 7, ///< Preceding operand contains block size
-      SignBit = 0x8,
+      BaseTypeRef = 8,
+      SignBit = 0x80,
       SignedSize1 = SignBit | Size1,
       SignedSize2 = SignBit | Size2,
       SignedSize4 = SignBit | Size4,
@@ -54,7 +55,8 @@ public:
       DwarfNA, ///< Serves as a marker for unused entries
       Dwarf2 = 2,
       Dwarf3,
-      Dwarf4
+      Dwarf4,
+      Dwarf5
     };
 
     /// Description of the encoding of one expression Op.
@@ -86,8 +88,9 @@ public:
     bool extract(DataExtractor Data, uint16_t Version, uint8_t AddressSize,
                  uint32_t Offset);
     bool isError() { return Error; }
-    bool print(raw_ostream &OS, const DWARFExpression *U,
-               const MCRegisterInfo *RegInfo, bool isEH);
+    bool print(raw_ostream &OS, const DWARFExpression *Expr,
+               const MCRegisterInfo *RegInfo, DWARFUnit *U, bool isEH);
+    bool verify(DWARFUnit *U);
   };
 
   /// An iterator to go through the expression operations.
@@ -130,9 +133,11 @@ public:
   iterator begin() const { return iterator(this, 0); }
   iterator end() const { return iterator(this, Data.getData().size()); }
 
-  void print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
+  void print(raw_ostream &OS, const MCRegisterInfo *RegInfo, DWARFUnit *U,
              bool IsEH = false) const;
 
+  bool verify(DWARFUnit *U);
+
 private:
   DataExtractor Data;
   uint16_t Version;
index 154e466e91113427aca1f817ada8d838c5af3f18..c112d2be12a996397ccb52bd99ab50745e80de5b 100644 (file)
@@ -266,7 +266,7 @@ void CFIProgram::printOperand(raw_ostream &OS, const MCRegisterInfo *MRI,
   case OT_Expression:
     assert(Instr.Expression && "missing DWARFExpression object");
     OS << " ";
-    Instr.Expression->print(OS, MRI, IsEH);
+    Instr.Expression->print(OS, MRI, nullptr, IsEH);
     break;
   }
 }
index 54e0e8e18fab0d211b05f2da322035a2d3c29fcc..366b4df66579efb3856f4b86ef1efc775088582b 100644 (file)
@@ -30,15 +30,16 @@ using namespace llvm;
 // non-LLVM tools.
 static void dumpExpression(raw_ostream &OS, ArrayRef<char> Data,
                            bool IsLittleEndian, unsigned AddressSize,
-                           const MCRegisterInfo *MRI) {
+                           const MCRegisterInfo *MRI, DWARFUnit *U) {
   DWARFDataExtractor Extractor(StringRef(Data.data(), Data.size()),
                                IsLittleEndian, AddressSize);
-  DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI);
+  DWARFExpression(Extractor, dwarf::DWARF_VERSION, AddressSize).print(OS, MRI, U);
 }
 
 void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
                                        unsigned AddressSize,
                                        const MCRegisterInfo *MRI,
+                                       DWARFUnit *U,
                                        uint64_t BaseAddress,
                                        unsigned Indent) const {
   for (const Entry &E : Entries) {
@@ -50,7 +51,7 @@ void DWARFDebugLoc::LocationList::dump(raw_ostream &OS, bool IsLittleEndian,
                  BaseAddress + E.End);
     OS << ": ";
 
-    dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
+    dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, U);
   }
 }
 
@@ -68,7 +69,7 @@ void DWARFDebugLoc::dump(raw_ostream &OS, const MCRegisterInfo *MRI,
                          Optional<uint64_t> Offset) const {
   auto DumpLocationList = [&](const LocationList &L) {
     OS << format("0x%8.8x: ", L.Offset);
-    L.dump(OS, IsLittleEndian, AddressSize, MRI, 0, 12);
+    L.dump(OS, IsLittleEndian, AddressSize, MRI, nullptr, 0, 12);
     OS << "\n\n";
   };
 
@@ -253,7 +254,7 @@ void DWARFDebugLoclists::LocationList::dump(raw_ostream &OS, uint64_t BaseAddr,
       llvm_unreachable("unreachable locations list kind");
     }
 
-    dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI);
+    dumpExpression(OS, E.Loc, IsLittleEndian, AddressSize, MRI, nullptr);
   }
 }
 
index b1aa77d1f236d6e68a8c993a1ba11017b7099843..e8887780767387ebba93b64055334ddf6ec0e872 100644 (file)
@@ -86,7 +86,7 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
     DataExtractor Data(StringRef((const char *)Expr.data(), Expr.size()),
                        Ctx.isLittleEndian(), 0);
     DWARFExpression(Data, U->getVersion(), U->getAddressByteSize())
-        .print(OS, MRI);
+        .print(OS, MRI, U);
     return;
   }
 
@@ -102,8 +102,8 @@ static void dumpLocation(raw_ostream &OS, DWARFFormValue &FormValue,
         uint64_t BaseAddr = 0;
         if (Optional<SectionedAddress> BA = U->getBaseAddress())
           BaseAddr = BA->Address;
-        LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, BaseAddr,
-                 Indent);
+        LL->dump(OS, Ctx.isLittleEndian(), Obj.getAddressSize(), MRI, U,
+                 BaseAddr, Indent);
       } else
         OS << "error extracting location list.";
       return;
index 920fa183e4526b34811b5920c160f4394b1a27b6..24400ff89c6a90cd7ada5323bc51b360575ea51d 100644 (file)
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/BinaryFormat/Dwarf.h"
 #include "llvm/MC/MCRegisterInfo.h"
 #include "llvm/Support/Format.h"
@@ -96,6 +97,9 @@ static DescVector getDescriptions() {
   Descriptions[DW_OP_addrx] = Desc(Op::Dwarf4, Op::SizeLEB);
   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_convert] = Desc(Op::Dwarf5, Op::BaseTypeRef);
+
   return Descriptions;
 }
 
@@ -170,6 +174,9 @@ bool DWARFExpression::Operation::extract(DataExtractor Data, uint16_t Version,
       else
         Operands[Operand] = Data.getULEB128(&Offset);
       break;
+    case Operation::BaseTypeRef:
+      Operands[Operand] = Data.getULEB128(&Offset);
+      break;
     case Operation::SizeBlock:
       // We need a size, so this cannot be the first operand
       if (Operand == 0)
@@ -221,6 +228,7 @@ static bool prettyPrintRegisterOp(raw_ostream &OS, uint8_t Opcode,
 bool DWARFExpression::Operation::print(raw_ostream &OS,
                                        const DWARFExpression *Expr,
                                        const MCRegisterInfo *RegInfo,
+                                       DWARFUnit *U,
                                        bool isEH) {
   if (Error) {
     OS << "<decoding error>";
@@ -244,7 +252,17 @@ bool DWARFExpression::Operation::print(raw_ostream &OS,
     if (Size == Operation::SizeNA)
       break;
 
-    if (Size == Operation::SizeBlock) {
+    if (Size == Operation::BaseTypeRef && U) {
+      auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]);
+      if (Die && Die.getTag() == dwarf::DW_TAG_base_type) {
+        OS << format(" (0x%08x)", U->getOffset() + Operands[Operand]);
+        if (auto Name = Die.find(dwarf::DW_AT_name))
+          OS << " \"" << Name->getAsCString() << "\"";
+      } else {
+        OS << format(" <invalid base_type ref: 0x%" PRIx64 ">",
+                     Operands[Operand]);
+      }
+    } else if (Size == Operation::SizeBlock) {
       uint32_t Offset = Operands[Operand];
       for (unsigned i = 0; i < Operands[Operand - 1]; ++i)
         OS << format(" 0x%02x", Expr->Data.getU8(&Offset));
@@ -259,9 +277,9 @@ bool DWARFExpression::Operation::print(raw_ostream &OS,
 }
 
 void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
-                            bool IsEH) const {
+                            DWARFUnit *U, bool IsEH) const {
   for (auto &Op : *this) {
-    if (!Op.print(OS, this, RegInfo, IsEH)) {
+    if (!Op.print(OS, this, RegInfo, U, IsEH)) {
       uint32_t FailOffset = Op.getEndOffset();
       while (FailOffset < Data.getData().size())
         OS << format(" %02x", Data.getU8(&FailOffset));
@@ -272,4 +290,32 @@ void DWARFExpression::print(raw_ostream &OS, const MCRegisterInfo *RegInfo,
   }
 }
 
+bool DWARFExpression::Operation::verify(DWARFUnit *U) {
+
+  for (unsigned Operand = 0; Operand < 2; ++Operand) {
+    unsigned Size = Desc.Op[Operand];
+
+    if (Size == Operation::SizeNA)
+      break;
+
+    if (Size == Operation::BaseTypeRef) {
+      auto Die = U->getDIEForOffset(U->getOffset() + Operands[Operand]);
+      if (!Die || Die.getTag() != dwarf::DW_TAG_base_type) {
+        Error = true;
+        return false;
+      }
+    }
+  }
+
+  return true;
+}
+
+bool DWARFExpression::verify(DWARFUnit *U) {
+  for (auto &Op : *this)
+    if (!Op.verify(U))
+      return false;
+
+  return true;
+}
+
 } // namespace llvm
index 0eef0f6a82bf5a05fd04238c21b4f7fc7cbed106..2447708465a013e1faca4ea5587f4aea88f8fc4b 100644 (file)
@@ -502,7 +502,7 @@ unsigned DWARFVerifier::verifyDebugInfoAttribute(const DWARFDie &Die,
       bool Error = llvm::any_of(Expression, [](DWARFExpression::Operation &Op) {
         return Op.isError();
       });
-      if (Error)
+      if (Error || !Expression.verify(U))
         ReportError("DIE contains invalid DWARF expression:");
     };
     if (Optional<ArrayRef<uint8_t>> Expr = AttrValue.Value.getAsBlock()) {
diff --git a/test/tools/llvm-dwarfdump/X86/debug_expr_convert.s b/test/tools/llvm-dwarfdump/X86/debug_expr_convert.s
new file mode 100644 (file)
index 0000000..7f9058c
--- /dev/null
@@ -0,0 +1,124 @@
+# RUN: llvm-mc %s -filetype obj -triple x86_64-pc-linux -o %t.o
+# RUN: llvm-dwarfdump %t.o | FileCheck %s
+# RUN: not llvm-dwarfdump -verify %t.o
+
+# CHECK: DW_AT_location  (DW_OP_addr 0x{{[0-9a-f]+}}, DW_OP_convert <invalid base_type ref: 0x{{[0-9a-f]+}}>, DW_OP_convert (0x{{[0-9a-f]+}}) "DW_ATE_signed_32")
+
+       .text
+       .file   "dbg.g.c"
+       .file   1 "/tmp/dbg.g.c"
+       .type   global,@object          # @global
+       .data
+       .globl  global
+       .p2align        2
+global:
+       .long   255                     # 0xff
+       .size   global, 4
+
+       .section        .debug_str,"MS",@progbits,1
+.Linfo_string0:
+       .asciz  "clang version 9.0.0 (trunk 354265) (llvm/trunk 354264)" # string offset=0
+.Linfo_string1:
+       .asciz  "dbg.g.c"               # string offset=55
+.Linfo_string2:
+       .asciz  "/tmp"                  # string offset=63
+.Linfo_string3:
+       .asciz  "global"                # string offset=68
+.Linfo_string4:
+       .asciz  "int"                   # string offset=75
+.Linfo_string5:
+       .asciz  "DW_ATE_signed_32"      # string offset=79
+.Linfo_string6:
+       .asciz  "DW_ATE_signed_8"       # string offset=96
+       .section        .debug_abbrev,"",@progbits
+       .byte   1                       # Abbreviation Code
+       .byte   17                      # DW_TAG_compile_unit
+       .byte   1                       # DW_CHILDREN_yes
+       .byte   37                      # DW_AT_producer
+       .byte   14                      # DW_FORM_strp
+       .byte   19                      # DW_AT_language
+       .byte   5                       # DW_FORM_data2
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   16                      # DW_AT_stmt_list
+       .byte   23                      # DW_FORM_sec_offset
+       .byte   27                      # DW_AT_comp_dir
+       .byte   14                      # DW_FORM_strp
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   2                       # Abbreviation Code
+       .byte   36                      # DW_TAG_base_type
+       .byte   0                       # DW_CHILDREN_no
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   62                      # DW_AT_encoding
+       .byte   11                      # DW_FORM_data1
+       .byte   11                      # DW_AT_byte_size
+       .byte   11                      # DW_FORM_data1
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   3                       # Abbreviation Code
+       .byte   52                      # DW_TAG_variable
+       .byte   0                       # DW_CHILDREN_no
+       .byte   3                       # DW_AT_name
+       .byte   14                      # DW_FORM_strp
+       .byte   73                      # DW_AT_type
+       .byte   19                      # DW_FORM_ref4
+       .byte   63                      # DW_AT_external
+       .byte   25                      # DW_FORM_flag_present
+       .byte   58                      # DW_AT_decl_file
+       .byte   11                      # DW_FORM_data1
+       .byte   59                      # DW_AT_decl_line
+       .byte   11                      # DW_FORM_data1
+       .byte   2                       # DW_AT_location
+       .byte   24                      # DW_FORM_exprloc
+       .byte   0                       # EOM(1)
+       .byte   0                       # EOM(2)
+       .byte   0                       # EOM(3)
+       .section        .debug_info,"",@progbits
+.Lcu_begin0:
+       .long   .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
+.Ldebug_info_start0:
+       .short  4                       # DWARF version number
+       .long   .debug_abbrev           # Offset Into Abbrev. Section
+       .byte   8                       # Address Size (in bytes)
+       .byte   1                       # Abbrev [1] 0xb:0x48 DW_TAG_compile_unit
+       .long   .Linfo_string0          # DW_AT_producer
+       .short  12                      # DW_AT_language
+       .long   .Linfo_string1          # DW_AT_name
+       .long   .Lline_table_start0     # DW_AT_stmt_list
+       .long   .Linfo_string2          # DW_AT_comp_dir
+       .byte   2                       # Abbrev [2] 0x1e:0x7 DW_TAG_base_type
+       .long   .Linfo_string6          # DW_AT_name
+       .byte   5                       # DW_AT_encoding
+       .byte   1                       # DW_AT_byte_size
+       .byte   2                       # Abbrev [2] 0x25:0x7 DW_TAG_base_type
+       .long   .Linfo_string5          # DW_AT_name
+       .byte   5                       # DW_AT_encoding
+       .byte   4                       # DW_AT_byte_size
+       .byte   3                       # Abbrev [3] 0x2c:0x1f DW_TAG_variable
+       .long   .Linfo_string3          # DW_AT_name
+       .long   75                      # DW_AT_type
+                                        # DW_AT_external
+       .byte   1                       # DW_AT_decl_file
+       .byte   1                       # DW_AT_decl_line
+       .byte   19                      # DW_AT_location
+       .byte   3
+       .quad   global
+       .byte   168
+       .asciz  "\235\200\200"  ### This offset is off by one to test the invalid base_type ref printout
+       .byte   168
+       .asciz  "\245\200\200"
+       .byte   2                       # Abbrev [2] 0x4b:0x7 DW_TAG_base_type
+       .long   .Linfo_string4          # DW_AT_name
+       .byte   5                       # DW_AT_encoding
+       .byte   4                       # DW_AT_byte_size
+       .byte   0                       # End Of Children Mark
+.Ldebug_info_end0:
+       .section        .debug_macinfo,"",@progbits
+       .byte   0                       # End Of Macro List Mark
+
+       .ident  "clang version 9.0.0 (trunk 354265) (llvm/trunk 354264)"
+       .section        ".note.GNU-stack","",@progbits
+       .section        .debug_line,"",@progbits
+.Lline_table_start0: