[Lldb-commits] [lldb] c08d3b0 - [lldb] Allow plugins to extend DWARF expression parsing for vendor extensions

Philip Pfaffe via lldb-commits lldb-commits at lists.llvm.org
Tue Nov 22 06:38:46 PST 2022


Author: Philip Pfaffe
Date: 2022-11-22T14:38:07Z
New Revision: c08d3b08f6d71e974537de226c68d4c94c396a46

URL: https://github.com/llvm/llvm-project/commit/c08d3b08f6d71e974537de226c68d4c94c396a46
DIFF: https://github.com/llvm/llvm-project/commit/c08d3b08f6d71e974537de226c68d4c94c396a46.diff

LOG: [lldb] Allow plugins to extend DWARF expression parsing for vendor extensions

Parsing DWARF expressions currently does not support DW_OPs that are vendor
extensions. With this change expression parsing calls into SymbolFileDWARF for
unknown opcodes, which is the semantically "closest" plugin that we have right
now. Plugins can then extend SymbolFileDWARF to add support for vendor
extensions.

Reviewed By: labath

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

Added: 
    

Modified: 
    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

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h
index 49e51d51f211c..aea41926d848d 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -75,14 +75,15 @@ class DWARFExpression {
   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);
 

diff  --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 3c36587f63115..9e7df2d3b82ef 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -131,7 +131,7 @@ static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
 /// 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 +333,12 @@ static offset_t GetOpcodeDataSize(const DataExtractor &data,
   }
 
   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 +367,8 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu,
       }
       ++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 +379,8 @@ lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu,
   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 +407,8 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
       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 +417,16 @@ bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
   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 +434,7 @@ bool DWARFExpression::ContainsThreadLocalStorage() const {
   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 +505,8 @@ bool DWARFExpression::LinkThreadLocalStorage(
     }
 
     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
@@ -2556,6 +2566,12 @@ bool DWARFExpression::Evaluate(
     }
 
     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));

diff  --git a/lldb/source/Expression/DWARFExpressionList.cpp b/lldb/source/Expression/DWARFExpressionList.cpp
index 5cf722c42fa91..cba4e4e5858ac 100644
--- a/lldb/source/Expression/DWARFExpressionList.cpp
+++ b/lldb/source/Expression/DWARFExpressionList.cpp
@@ -90,7 +90,7 @@ bool DWARFExpressionList::ContainsThreadLocalStorage() const {
     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 @@ bool DWARFExpressionList::LinkThreadLocalStorage(
   // 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;
 }

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 2447f93411e04..fef2a36384703 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -3492,7 +3492,8 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
                   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;
                     }
@@ -3512,7 +3513,7 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
             // 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;

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 410a95ddab5c1..8926ab8203d70 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -330,6 +330,20 @@ class SymbolFileDWARF : public lldb_private::SymbolFileCommon,
     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:

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
index f0b0864fb1272..f891ccc453ed7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp
@@ -77,6 +77,18 @@ DWARFCompileUnit *SymbolFileDWARFDwo::FindSingleCompileUnit() {
   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();
 }

diff  --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
index c8501037372b6..9da6e63ab7193 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h
@@ -42,6 +42,16 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
 
   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 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF {
       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.

diff  --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp
index 4251eb0aecda9..942426e4345eb 100644
--- a/lldb/unittests/Expression/DWARFExpressionTest.cpp
+++ b/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 @@ TEST_F(DWARFExpressionMockProcessTest, WASM_DW_OP_addr_index) {
   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);
+}


        


More information about the lldb-commits mailing list