[Lldb-commits] [lldb] 9b3254d - [LLDB] Add SymbolVendorWasm plugin for WebAssembly debugging
Derek Schuff via lldb-commits
lldb-commits at lists.llvm.org
Thu Jan 16 09:36:56 PST 2020
Author: Paolo Severini
Date: 2020-01-16T09:36:17-08:00
New Revision: 9b3254dbf9f6624c772db7cfa7a3c29a0b94be8e
URL: https://github.com/llvm/llvm-project/commit/9b3254dbf9f6624c772db7cfa7a3c29a0b94be8e
DIFF: https://github.com/llvm/llvm-project/commit/9b3254dbf9f6624c772db7cfa7a3c29a0b94be8e.diff
LOG: [LLDB] Add SymbolVendorWasm plugin for WebAssembly debugging
Add plugin class SymbolVendorWasm, with the logic to manage debug symbols
for Wasm modules.
Reviewers: clayborg, labath, aprantl, sbc100, teemperor
Reviewed By: labath
Tags: #lldb
Differential Revision: https://reviews.llvm.org/D72650
Added:
lldb/source/Plugins/SymbolVendor/wasm/CMakeLists.txt
lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.h
lldb/test/Shell/ObjectFile/wasm/unified-debug-sections.yaml
Modified:
lldb/source/API/SystemInitializerFull.cpp
lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
lldb/source/Plugins/SymbolVendor/CMakeLists.txt
lldb/tools/lldb-test/SystemInitializerTest.cpp
Removed:
################################################################################
diff --git a/lldb/source/API/SystemInitializerFull.cpp b/lldb/source/API/SystemInitializerFull.cpp
index 2c567974891c..2bc53af91d00 100644
--- a/lldb/source/API/SystemInitializerFull.cpp
+++ b/lldb/source/API/SystemInitializerFull.cpp
@@ -95,6 +95,7 @@
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
+#include "Plugins/SymbolVendor/wasm/SymbolVendorWasm.h"
#include "Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h"
#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
#include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h"
@@ -242,6 +243,7 @@ llvm::Error SystemInitializerFull::Initialize() {
SymbolFileDWARF::Initialize();
SymbolFilePDB::Initialize();
SymbolFileSymtab::Initialize();
+ wasm::SymbolVendorWasm::Initialize();
UnwindAssemblyInstEmulation::Initialize();
UnwindAssembly_x86::Initialize();
@@ -334,6 +336,7 @@ void SystemInitializerFull::Terminate() {
ThreadSanitizerRuntime::Terminate();
UndefinedBehaviorSanitizerRuntime::Terminate();
MainThreadCheckerRuntime::Terminate();
+ wasm::SymbolVendorWasm::Terminate();
SymbolVendorELF::Terminate();
breakpad::SymbolFileBreakpad::Terminate();
SymbolFileDWARF::Terminate();
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
index 2c918a8f9db3..bd4c3597b066 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp
@@ -72,6 +72,8 @@ GetWasmString(llvm::DataExtractor &data, llvm::DataExtractor::Cursor &c) {
return ConstString(str);
}
+char ObjectFileWasm::ID;
+
void ObjectFileWasm::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
GetPluginDescriptionStatic(), CreateInstance,
@@ -177,6 +179,9 @@ bool ObjectFileWasm::DecodeNextSection(lldb::offset_t *offset_ptr) {
return false;
if (section_id == llvm::wasm::WASM_SEC_CUSTOM) {
+ // Custom sections have the id 0. Their contents consist of a name
+ // identifying the custom section, followed by an uninterpreted sequence
+ // of bytes.
lldb::offset_t prev_offset = c.tell();
llvm::Optional<ConstString> sect_name = GetWasmString(data, c);
if (!sect_name)
@@ -389,6 +394,24 @@ DataExtractor ObjectFileWasm::ReadImageData(uint64_t offset, size_t size) {
return data;
}
+llvm::Optional<FileSpec> ObjectFileWasm::GetExternalDebugInfoFileSpec() {
+ static ConstString g_sect_name_external_debug_info("external_debug_info");
+
+ for (const section_info §_info : m_sect_infos) {
+ if (g_sect_name_external_debug_info == sect_info.name) {
+ const uint32_t kBufferSize = 1024;
+ DataExtractor section_header_data =
+ ReadImageData(sect_info.offset, kBufferSize);
+ llvm::DataExtractor data = section_header_data.GetAsLLVM();
+ llvm::DataExtractor::Cursor c(0);
+ llvm::Optional<ConstString> symbols_url = GetWasmString(data, c);
+ if (symbols_url)
+ return FileSpec(symbols_url->GetStringRef());
+ }
+ }
+ return llvm::None;
+}
+
void ObjectFileWasm::Dump(Stream *s) {
ModuleSP module_sp(GetModule());
if (!module_sp)
diff --git a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
index 986f7f9f1679..65d237e20450 100644
--- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
+++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.h
@@ -52,6 +52,15 @@ class ObjectFileWasm : public ObjectFile {
uint32_t GetPluginVersion() override { return 1; }
/// \}
+ /// LLVM RTTI support
+ /// \{
+ static char ID;
+ bool isA(const void *ClassID) const override {
+ return ClassID == &ID || ObjectFile::isA(ClassID);
+ }
+ static bool classof(const ObjectFile *obj) { return obj->isA(&ID); }
+ /// \}
+
/// ObjectFile Protocol.
/// \{
bool ParseHeader() override;
@@ -97,6 +106,12 @@ class ObjectFileWasm : public ObjectFile {
}
/// \}
+ /// A Wasm module that has external DWARF debug information should contain a
+ /// custom section named "external_debug_info", whose payload is an UTF-8
+ /// encoded string that points to a Wasm module that contains the debug
+ /// information for this module.
+ llvm::Optional<FileSpec> GetExternalDebugInfoFileSpec();
+
private:
ObjectFileWasm(const lldb::ModuleSP &module_sp, lldb::DataBufferSP &data_sp,
lldb::offset_t data_offset, const FileSpec *file,
diff --git a/lldb/source/Plugins/SymbolVendor/CMakeLists.txt b/lldb/source/Plugins/SymbolVendor/CMakeLists.txt
index 94862d588727..695b9a019ae7 100644
--- a/lldb/source/Plugins/SymbolVendor/CMakeLists.txt
+++ b/lldb/source/Plugins/SymbolVendor/CMakeLists.txt
@@ -3,3 +3,4 @@ if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
endif()
add_subdirectory(ELF)
+add_subdirectory(wasm)
diff --git a/lldb/source/Plugins/SymbolVendor/wasm/CMakeLists.txt b/lldb/source/Plugins/SymbolVendor/wasm/CMakeLists.txt
new file mode 100644
index 000000000000..49f6012c7bca
--- /dev/null
+++ b/lldb/source/Plugins/SymbolVendor/wasm/CMakeLists.txt
@@ -0,0 +1,9 @@
+add_lldb_library(lldbPluginSymbolVendorWasm PLUGIN
+ SymbolVendorWasm.cpp
+
+ LINK_LIBS
+ lldbCore
+ lldbHost
+ lldbSymbol
+ lldbPluginObjectFileWasm
+ )
diff --git a/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
new file mode 100644
index 000000000000..bd59bd5cf358
--- /dev/null
+++ b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.cpp
@@ -0,0 +1,145 @@
+//===-- SymbolVendorWasm.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 "SymbolVendorWasm.h"
+
+#include <string.h>
+
+#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/ModuleSpec.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Host/Host.h"
+#include "lldb/Symbol/LocateSymbolFile.h"
+#include "lldb/Symbol/ObjectFile.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Utility/StreamString.h"
+#include "lldb/Utility/Timer.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::wasm;
+
+// SymbolVendorWasm constructor
+SymbolVendorWasm::SymbolVendorWasm(const lldb::ModuleSP &module_sp)
+ : SymbolVendor(module_sp) {}
+
+void SymbolVendorWasm::Initialize() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance);
+}
+
+void SymbolVendorWasm::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+lldb_private::ConstString SymbolVendorWasm::GetPluginNameStatic() {
+ static ConstString g_name("WASM");
+ return g_name;
+}
+
+const char *SymbolVendorWasm::GetPluginDescriptionStatic() {
+ return "Symbol vendor for WASM that looks for dwo files that match "
+ "executables.";
+}
+
+// CreateInstance
+//
+// Platforms can register a callback to use when creating symbol vendors to
+// allow for complex debug information file setups, and to also allow for
+// finding separate debug information files.
+SymbolVendor *
+SymbolVendorWasm::CreateInstance(const lldb::ModuleSP &module_sp,
+ lldb_private::Stream *feedback_strm) {
+ if (!module_sp)
+ return nullptr;
+
+ ObjectFileWasm *obj_file =
+ llvm::dyn_cast_or_null<ObjectFileWasm>(module_sp->GetObjectFile());
+ if (!obj_file)
+ return nullptr;
+
+ // If the main object file already contains debug info, then we are done.
+ if (obj_file->GetSectionList()->FindSectionByType(
+ lldb::eSectionTypeDWARFDebugInfo, true))
+ return nullptr;
+
+ static Timer::Category func_cat(LLVM_PRETTY_FUNCTION);
+ Timer scoped_timer(func_cat, "SymbolVendorWasm::CreateInstance (module = %s)",
+ module_sp->GetFileSpec().GetPath().c_str());
+
+ ModuleSpec module_spec;
+ module_spec.GetFileSpec() = obj_file->GetFileSpec();
+ FileSystem::Instance().Resolve(module_spec.GetFileSpec());
+ module_spec.GetUUID() = obj_file->GetUUID();
+
+ // A Wasm module may have a custom section named "external_debug_info" whose
+ // content is the absolute or relative path of the Wasm module that contains
+ // debug symbols for this module.
+ llvm::Optional<FileSpec> symbol_file_spec =
+ obj_file->GetExternalDebugInfoFileSpec();
+ if (!symbol_file_spec)
+ return nullptr;
+ module_spec.GetSymbolFileSpec() = *symbol_file_spec;
+
+ FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
+ FileSpec sym_fspec =
+ Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+ if (!sym_fspec)
+ return nullptr;
+
+ DataBufferSP sym_file_data_sp;
+ lldb::offset_t sym_file_data_offset = 0;
+ ObjectFileSP sym_objfile_sp = ObjectFile::FindPlugin(
+ module_sp, &sym_fspec, 0, FileSystem::Instance().GetByteSize(sym_fspec),
+ sym_file_data_sp, sym_file_data_offset);
+ if (!sym_objfile_sp)
+ return nullptr;
+
+ // This objfile is for debugging purposes.
+ sym_objfile_sp->SetType(ObjectFile::eTypeDebugInfo);
+
+ SymbolVendorWasm *symbol_vendor = new SymbolVendorWasm(module_sp);
+
+ // Get the module unified section list and add our debug sections to
+ // that.
+ SectionList *module_section_list = module_sp->GetSectionList();
+ SectionList *objfile_section_list = sym_objfile_sp->GetSectionList();
+
+ static const SectionType g_sections[] = {
+ eSectionTypeDWARFDebugAbbrev, eSectionTypeDWARFDebugAddr,
+ eSectionTypeDWARFDebugAranges, eSectionTypeDWARFDebugCuIndex,
+ eSectionTypeDWARFDebugFrame, eSectionTypeDWARFDebugInfo,
+ eSectionTypeDWARFDebugLine, eSectionTypeDWARFDebugLineStr,
+ eSectionTypeDWARFDebugLoc, eSectionTypeDWARFDebugLocLists,
+ eSectionTypeDWARFDebugMacInfo, eSectionTypeDWARFDebugMacro,
+ eSectionTypeDWARFDebugPubNames, eSectionTypeDWARFDebugPubTypes,
+ eSectionTypeDWARFDebugRanges, eSectionTypeDWARFDebugRngLists,
+ eSectionTypeDWARFDebugStr, eSectionTypeDWARFDebugStrOffsets,
+ eSectionTypeDWARFDebugTypes};
+ for (SectionType section_type : g_sections) {
+ if (SectionSP section_sp =
+ objfile_section_list->FindSectionByType(section_type, true)) {
+ if (SectionSP module_section_sp =
+ module_section_list->FindSectionByType(section_type, true))
+ module_section_list->ReplaceSection(module_section_sp->GetID(),
+ section_sp);
+ else
+ module_section_list->AddSection(section_sp);
+ }
+ }
+
+ symbol_vendor->AddSymbolFileRepresentation(sym_objfile_sp);
+ return symbol_vendor;
+}
+
+// PluginInterface protocol
+ConstString SymbolVendorWasm::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t SymbolVendorWasm::GetPluginVersion() { return 1; }
diff --git a/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.h b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.h
new file mode 100644
index 000000000000..7a688ab41301
--- /dev/null
+++ b/lldb/source/Plugins/SymbolVendor/wasm/SymbolVendorWasm.h
@@ -0,0 +1,44 @@
+//===-- SymbolVendorWasm.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_SymbolVendorWasm_h_
+#define liblldb_SymbolVendorWasm_h_
+
+#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+namespace wasm {
+
+class SymbolVendorWasm : public lldb_private::SymbolVendor {
+public:
+ SymbolVendorWasm(const lldb::ModuleSP &module_sp);
+
+ static void Initialize();
+ static void Terminate();
+ static lldb_private::ConstString GetPluginNameStatic();
+ static const char *GetPluginDescriptionStatic();
+
+ static lldb_private::SymbolVendor *
+ CreateInstance(const lldb::ModuleSP &module_sp,
+ lldb_private::Stream *feedback_strm);
+
+ /// PluginInterface protocol.
+ /// \{
+ lldb_private::ConstString GetPluginName() override;
+ uint32_t GetPluginVersion() override;
+ /// \}
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(SymbolVendorWasm);
+};
+
+} // namespace wasm
+} // namespace lldb_private
+
+#endif // liblldb_SymbolVendorWasm_h_
diff --git a/lldb/test/Shell/ObjectFile/wasm/unified-debug-sections.yaml b/lldb/test/Shell/ObjectFile/wasm/unified-debug-sections.yaml
new file mode 100644
index 000000000000..d72080f40224
--- /dev/null
+++ b/lldb/test/Shell/ObjectFile/wasm/unified-debug-sections.yaml
@@ -0,0 +1,85 @@
+# RUN: yaml2obj -docnum=1 %s > test.wasm
+# RUN: yaml2obj -docnum=2 %s > test_sym.wasm
+# RUN: lldb-test object-file test.wasm | FileCheck %s
+
+# This test checks that SymbolVendorWasm correctly loads DWARF debug sections
+# that have been stripped out into a separated Wasm module. The original Wasm
+# module contains a "external_debug_info" custom section with the absolute or
+# relative path of the debug module.
+
+# CHECK: Plugin name: wasm
+# CHECK: Architecture: wasm32-unknown-unknown-wasm
+# CHECK: UUID:
+# CHECK: Executable: true
+# CHECK: Stripped: true
+# CHECK: Type: executable
+# CHECK: Strata: user
+# CHECK: Base VM address: 0xa
+
+# CHECK: Name: code
+# CHECK: Type: code
+# CHECK: VM address: 0x0
+# CHECK: VM size: 56
+# CHECK: File size: 56
+
+# CHECK: Name: .debug_info
+# CHECK: Type: dwarf-info
+# CHECK: VM address: 0x0
+# CHECK: VM size: 0
+# CHECK: File size: 2
+
+# CHECK: Name: .debug_abbrev
+# CHECK: Type: dwarf-abbrev
+# CHECK: VM address: 0x0
+# CHECK: VM size: 0
+# CHECK: File size: 2
+
+# CHECK: Name: .debug_line
+# CHECK: Type: dwarf-line
+# CHECK: VM address: 0x0
+# CHECK: VM size: 0
+# CHECK: File size: 2
+
+# CHECK: Name: .debug_str
+# CHECK: Type: dwarf-str
+# CHECK: VM address: 0x0
+# CHECK: VM size: 0
+# CHECK: File size: 3
+
+--- !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
+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/tools/lldb-test/SystemInitializerTest.cpp b/lldb/tools/lldb-test/SystemInitializerTest.cpp
index ab8a92e8955f..db0a9d464146 100644
--- a/lldb/tools/lldb-test/SystemInitializerTest.cpp
+++ b/lldb/tools/lldb-test/SystemInitializerTest.cpp
@@ -76,6 +76,7 @@
#include "Plugins/SymbolFile/PDB/SymbolFilePDB.h"
#include "Plugins/SymbolFile/Symtab/SymbolFileSymtab.h"
#include "Plugins/SymbolVendor/ELF/SymbolVendorELF.h"
+#include "Plugins/SymbolVendor/wasm/SymbolVendorWasm.h"
#include "Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.h"
#include "Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h"
#include "Plugins/UnwindAssembly/x86/UnwindAssembly-x86.h"
@@ -201,6 +202,7 @@ llvm::Error SystemInitializerTest::Initialize() {
SymbolFileDWARF::Initialize();
SymbolFilePDB::Initialize();
SymbolFileSymtab::Initialize();
+ wasm::SymbolVendorWasm::Initialize();
UnwindAssemblyInstEmulation::Initialize();
UnwindAssembly_x86::Initialize();
EmulateInstructionARM64::Initialize();
@@ -288,6 +290,7 @@ void SystemInitializerTest::Terminate() {
SymbolFileDWARF::Terminate();
SymbolFilePDB::Terminate();
SymbolFileSymtab::Terminate();
+ wasm::SymbolVendorWasm::Terminate();
UnwindAssembly_x86::Terminate();
UnwindAssemblyInstEmulation::Terminate();
EmulateInstructionARM64::Terminate();
More information about the lldb-commits
mailing list