pfaffe updated this revision to Diff 477099.
pfaffe marked 2 inline comments as done.
pfaffe added a comment.

Override new functions in DWOs.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D137247/new/

https://reviews.llvm.org/D137247

Files:
  lldb/include/lldb/Expression/DWARFExpression.h
  lldb/source/Expression/DWARFExpression.cpp
  lldb/source/Expression/DWARFExpressionList.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
  lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
  lldb/unittests/Expression/DWARFExpressionTest.cpp

Index: lldb/unittests/Expression/DWARFExpressionTest.cpp
===================================================================
--- lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ lldb/unittests/Expression/DWARFExpressionTest.cpp
@@ -9,9 +9,11 @@
 #include "lldb/Expression/DWARFExpression.h"
 #include "Plugins/Platform/Linux/PlatformLinux.h"
 #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
 #include "TestingSupport/Symbol/YAMLModuleTester.h"
 #include "lldb/Core/Debugger.h"
+#include "lldb/Core/PluginManager.h"
 #include "lldb/Core/Value.h"
 #include "lldb/Core/dwarf.h"
 #include "lldb/Host/HostInfo.h"
@@ -514,3 +516,242 @@
   ASSERT_EQ(result.GetValueType(), Value::ValueType::LoadAddress);
   ASSERT_EQ(result.GetScalar().UInt(), 0x5678u);
 }
+
+class CustomSymbolFileDWARF : public SymbolFileDWARF {
+  static char ID;
+
+public:
+  using SymbolFileDWARF::SymbolFileDWARF;
+
+  bool isA(const void *ClassID) const override {
+    return ClassID == &ID || SymbolFile::isA(ClassID);
+  }
+  static bool classof(const SymbolFile *obj) { return obj->isA(&ID); }
+
+  static llvm::StringRef GetPluginNameStatic() { return "custom_dwarf"; }
+
+  static llvm::StringRef GetPluginDescriptionStatic() {
+    return "Symbol file reader with expression extensions.";
+  }
+
+  static void Initialize() {
+    PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                  GetPluginDescriptionStatic(), CreateInstance,
+                                  SymbolFileDWARF::DebuggerInitialize);
+  }
+
+  static void Terminate() { PluginManager::UnregisterPlugin(CreateInstance); }
+
+  static lldb_private::SymbolFile *
+  CreateInstance(lldb::ObjectFileSP objfile_sp) {
+    return new CustomSymbolFileDWARF(std::move(objfile_sp),
+                                     /*dwo_section_list*/ nullptr);
+  }
+
+  lldb::offset_t
+  GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data,
+                           const lldb::offset_t data_offset,
+                           const uint8_t op) const final {
+    auto offset = data_offset;
+    if (op != DW_OP_WASM_location) {
+      return LLDB_INVALID_OFFSET;
+    }
+
+    // DW_OP_WASM_location WASM_GLOBAL:0x03 index:u32
+    // Called with "arguments" 0x03 and 0x04
+    // Location type:
+    if (data.GetU8(&offset) != /* global */ 0x03) {
+      return LLDB_INVALID_OFFSET;
+    }
+
+    // Index
+    if (data.GetU32(&offset) != 0x04) {
+      return LLDB_INVALID_OFFSET;
+    }
+
+    // Report the skipped distance:
+    return offset - data_offset;
+  }
+
+  bool
+  ParseVendorDWARFOpcode(uint8_t op, const lldb_private::DataExtractor &opcodes,
+                         lldb::offset_t &offset,
+                         std::vector<lldb_private::Value> &stack) const final {
+    if (op != DW_OP_WASM_location) {
+      return false;
+    }
+
+    // DW_OP_WASM_location WASM_GLOBAL:0x03 index:u32
+    // Called with "arguments" 0x03 and  0x04
+    // Location type:
+    if (opcodes.GetU8(&offset) != /* global */ 0x03) {
+      return false;
+    }
+
+    // Index:
+    if (opcodes.GetU32(&offset) != 0x04) {
+      return false;
+    }
+
+    // Return some value:
+    stack.push_back({GetScalar(32, 42, false)});
+    return true;
+  }
+};
+
+char CustomSymbolFileDWARF::ID;
+
+static auto testExpressionVendorExtensions(lldb::ModuleSP module_sp,
+                                           DWARFUnit &dwarf_unit) {
+  // Test that expression extensions can be evaluated, for example
+  // DW_OP_WASM_location which is not currently handled by DWARFExpression:
+  EXPECT_THAT_EXPECTED(Evaluate({DW_OP_WASM_location, 0x03, // WASM_GLOBAL:0x03
+                                 0x04, 0x00, 0x00,          // index:u32
+                                 0x00, DW_OP_stack_value},
+                                module_sp, &dwarf_unit),
+                       llvm::HasValue(GetScalar(32, 42, false)));
+
+  // Test that searches for opcodes work in the presence of extensions:
+  uint8_t expr[] = {DW_OP_WASM_location,   0x03, 0x04, 0x00, 0x00, 0x00,
+                    DW_OP_form_tls_address};
+  DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle,
+                          /*addr_size*/ 4);
+  DWARFExpression dwarf_expr(extractor);
+  ASSERT_TRUE(dwarf_expr.ContainsThreadLocalStorage(&dwarf_unit));
+}
+
+TEST(DWARFExpression, Extensions) {
+  const char *yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_386
+DWARF:
+  debug_abbrev:
+    - Table:
+        - Code:            0x00000001
+          Tag:             DW_TAG_compile_unit
+          Children:        DW_CHILDREN_no
+  debug_info:
+    - Version:         4
+      AddrSize:        4
+      Entries:
+        - AbbrCode:        0x1
+        - AbbrCode:        0x0
+)";
+
+  SubsystemRAII<FileSystem, HostInfo, TypeSystemClang, ObjectFileELF,
+                CustomSymbolFileDWARF>
+      subsystems;
+
+  llvm::Expected<TestFile> file = TestFile::fromYaml(yamldata);
+  EXPECT_THAT_EXPECTED(file, llvm::Succeeded());
+
+  auto module_sp = std::make_shared<Module>(file->moduleSpec());
+  auto &symfile =
+      *llvm::cast<CustomSymbolFileDWARF>(module_sp->GetSymbolFile());
+  auto *dwarf_unit = symfile.DebugInfo().GetUnitAtIndex(0);
+
+  testExpressionVendorExtensions(module_sp, *dwarf_unit);
+}
+
+TEST(DWARFExpression, ExtensionsDWO) {
+  const char *skeleton_yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_EXEC
+  Machine: EM_386
+DWARF:
+  debug_abbrev:
+    - Table:
+        - Code:            0x00000001
+          Tag:             DW_TAG_skeleton_unit
+          Children:        DW_CHILDREN_no
+          Attributes:
+            - Attribute:       DW_AT_dwo_name
+              Form:            DW_FORM_string
+            - Attribute:       DW_AT_dwo_id
+              Form:            DW_FORM_data4
+  debug_info:
+    - Version:         4
+      AddrSize:        4
+      Entries:
+        - AbbrCode:        0x1
+          Values:
+            - CStr:           "dwo_unit"
+            - Value:           0x01020304
+        - AbbrCode:        0x0
+)";
+
+  // .dwo sections aren't currently supported by dwarfyaml. The dwo_yamldata
+  // contents where generated by roundtripping the following yaml through
+  // yaml2obj | obj2yaml and renaming the sections. This works because the
+  // structure of the .dwo and non-.dwo sections is identical.
+  //
+  // --- !ELF
+  // FileHeader:
+  //   Class:   ELFCLASS64
+  //   Data:    ELFDATA2LSB
+  //   Type:    ET_EXEC
+  //   Machine: EM_386
+  // DWARF:
+  //   debug_abbrev: #.dwo
+  //     - Table:
+  //         - Code:            0x00000001
+  //           Tag:             DW_TAG_compile_unit
+  //           Children:        DW_CHILDREN_no
+  //           Attributes:
+  //             - Attribute:       DW_AT_dwo_id
+  //               Form:            DW_FORM_data4
+  //   debug_info: #.dwo
+  //     - Version:         4
+  //       AddrSize:        4
+  //       Entries:
+  //         - AbbrCode:        0x1
+  //           Values:
+  //             - Value:           0x01020304
+  //         - AbbrCode:        0x0
+  const char *dwo_yamldata = R"(
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_386
+Sections:
+  - Name:            .debug_abbrev.dwo
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x1
+    Content:         '0111007506000000'
+  - Name:            .debug_info.dwo
+    Type:            SHT_PROGBITS
+    AddressAlign:    0x1
+    Content:         0D00000004000000000004010403020100
+)";
+
+  SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, CustomSymbolFileDWARF>
+      subsystems;
+
+  llvm::Expected<TestFile> skeleton_file =
+      TestFile::fromYaml(skeleton_yamldata);
+  EXPECT_THAT_EXPECTED(skeleton_file, llvm::Succeeded());
+  llvm::Expected<TestFile> dwo_file = TestFile::fromYaml(dwo_yamldata);
+  EXPECT_THAT_EXPECTED(dwo_file, llvm::Succeeded());
+
+  auto skeleton_module_sp =
+      std::make_shared<Module>(skeleton_file->moduleSpec());
+  auto &skeleton_symfile =
+      *llvm::cast<CustomSymbolFileDWARF>(skeleton_module_sp->GetSymbolFile());
+
+  auto dwo_module_sp = std::make_shared<Module>(dwo_file->moduleSpec());
+  SymbolFileDWARFDwo dwo_symfile(
+      skeleton_symfile, dwo_module_sp->GetObjectFile()->shared_from_this(),
+      0x01020304);
+  auto *dwo_dwarf_unit = dwo_symfile.DebugInfo().GetUnitAtIndex(0);
+
+  testExpressionVendorExtensions(dwo_module_sp, *dwo_dwarf_unit);
+}
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -42,6 +42,16 @@
 
   llvm::Optional<uint32_t> GetDwoNum() override { return GetID() >> 32; }
 
+  lldb::offset_t
+  GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data,
+                           const lldb::offset_t data_offset,
+                           const uint8_t op) const override;
+
+  bool ParseVendorDWARFOpcode(
+      uint8_t op, const lldb_private::DataExtractor &opcodes,
+      lldb::offset_t &offset,
+      std::vector<lldb_private::Value> &stack) const override;
+
 protected:
   DIEToTypePtr &GetDIEToType() override;
 
@@ -60,7 +70,7 @@
       const DWARFDIE &die, lldb_private::ConstString type_name,
       bool must_be_implementation) override;
 
-  SymbolFileDWARF &GetBaseSymbolFile() { return m_base_symbol_file; }
+  SymbolFileDWARF &GetBaseSymbolFile() const { return m_base_symbol_file; }
 
   /// If this file contains exactly one compile unit, this function will return
   /// it. Otherwise it returns nullptr.
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -77,6 +77,18 @@
   return cu;
 }
 
+lldb::offset_t SymbolFileDWARFDwo::GetVendorDWARFOpcodeSize(
+    const lldb_private::DataExtractor &data, const lldb::offset_t data_offset,
+    const uint8_t op) const {
+  return GetBaseSymbolFile().GetVendorDWARFOpcodeSize(data, data_offset, op);
+}
+
+bool SymbolFileDWARFDwo::ParseVendorDWARFOpcode(
+    uint8_t op, const lldb_private::DataExtractor &opcodes,
+    lldb::offset_t &offset, std::vector<lldb_private::Value> &stack) const {
+  return GetBaseSymbolFile().ParseVendorDWARFOpcode(op, opcodes, offset, stack);
+}
+
 SymbolFileDWARF::DIEToTypePtr &SymbolFileDWARFDwo::GetDIEToType() {
   return GetBaseSymbolFile().GetDIEToType();
 }
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -331,6 +331,20 @@
     return m_parse_time;
   }
 
+  virtual lldb::offset_t
+  GetVendorDWARFOpcodeSize(const lldb_private::DataExtractor &data,
+                           const lldb::offset_t data_offset,
+                           const uint8_t op) const {
+    return LLDB_INVALID_OFFSET;
+  }
+
+  virtual bool
+  ParseVendorDWARFOpcode(uint8_t op, const lldb_private::DataExtractor &opcodes,
+                         lldb::offset_t &offset,
+                         std::vector<lldb_private::Value> &stack) const {
+    return false;
+  }
+
   lldb_private::ConstString ConstructFunctionDemangledName(const DWARFDIE &die);
 
 protected:
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3466,7 +3466,8 @@
                   if (exe_file_addr != LLDB_INVALID_ADDRESS) {
                     DWARFExpression *location =
                         location_list.GetMutableExpressionAtAddress();
-                    if (location->Update_DW_OP_addr(exe_file_addr)) {
+                    if (location->Update_DW_OP_addr(die.GetCU(),
+                                                    exe_file_addr)) {
                       linked_oso_file_addr = true;
                       symbol_context_scope = exe_symbol;
                     }
@@ -3486,7 +3487,7 @@
             // Update the file address for this variable
             DWARFExpression *location =
                 location_list.GetMutableExpressionAtAddress();
-            location->Update_DW_OP_addr(exe_file_addr);
+            location->Update_DW_OP_addr(die.GetCU(), exe_file_addr);
           } else {
             // Variable didn't make it into the final executable
             return nullptr;
Index: lldb/source/Expression/DWARFExpressionList.cpp
===================================================================
--- lldb/source/Expression/DWARFExpressionList.cpp
+++ lldb/source/Expression/DWARFExpressionList.cpp
@@ -90,7 +90,7 @@
     return false;
 
   const DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
-  return expr.ContainsThreadLocalStorage();
+  return expr.ContainsThreadLocalStorage(m_dwarf_cu);
 }
 
 bool DWARFExpressionList::LinkThreadLocalStorage(
@@ -107,7 +107,7 @@
   // If we linked the TLS address correctly, update the module so that when the
   // expression is evaluated it can resolve the file address to a load address
   // and read the TLS data
-  if (expr.LinkThreadLocalStorage(link_address_callback))
+  if (expr.LinkThreadLocalStorage(m_dwarf_cu, link_address_callback))
     m_module_wp = new_module_sp;
   return true;
 }
Index: lldb/source/Expression/DWARFExpression.cpp
===================================================================
--- lldb/source/Expression/DWARFExpression.cpp
+++ lldb/source/Expression/DWARFExpression.cpp
@@ -38,8 +38,10 @@
 #include "lldb/Target/Thread.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
 #include "llvm/DebugInfo/DWARF/DWARFExpression.h"
+#include "llvm/Support/Casting.h"
 
 #include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
+#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -131,7 +133,7 @@
 /// are made on the state of \p data after this call.
 static offset_t GetOpcodeDataSize(const DataExtractor &data,
                                   const lldb::offset_t data_offset,
-                                  const uint8_t op) {
+                                  const uint8_t op, const DWARFUnit *dwarf_cu) {
   lldb::offset_t offset = data_offset;
   switch (op) {
   case DW_OP_addr:
@@ -333,9 +335,12 @@
   }
 
   default:
-    break;
+    if (!dwarf_cu) {
+      return LLDB_INVALID_OFFSET;
+    }
+    return dwarf_cu->GetSymbolFileDWARF().GetVendorDWARFOpcodeSize(
+        data, data_offset, op);
   }
-  return LLDB_INVALID_OFFSET;
 }
 
 lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu,
@@ -364,7 +369,8 @@
       }
       ++curr_op_addr_idx;
     } else {
-      const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
+      const offset_t op_arg_size =
+          GetOpcodeDataSize(m_data, offset, op, dwarf_cu);
       if (op_arg_size == LLDB_INVALID_OFFSET) {
         error = true;
         break;
@@ -375,7 +381,8 @@
   return LLDB_INVALID_ADDRESS;
 }
 
-bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
+bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu,
+                                        lldb::addr_t file_addr) {
   lldb::offset_t offset = 0;
   while (m_data.ValidOffset(offset)) {
     const uint8_t op = m_data.GetU8(&offset);
@@ -402,7 +409,8 @@
       m_data.SetData(encoder.GetDataBuffer());
       return true;
     } else {
-      const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
+      const offset_t op_arg_size =
+          GetOpcodeDataSize(m_data, offset, op, dwarf_cu);
       if (op_arg_size == LLDB_INVALID_OFFSET)
         break;
       offset += op_arg_size;
@@ -411,14 +419,16 @@
   return false;
 }
 
-bool DWARFExpression::ContainsThreadLocalStorage() const {
+bool DWARFExpression::ContainsThreadLocalStorage(
+    const DWARFUnit *dwarf_cu) const {
   lldb::offset_t offset = 0;
   while (m_data.ValidOffset(offset)) {
     const uint8_t op = m_data.GetU8(&offset);
 
     if (op == DW_OP_form_tls_address || op == DW_OP_GNU_push_tls_address)
       return true;
-    const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
+    const offset_t op_arg_size =
+        GetOpcodeDataSize(m_data, offset, op, dwarf_cu);
     if (op_arg_size == LLDB_INVALID_OFFSET)
       return false;
     offset += op_arg_size;
@@ -426,6 +436,7 @@
   return false;
 }
 bool DWARFExpression::LinkThreadLocalStorage(
+    const DWARFUnit *dwarf_cu,
     std::function<lldb::addr_t(lldb::addr_t file_addr)> const
         &link_address_callback) {
   const uint32_t addr_byte_size = m_data.GetAddressByteSize();
@@ -496,7 +507,8 @@
     }
 
     if (!decoded_data) {
-      const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
+      const offset_t op_arg_size =
+          GetOpcodeDataSize(m_data, offset, op, dwarf_cu);
       if (op_arg_size == LLDB_INVALID_OFFSET)
         return false;
       else
@@ -2557,6 +2569,12 @@
     }
 
     default:
+      if (dwarf_cu) {
+        if (dwarf_cu->GetSymbolFileDWARF().ParseVendorDWARFOpcode(
+                op, opcodes, offset, stack)) {
+          break;
+        }
+      }
       if (error_ptr)
         error_ptr->SetErrorStringWithFormatv(
             "Unhandled opcode {0} in DWARFExpression", LocationAtom(op));
Index: lldb/include/lldb/Expression/DWARFExpression.h
===================================================================
--- lldb/include/lldb/Expression/DWARFExpression.h
+++ lldb/include/lldb/Expression/DWARFExpression.h
@@ -75,14 +75,15 @@
   lldb::addr_t GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu,
                                       uint32_t op_addr_idx, bool &error) const;
 
-  bool Update_DW_OP_addr(lldb::addr_t file_addr);
+  bool Update_DW_OP_addr(const DWARFUnit *dwarf_cu, lldb::addr_t file_addr);
 
   void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size,
                    uint8_t addr_byte_size);
 
-  bool ContainsThreadLocalStorage() const;
+  bool ContainsThreadLocalStorage(const DWARFUnit *dwarf_cu) const;
 
   bool LinkThreadLocalStorage(
+      const DWARFUnit *dwarf_cu,
       std::function<lldb::addr_t(lldb::addr_t file_addr)> const
           &link_address_callback);
 
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to