[Lldb-commits] [lldb] c112190 - [LLDB] Add DynamicLoaderWasmDYLD plugin for WebAssembly debugging

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Mon Feb 17 03:49:10 PST 2020


Author: Paolo Severini
Date: 2020-02-17T12:42:23+01:00
New Revision: c1121908aace019b3e31e24def58a21a978531cd

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

LOG: [LLDB] Add DynamicLoaderWasmDYLD plugin for WebAssembly debugging

Add a dynamic loader plug-in class for WebAssembly modules.

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

Added: 
    lldb/source/Plugins/DynamicLoader/wasm-DYLD/CMakeLists.txt
    lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
    lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.h
    lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
    lldb/test/API/functionalities/gdb_remote_client/test_sym.yaml
    lldb/test/API/functionalities/gdb_remote_client/test_wasm_embedded_debug_sections.yaml
    lldb/test/API/functionalities/gdb_remote_client/test_wasm_external_debug_sections.yaml

Modified: 
    lldb/source/API/SystemInitializerFull.cpp
    lldb/source/Plugins/DynamicLoader/CMakeLists.txt
    lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
    lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
    lldb/test/Shell/ObjectFile/wasm/basic.yaml
    lldb/test/Shell/ObjectFile/wasm/embedded-debug-sections.yaml
    lldb/test/Shell/ObjectFile/wasm/stripped-debug-sections.yaml
    lldb/test/Shell/ObjectFile/wasm/unified-debug-sections.yaml
    lldb/tools/lldb-test/SystemInitializerTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp
index 7e2d80fceec8..9f68fc7e88c5 100644
--- a/lldb/source/API/SystemInitializerFull.cpp
+++ b/lldb/source/API/SystemInitializerFull.cpp
@@ -105,6 +105,7 @@ LLDB_PLUGIN_DECLARE(ProcessGDBRemote)
 LLDB_PLUGIN_DECLARE(DynamicLoaderMacOSXDYLD)
 LLDB_PLUGIN_DECLARE(DynamicLoaderPOSIXDYLD)
 LLDB_PLUGIN_DECLARE(DynamicLoaderStatic)
+LLDB_PLUGIN_DECLARE(DynamicLoaderWasmDYLD)
 LLDB_PLUGIN_DECLARE(DynamicLoaderWindowsDYLD)
 
 using namespace lldb_private;
@@ -240,6 +241,7 @@ llvm::Error SystemInitializerFull::Initialize() {
   LLDB_PLUGIN_INITIALIZE(ProcessGDBRemote);
   LLDB_PLUGIN_INITIALIZE(DynamicLoaderMacOSXDYLD);
   LLDB_PLUGIN_INITIALIZE(DynamicLoaderPOSIXDYLD);
+  LLDB_PLUGIN_INITIALIZE(DynamicLoaderWasmDYLD); // Before DynamicLoaderStatic.
   LLDB_PLUGIN_INITIALIZE(DynamicLoaderStatic);
   LLDB_PLUGIN_INITIALIZE(DynamicLoaderWindowsDYLD);
 
@@ -327,6 +329,7 @@ void SystemInitializerFull::Terminate() {
 
   LLDB_PLUGIN_TERMINATE(DynamicLoaderMacOSXDYLD);
   LLDB_PLUGIN_TERMINATE(DynamicLoaderPOSIXDYLD);
+  LLDB_PLUGIN_TERMINATE(DynamicLoaderWasmDYLD);
   LLDB_PLUGIN_TERMINATE(DynamicLoaderStatic);
   LLDB_PLUGIN_TERMINATE(DynamicLoaderWindowsDYLD);
 

diff  --git a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt
index 9f3b2ab0e50f..f357fea02efb 100644
--- a/lldb/source/Plugins/DynamicLoader/CMakeLists.txt
+++ b/lldb/source/Plugins/DynamicLoader/CMakeLists.txt
@@ -4,3 +4,4 @@ add_subdirectory(POSIX-DYLD)
 add_subdirectory(Static)
 add_subdirectory(Hexagon-DYLD)
 add_subdirectory(Windows-DYLD)
+add_subdirectory(wasm-DYLD)

diff  --git a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/CMakeLists.txt b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/CMakeLists.txt
new file mode 100644
index 000000000000..a4a4ac7b44e7
--- /dev/null
+++ b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_lldb_library(lldbPluginDynamicLoaderWasmDYLD PLUGIN
+  DynamicLoaderWasmDYLD.cpp
+
+  LINK_LIBS
+    lldbCore
+    lldbTarget
+  LINK_COMPONENTS
+    Support
+  )

diff  --git a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
new file mode 100644
index 000000000000..ae7e011eaa52
--- /dev/null
+++ b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.cpp
@@ -0,0 +1,70 @@
+//===-- DynamicLoaderWasmDYLD.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 "DynamicLoaderWasmDYLD.h"
+
+#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Target/Process.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/Log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::wasm;
+
+LLDB_PLUGIN_DEFINE(DynamicLoaderWasmDYLD)
+
+DynamicLoaderWasmDYLD::DynamicLoaderWasmDYLD(Process *process)
+    : DynamicLoader(process) {}
+
+void DynamicLoaderWasmDYLD::Initialize() {
+  PluginManager::RegisterPlugin(GetPluginNameStatic(),
+                                GetPluginDescriptionStatic(), CreateInstance);
+}
+
+ConstString DynamicLoaderWasmDYLD::GetPluginNameStatic() {
+  static ConstString g_plugin_name("wasm-dyld");
+  return g_plugin_name;
+}
+
+const char *DynamicLoaderWasmDYLD::GetPluginDescriptionStatic() {
+  return "Dynamic loader plug-in that watches for shared library "
+         "loads/unloads in WebAssembly engines.";
+}
+
+DynamicLoader *DynamicLoaderWasmDYLD::CreateInstance(Process *process,
+                                                     bool force) {
+  bool should_create = force;
+  if (!should_create) {
+    should_create =
+        (process->GetTarget().GetArchitecture().GetTriple().getArch() ==
+         llvm::Triple::wasm32);
+  }
+
+  if (should_create)
+    return new DynamicLoaderWasmDYLD(process);
+
+  return nullptr;
+}
+
+void DynamicLoaderWasmDYLD::DidAttach() {
+  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
+  LLDB_LOGF(log, "DynamicLoaderWasmDYLD::%s()", __FUNCTION__);
+
+  // Ask the process for the list of loaded WebAssembly modules.
+  auto error = m_process->LoadModules();
+  LLDB_LOG_ERROR(log, std::move(error), "Couldn't load modules: {0}");
+}
+
+ThreadPlanSP DynamicLoaderWasmDYLD::GetStepThroughTrampolinePlan(Thread &thread,
+                                                                 bool stop) {
+  return ThreadPlanSP();
+}

diff  --git a/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.h b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.h
new file mode 100644
index 000000000000..4a18972bb848
--- /dev/null
+++ b/lldb/source/Plugins/DynamicLoader/wasm-DYLD/DynamicLoaderWasmDYLD.h
@@ -0,0 +1,48 @@
+//===-- DynamicLoaderWasmDYLD.h ---------------------------------*- 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 liblldb_Plugins_DynamicLoaderWasmDYLD_h_
+#define liblldb_Plugins_DynamicLoaderWasmDYLD_h_
+
+#include "lldb/Target/DynamicLoader.h"
+
+namespace lldb_private {
+namespace wasm {
+
+class DynamicLoaderWasmDYLD : public DynamicLoader {
+public:
+  DynamicLoaderWasmDYLD(Process *process);
+
+  static void Initialize();
+  static void Terminate() {}
+
+  static ConstString GetPluginNameStatic();
+  static const char *GetPluginDescriptionStatic();
+
+  static DynamicLoader *CreateInstance(Process *process, bool force);
+
+  /// DynamicLoader
+  /// \{
+  void DidAttach() override;
+  void DidLaunch() override {}
+  Status CanLoadImage() override { return Status(); }
+  lldb::ThreadPlanSP GetStepThroughTrampolinePlan(Thread &thread,
+                                                  bool stop) override;
+  /// \}
+
+  /// PluginInterface protocol.
+  /// \{
+  ConstString GetPluginName() override { return GetPluginNameStatic(); }
+  uint32_t GetPluginVersion() override { return 1; }
+  /// \}
+};
+
+} // namespace wasm
+} // namespace lldb_private
+
+#endif // liblldb_Plugins_DynamicLoaderWasmDYLD_h_

diff  --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index b9561bdff9f3..e18a84bda4a8 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -235,7 +235,7 @@ ObjectFileWasm::ObjectFileWasm(const ModuleSP &module_sp, DataBufferSP &data_sp,
                                offset_t data_offset, const FileSpec *file,
                                offset_t offset, offset_t length)
     : ObjectFile(module_sp, file, offset, length, data_sp, data_offset),
-      m_arch("wasm32-unknown-unknown-wasm"), m_code_section_offset(0) {
+      m_arch("wasm32-unknown-unknown-wasm") {
   m_data.SetAddressByteSize(4);
 }
 
@@ -244,7 +244,7 @@ ObjectFileWasm::ObjectFileWasm(const lldb::ModuleSP &module_sp,
                                const lldb::ProcessSP &process_sp,
                                lldb::addr_t header_addr)
     : ObjectFile(module_sp, process_sp, header_addr, header_data_sp),
-      m_arch("wasm32-unknown-unknown-wasm"), m_code_section_offset(0) {}
+      m_arch("wasm32-unknown-unknown-wasm") {}
 
 bool ObjectFileWasm::ParseHeader() {
   // We already parsed the header during initialization.
@@ -266,15 +266,19 @@ void ObjectFileWasm::CreateSections(SectionList &unified_section_list) {
   for (const section_info &sect_info : m_sect_infos) {
     SectionType section_type = eSectionTypeOther;
     ConstString section_name;
-    offset_t file_offset = 0;
-    addr_t vm_addr = 0;
-    size_t vm_size = 0;
+    offset_t file_offset = sect_info.offset & 0xffffffff;
+    addr_t vm_addr = file_offset;
+    size_t vm_size = sect_info.size;
 
     if (llvm::wasm::WASM_SEC_CODE == sect_info.id) {
       section_type = eSectionTypeCode;
       section_name = ConstString("code");
-      m_code_section_offset = sect_info.offset & 0xffffffff;
-      vm_size = sect_info.size;
+
+      // A code address in DWARF for WebAssembly is the offset of an
+      // instruction relative within the Code section of the WebAssembly file.
+      // For this reason Section::GetFileAddress() must return zero for the
+      // Code section.
+      vm_addr = 0;
     } else {
       section_type =
           llvm::StringSwitch<SectionType>(sect_info.name.GetStringRef())
@@ -302,10 +306,9 @@ void ObjectFileWasm::CreateSections(SectionList &unified_section_list) {
       if (section_type == eSectionTypeOther)
         continue;
       section_name = sect_info.name;
-      file_offset = sect_info.offset & 0xffffffff;
-      if (IsInMemory()) {
-        vm_addr = sect_info.offset & 0xffffffff;
-        vm_size = sect_info.size;
+      if (!IsInMemory()) {
+        vm_size = 0;
+        vm_addr = 0;
       }
     }
 
@@ -345,6 +348,10 @@ bool ObjectFileWasm::SetLoadAddress(Target &target, lldb::addr_t load_address,
   /// 0x0000000400000000 for module_id == 4.
   /// These 64-bit addresses will be used to request code ranges for a specific
   /// module from the WebAssembly engine.
+
+  assert(m_memory_addr == LLDB_INVALID_ADDRESS ||
+         m_memory_addr == load_address);
+
   ModuleSP module_sp = GetModule();
   if (!module_sp)
     return false;
@@ -357,12 +364,10 @@ bool ObjectFileWasm::SetLoadAddress(Target &target, lldb::addr_t load_address,
     return false;
 
   const size_t num_sections = section_list->GetSize();
-  size_t sect_idx = 0;
-
-  for (sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
+  for (size_t sect_idx = 0; sect_idx < num_sections; ++sect_idx) {
     SectionSP section_sp(section_list->GetSectionAtIndex(sect_idx));
-    if (target.GetSectionLoadList().SetSectionLoadAddress(
-            section_sp, load_address | section_sp->GetFileAddress())) {
+    if (target.SetSectionLoadAddress(
+            section_sp, load_address | section_sp->GetFileOffset())) {
       ++num_loaded_sections;
     }
   }
@@ -370,11 +375,11 @@ bool ObjectFileWasm::SetLoadAddress(Target &target, lldb::addr_t load_address,
   return num_loaded_sections > 0;
 }
 
-DataExtractor ObjectFileWasm::ReadImageData(uint64_t offset, size_t size) {
+DataExtractor ObjectFileWasm::ReadImageData(offset_t offset, uint32_t size) {
   DataExtractor data;
   if (m_file) {
     if (offset < GetByteSize()) {
-      size = std::min(size, (size_t) (GetByteSize() - offset));
+      size = std::min(static_cast<uint64_t>(size), GetByteSize() - offset);
       auto buffer_sp = MapFileData(m_file, size, offset);
       return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize());
     }

diff  --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
index 36ef56fe2cce..5fedd06def27 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
@@ -69,7 +69,7 @@ class ObjectFileWasm : public ObjectFile {
     return m_arch.GetByteOrder();
   }
 
-  bool IsExecutable() const override { return true; }
+  bool IsExecutable() const override { return false; }
 
   uint32_t GetAddressByteSize() const override {
     return m_arch.GetAddressByteSize();
@@ -81,7 +81,7 @@ class ObjectFileWasm : public ObjectFile {
 
   Symtab *GetSymtab() override;
 
-  bool IsStripped() override { return true; }
+  bool IsStripped() override { return !!GetExternalDebugInfoFileSpec(); }
 
   void CreateSections(SectionList &unified_section_list) override;
 
@@ -93,7 +93,7 @@ class ObjectFileWasm : public ObjectFile {
 
   uint32_t GetDependentModules(FileSpecList &files) override { return 0; }
 
-  Type CalculateType() override { return eTypeExecutable; }
+  Type CalculateType() override { return eTypeSharedLibrary; }
 
   Strata CalculateStrata() override { return eStrataUser; }
 
@@ -101,8 +101,7 @@ class ObjectFileWasm : public ObjectFile {
                       bool value_is_offset) override;
 
   lldb_private::Address GetBaseAddress() override {
-    return IsInMemory() ? Address(m_memory_addr + m_code_section_offset)
-                        : Address(m_code_section_offset);
+    return IsInMemory() ? Address(m_memory_addr) : Address(0);
   }
   /// \}
 
@@ -127,7 +126,7 @@ class ObjectFileWasm : public ObjectFile {
   /// \}
 
   /// Read a range of bytes from the Wasm module.
-  DataExtractor ReadImageData(uint64_t offset, size_t size);
+  DataExtractor ReadImageData(lldb::offset_t offset, uint32_t size);
 
   typedef struct section_info {
     lldb::offset_t offset;
@@ -145,7 +144,6 @@ class ObjectFileWasm : public ObjectFile {
   std::vector<section_info_t> m_sect_infos;
   ArchSpec m_arch;
   UUID m_uuid;
-  uint32_t m_code_section_offset;
 };
 
 } // namespace wasm

diff  --git a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
new file mode 100644
index 000000000000..8929e0e44e62
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
@@ -0,0 +1,229 @@
+import lldb
+import binascii
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from gdbclientutils import *
+
+LLDB_INVALID_ADDRESS = lldb.LLDB_INVALID_ADDRESS
+load_address = 0x400000000
+
+def format_register_value(val):
+    """
+    Encode each byte by two hex digits in little-endian order.
+    """
+    result = ""
+    mask = 0xff
+    shift = 0
+    for i in range(0, 8):
+        x = (val & mask) >> shift
+        result += format(x, '02x')
+        mask <<= 8
+        shift += 8
+    return result
+
+
+class MyResponder(MockGDBServerResponder):
+    current_pc = load_address + 0x0a
+
+    def __init__(self, obj_path, module_name = ""):
+        self._obj_path = obj_path
+        self._module_name = module_name or obj_path
+        MockGDBServerResponder.__init__(self)
+
+    def respond(self, packet):
+        if packet == "qProcessInfo":
+            return self.qProcessInfo()
+        if packet[0:13] == "qRegisterInfo":
+            return self.qRegisterInfo(packet[13:])
+        return MockGDBServerResponder.respond(self, packet)
+
+    def qSupported(self, client_supported):
+        return "qXfer:libraries:read+;PacketSize=1000;vContSupported-"
+
+    def qHostInfo(self):
+        return ""
+
+    def QEnableErrorStrings(self):
+        return ""
+
+    def qfThreadInfo(self):
+        return "OK"
+
+    def qRegisterInfo(self, index):
+        if (index == 0):
+            return "name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;"
+        return "E45"
+
+    def qProcessInfo(self):
+        return "pid:1;ppid:1;uid:1;gid:1;euid:1;egid:1;name:%s;triple:%s;ptrsize:4" % (hex_encode_bytes("lldb"), hex_encode_bytes("wasm32-unknown-unknown-wasm"))
+
+    def haltReason(self):
+        return "T05thread:1;"
+
+    def readRegister(self, register):                
+        return format_register_value(self.current_pc)
+
+    def qXferRead(self, obj, annex, offset, length):
+        if obj == "libraries":
+            xml = '<library-list><library name=\"%s\"><section address=\"%d\"/></library></library-list>' % (self._module_name, load_address)
+            return xml, False
+        else:
+            return None, False
+
+    def readMemory(self, addr, length):
+        if addr < load_address: 
+            return "E02"
+        result = ""
+        with open(self._obj_path, mode='rb') as file:
+            file_content = bytearray(file.read())                    
+            addr_from = addr - load_address
+            addr_to = addr_from + min(length, len(file_content) - addr_from)
+            for i in range(addr_from, addr_to):
+                result += format(file_content[i], '02x')
+            file.close()
+        return result
+
+
+class TestWasm(GDBRemoteTestBase):
+
+    def setUp(self):
+        super(TestWasm, self).setUp()
+        self._initial_platform = lldb.DBG.GetSelectedPlatform()
+
+    def tearDown(self):
+        lldb.DBG.SetSelectedPlatform(self._initial_platform)
+        super(TestWasm, self).tearDown()
+
+    def test_load_module_with_embedded_symbols_from_remote(self):
+        """Test connecting to a WebAssembly engine via GDB-remote and loading a Wasm module with embedded DWARF symbols"""
+
+        yaml_path = "test_wasm_embedded_debug_sections.yaml"
+        yaml_base, ext = os.path.splitext(yaml_path)
+        obj_path = self.getBuildArtifact(yaml_base)
+        self.yaml2obj(yaml_path, obj_path)
+
+        self.server.responder = MyResponder(obj_path, "test_wasm")
+
+        target = self.dbg.CreateTarget("")
+        process = self.connect(target)
+        lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateStopped])
+    
+        num_modules = target.GetNumModules()
+        self.assertEquals(1, num_modules)
+
+        module = target.GetModuleAtIndex(0)
+        num_sections = module.GetNumSections()
+        self.assertEquals(5, num_sections)
+
+        code_section = module.GetSectionAtIndex(0)
+        self.assertEquals("code", code_section.GetName())
+        self.assertEquals(load_address | code_section.GetFileOffset(), code_section.GetLoadAddress(target))
+
+        debug_info_section = module.GetSectionAtIndex(1)
+        self.assertEquals(".debug_info", debug_info_section.GetName())
+        self.assertEquals(load_address | debug_info_section.GetFileOffset(), debug_info_section.GetLoadAddress(target))
+
+        debug_abbrev_section = module.GetSectionAtIndex(2)
+        self.assertEquals(".debug_abbrev", debug_abbrev_section.GetName())
+        self.assertEquals(load_address | debug_abbrev_section.GetFileOffset(), debug_abbrev_section.GetLoadAddress(target))
+
+        debug_line_section = module.GetSectionAtIndex(3)
+        self.assertEquals(".debug_line", debug_line_section.GetName())
+        self.assertEquals(load_address | debug_line_section.GetFileOffset(), debug_line_section.GetLoadAddress(target))
+
+        debug_str_section = module.GetSectionAtIndex(4)
+        self.assertEquals(".debug_str", debug_str_section.GetName())
+        self.assertEquals(load_address | debug_line_section.GetFileOffset(), debug_line_section.GetLoadAddress(target))
+
+        
+    def test_load_module_with_stripped_symbols_from_remote(self):
+        """Test connecting to a WebAssembly engine via GDB-remote and loading a Wasm module with symbols stripped into a separate Wasm file"""
+
+        sym_yaml_path = "test_sym.yaml"
+        sym_yaml_base, ext = os.path.splitext(sym_yaml_path)
+        sym_obj_path = self.getBuildArtifact(sym_yaml_base) + ".wasm"
+        self.yaml2obj(sym_yaml_path, sym_obj_path)
+
+        yaml_path = "test_wasm_external_debug_sections.yaml"
+        yaml_base, ext = os.path.splitext(yaml_path)
+        obj_path = self.getBuildArtifact(yaml_base) + ".wasm"
+        self.yaml2obj(yaml_path, obj_path)
+
+        self.server.responder = MyResponder(obj_path, "test_wasm")
+
+        folder, _ = os.path.split(obj_path)
+        self.runCmd("settings set target.debug-file-search-paths " + os.path.abspath(folder))
+
+        target = self.dbg.CreateTarget("")
+        process = self.connect(target)
+        lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateStopped])
+    
+        num_modules = target.GetNumModules()
+        self.assertEquals(1, num_modules)
+
+        module = target.GetModuleAtIndex(0)
+        num_sections = module.GetNumSections()
+        self.assertEquals(5, num_sections)
+
+        code_section = module.GetSectionAtIndex(0)
+        self.assertEquals("code", code_section.GetName())
+        self.assertEquals(load_address | code_section.GetFileOffset(), code_section.GetLoadAddress(target))
+
+        debug_info_section = module.GetSectionAtIndex(1)
+        self.assertEquals(".debug_info", debug_info_section.GetName())
+        self.assertEquals(LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target))
+
+        debug_abbrev_section = module.GetSectionAtIndex(2)
+        self.assertEquals(".debug_abbrev", debug_abbrev_section.GetName())
+        self.assertEquals(LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target))
+
+        debug_line_section = module.GetSectionAtIndex(3)
+        self.assertEquals(".debug_line", debug_line_section.GetName())
+        self.assertEquals(LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target))
+
+        debug_str_section = module.GetSectionAtIndex(4)
+        self.assertEquals(".debug_str", debug_str_section.GetName())
+        self.assertEquals(LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target))
+
+
+    def test_load_module_from_file(self):
+        """Test connecting to a WebAssembly engine via GDB-remote and loading a Wasm module from a file"""
+
+        yaml_path = "test_wasm_embedded_debug_sections.yaml"
+        yaml_base, ext = os.path.splitext(yaml_path)
+        obj_path = self.getBuildArtifact(yaml_base)
+        self.yaml2obj(yaml_path, obj_path)
+
+        self.server.responder = MyResponder(obj_path)
+
+        target = self.dbg.CreateTarget("")
+        process = self.connect(target)
+        lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateStopped])
+    
+        num_modules = target.GetNumModules()
+        self.assertEquals(1, num_modules)
+
+        module = target.GetModuleAtIndex(0)
+        num_sections = module.GetNumSections()
+        self.assertEquals(5, num_sections)
+
+        code_section = module.GetSectionAtIndex(0)
+        self.assertEquals("code", code_section.GetName())
+        self.assertEquals(load_address | code_section.GetFileOffset(), code_section.GetLoadAddress(target))
+
+        debug_info_section = module.GetSectionAtIndex(1)
+        self.assertEquals(".debug_info", debug_info_section.GetName())
+        self.assertEquals(LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target))
+
+        debug_abbrev_section = module.GetSectionAtIndex(2)
+        self.assertEquals(".debug_abbrev", debug_abbrev_section.GetName())
+        self.assertEquals(LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target))
+
+        debug_line_section = module.GetSectionAtIndex(3)
+        self.assertEquals(".debug_line", debug_line_section.GetName())
+        self.assertEquals(LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target))
+
+        debug_str_section = module.GetSectionAtIndex(4)
+        self.assertEquals(".debug_str", debug_str_section.GetName())
+        self.assertEquals(LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target))
+

diff  --git a/lldb/test/API/functionalities/gdb_remote_client/test_sym.yaml b/lldb/test/API/functionalities/gdb_remote_client/test_sym.yaml
new file mode 100644
index 000000000000..ab517f5c22bd
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/test_sym.yaml
@@ -0,0 +1,18 @@
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+
+  - Type:            CUSTOM
+    Name:            .debug_info
+    Payload:         4C00
+  - Type:            CUSTOM
+    Name:            .debug_abbrev
+    Payload:         0111
+  - Type:            CUSTOM
+    Name:            .debug_line
+    Payload:         5100
+  - Type:            CUSTOM
+    Name:            .debug_str
+    Payload:         636CFF
+...

diff  --git a/lldb/test/API/functionalities/gdb_remote_client/test_wasm_embedded_debug_sections.yaml b/lldb/test/API/functionalities/gdb_remote_client/test_wasm_embedded_debug_sections.yaml
new file mode 100644
index 000000000000..347ead2ed17d
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/test_wasm_embedded_debug_sections.yaml
@@ -0,0 +1,25 @@
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:
+          - Type:            I32
+            Count:           6
+        Body:            238080808000210141102102200120026B21032003200036020C200328020C2104200328020C2105200420056C210620060F0B
+  - Type:            CUSTOM
+    Name:            .debug_info
+    Payload:         4C00
+  - Type:            CUSTOM
+    Name:            .debug_abbrev
+    Payload:         0111
+  - Type:            CUSTOM
+    Name:            .debug_line
+    Payload:         5100
+  - Type:            CUSTOM
+    Name:            .debug_str
+    Payload:         636CFF
+...

diff  --git a/lldb/test/API/functionalities/gdb_remote_client/test_wasm_external_debug_sections.yaml b/lldb/test/API/functionalities/gdb_remote_client/test_wasm_external_debug_sections.yaml
new file mode 100644
index 000000000000..4a34f799aa4c
--- /dev/null
+++ b/lldb/test/API/functionalities/gdb_remote_client/test_wasm_external_debug_sections.yaml
@@ -0,0 +1,16 @@
+--- !WASM
+FileHeader:
+  Version:         0x00000001
+Sections:
+
+  - Type:            CODE
+    Functions:
+      - Index:           0
+        Locals:
+          - Type:            I32
+            Count:           6
+        Body:            238080808000210141102102200120026B21032003200036020C200328020C2104200328020C2105200420056C210620060F0B
+  - Type:            CUSTOM
+    Name:            external_debug_info
+    Payload:         0d746573745f73796d2e7761736d # 'test_sym.wasm' Wasm-encoded
+...

diff  --git a/lldb/test/Shell/ObjectFile/wasm/basic.yaml b/lldb/test/Shell/ObjectFile/wasm/basic.yaml
index e7928f961590..79b6c73bcbe4 100644
--- a/lldb/test/Shell/ObjectFile/wasm/basic.yaml
+++ b/lldb/test/Shell/ObjectFile/wasm/basic.yaml
@@ -4,11 +4,11 @@
 # CHECK: Plugin name: wasm
 # CHECK: Architecture: wasm32-unknown-unknown-wasm
 # CHECK: UUID: 
-# CHECK: Executable: true
-# CHECK: Stripped: true
-# CHECK: Type: executable
+# CHECK: Executable: false
+# CHECK: Stripped: false
+# CHECK: Type: shared library
 # CHECK: Strata: user
-# CHECK: Base VM address: 0xa
+# CHECK: Base VM address: 0x0
 
 # CHECK: Name: code
 # CHECK: Type: code

diff  --git a/lldb/test/Shell/ObjectFile/wasm/embedded-debug-sections.yaml b/lldb/test/Shell/ObjectFile/wasm/embedded-debug-sections.yaml
index ac36c66df441..537c1553a9d7 100644
--- a/lldb/test/Shell/ObjectFile/wasm/embedded-debug-sections.yaml
+++ b/lldb/test/Shell/ObjectFile/wasm/embedded-debug-sections.yaml
@@ -4,11 +4,11 @@
 # CHECK: Plugin name: wasm
 # CHECK: Architecture: wasm32-unknown-unknown-wasm
 # CHECK: UUID: 
-# CHECK: Executable: true
-# CHECK: Stripped: true
-# CHECK: Type: executable
+# CHECK: Executable: false
+# CHECK: Stripped: false
+# CHECK: Type: shared library
 # CHECK: Strata: user
-# CHECK: Base VM address: 0xa
+# CHECK: Base VM address: 0x0
 
 # CHECK: Name: code
 # CHECK: Type: code

diff  --git a/lldb/test/Shell/ObjectFile/wasm/stripped-debug-sections.yaml b/lldb/test/Shell/ObjectFile/wasm/stripped-debug-sections.yaml
index 0ec349e73be2..412fb0aa9fd7 100644
--- a/lldb/test/Shell/ObjectFile/wasm/stripped-debug-sections.yaml
+++ b/lldb/test/Shell/ObjectFile/wasm/stripped-debug-sections.yaml
@@ -4,9 +4,9 @@
 # CHECK: Plugin name: wasm
 # CHECK: Architecture: wasm32-unknown-unknown-wasm
 # CHECK: UUID: 
-# CHECK: Executable: true
-# CHECK: Stripped: true
-# CHECK: Type: executable
+# CHECK: Executable: false
+# CHECK: Stripped: false
+# CHECK: Type: shared library
 # CHECK: Strata: user
 # CHECK: Base VM address: 0x0
 

diff  --git a/lldb/test/Shell/ObjectFile/wasm/unified-debug-sections.yaml b/lldb/test/Shell/ObjectFile/wasm/unified-debug-sections.yaml
index 182690eac51e..4bfdd5ae3cb1 100644
--- a/lldb/test/Shell/ObjectFile/wasm/unified-debug-sections.yaml
+++ b/lldb/test/Shell/ObjectFile/wasm/unified-debug-sections.yaml
@@ -13,11 +13,11 @@
 # CHECK: Plugin name: wasm
 # CHECK: Architecture: wasm32-unknown-unknown-wasm
 # CHECK: UUID: 
-# CHECK: Executable: true
+# CHECK: Executable: false
 # CHECK: Stripped: true
-# CHECK: Type: executable
+# CHECK: Type: shared library
 # CHECK: Strata: user
-# CHECK: Base VM address: 0xa
+# CHECK: Base VM address: 0x0
 
 # CHECK: Name: code
 # CHECK: Type: code

diff  --git a/lldb/tools/lldb-test/SystemInitializerTest.cpp b/lldb/tools/lldb-test/SystemInitializerTest.cpp
index 92b4a468d81c..b33b08640471 100644
--- a/lldb/tools/lldb-test/SystemInitializerTest.cpp
+++ b/lldb/tools/lldb-test/SystemInitializerTest.cpp
@@ -91,6 +91,7 @@ LLDB_PLUGIN_DECLARE(ProcessGDBRemote)
 LLDB_PLUGIN_DECLARE(DynamicLoaderMacOSXDYLD)
 LLDB_PLUGIN_DECLARE(DynamicLoaderPOSIXDYLD)
 LLDB_PLUGIN_DECLARE(DynamicLoaderStatic)
+LLDB_PLUGIN_DECLARE(DynamicLoaderWasmDYLD)
 LLDB_PLUGIN_DECLARE(DynamicLoaderWindowsDYLD)
 
 using namespace lldb_private;
@@ -215,6 +216,7 @@ llvm::Error SystemInitializerTest::Initialize() {
   LLDB_PLUGIN_INITIALIZE(ProcessGDBRemote);
   LLDB_PLUGIN_INITIALIZE(DynamicLoaderMacOSXDYLD);
   LLDB_PLUGIN_INITIALIZE(DynamicLoaderPOSIXDYLD);
+  LLDB_PLUGIN_INITIALIZE(DynamicLoaderWasmDYLD); // Before DynamicLoaderStatic.
   LLDB_PLUGIN_INITIALIZE(DynamicLoaderStatic);
   LLDB_PLUGIN_INITIALIZE(DynamicLoaderWindowsDYLD);
 
@@ -302,6 +304,7 @@ void SystemInitializerTest::Terminate() {
 
   LLDB_PLUGIN_TERMINATE(DynamicLoaderMacOSXDYLD);
   LLDB_PLUGIN_TERMINATE(DynamicLoaderPOSIXDYLD);
+  LLDB_PLUGIN_TERMINATE(DynamicLoaderWasmDYLD);
   LLDB_PLUGIN_TERMINATE(DynamicLoaderStatic);
   LLDB_PLUGIN_TERMINATE(DynamicLoaderWindowsDYLD);
 


        


More information about the lldb-commits mailing list