From c3a302d399e62ac2a21c52f1f0215bd772cbf54b Mon Sep 17 00:00:00 2001 From: Jonas Devlieghere Date: Fri, 3 Nov 2023 15:42:23 -0700 Subject: [PATCH] [lldb] Convert LocateSymbolFile into a plugin (#71151) This commit contains the initial scaffolding to convert the functionality currently implemented in LocateSymbolFile to a plugin architecture. The plugin approach allows us to easily add new ways to find symbols and fixes some issues with the current implementation. For instance, currently we (ab)use the host OS to include support for querying the DebugSymbols framework on macOS. The plugin approach retains all the benefits (including the ability to compile this out on other platforms) while maintaining a higher level of separation with the platform independent code. To limit the scope of this patch, I've only converted a single function: LocateExecutableObjectFile. Future commits will convert the remaining LocateSymbolFile functions and eventually remove LocateSymbolFile. To make reviewing easier, that will done as follow-ups. --- lldb/include/lldb/Core/PluginManager.h | 13 + lldb/include/lldb/Symbol/LocateSymbolFile.h | 6 - lldb/include/lldb/Symbol/SymbolLocator.h | 23 ++ lldb/include/lldb/lldb-forward.h | 1 + lldb/include/lldb/lldb-private-interfaces.h | 3 + lldb/source/Core/DynamicLoader.cpp | 2 +- lldb/source/Core/ModuleList.cpp | 3 +- lldb/source/Core/PluginManager.cpp | 53 +++ lldb/source/Plugins/CMakeLists.txt | 1 + .../Process/MacOSX-Kernel/ProcessKDP.cpp | 2 +- .../Plugins/SymbolLocator/CMakeLists.txt | 4 + .../SymbolLocator/DebugSymbols/CMakeLists.txt | 8 + .../SymbolLocatorDebugSymbols.cpp | 327 ++++++++++++++++++ .../DebugSymbols/SymbolLocatorDebugSymbols.h | 44 +++ .../SymbolLocator/Default/CMakeLists.txt | 8 + .../Default/SymbolLocatorDefault.cpp | 90 +++++ .../Default/SymbolLocatorDefault.h | 44 +++ lldb/source/Symbol/LocateSymbolFile.cpp | 23 -- 18 files changed, 623 insertions(+), 32 deletions(-) create mode 100644 lldb/include/lldb/Symbol/SymbolLocator.h create mode 100644 lldb/source/Plugins/SymbolLocator/CMakeLists.txt create mode 100644 lldb/source/Plugins/SymbolLocator/DebugSymbols/CMakeLists.txt create mode 100644 lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp create mode 100644 lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h create mode 100644 lldb/source/Plugins/SymbolLocator/Default/CMakeLists.txt create mode 100644 lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp create mode 100644 lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h index 24d8e28cf686..feaa351b71fa 100644 --- a/lldb/include/lldb/Core/PluginManager.h +++ b/lldb/include/lldb/Core/PluginManager.h @@ -345,6 +345,19 @@ public: static SymbolVendorCreateInstance GetSymbolVendorCreateCallbackAtIndex(uint32_t idx); + // SymbolLocator + static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, + SymbolLocatorCreateInstance create_callback, + SymbolLocatorLocateExecutableObjectFile + locate_executable_object_file = nullptr); + + static bool UnregisterPlugin(SymbolLocatorCreateInstance create_callback); + + static SymbolLocatorCreateInstance + GetSymbolLocatorCreateCallbackAtIndex(uint32_t idx); + + static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec); + // Trace static bool RegisterPlugin( llvm::StringRef name, llvm::StringRef description, diff --git a/lldb/include/lldb/Symbol/LocateSymbolFile.h b/lldb/include/lldb/Symbol/LocateSymbolFile.h index 0bf655590967..8cd62cd3f73e 100644 --- a/lldb/include/lldb/Symbol/LocateSymbolFile.h +++ b/lldb/include/lldb/Symbol/LocateSymbolFile.h @@ -24,12 +24,6 @@ class UUID; class Symbols { public: - // Locate the executable file given a module specification. - // - // Locating the file should happen only on the local computer or using the - // current computers global settings. - static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec); - // Locate the symbol file given a module specification. // // Locating the file should happen only on the local computer or using the diff --git a/lldb/include/lldb/Symbol/SymbolLocator.h b/lldb/include/lldb/Symbol/SymbolLocator.h new file mode 100644 index 000000000000..e8376ff75688 --- /dev/null +++ b/lldb/include/lldb/Symbol/SymbolLocator.h @@ -0,0 +1,23 @@ +//===-- SymbolLocator.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 LLDB_SYMBOL_SYMBOLLOCATOR_H +#define LLDB_SYMBOL_SYMBOLLOCATOR_H + +#include "lldb/Core/PluginInterface.h" + +namespace lldb_private { + +class SymbolLocator : public PluginInterface { +public: + SymbolLocator() = default; +}; + +} // namespace lldb_private + +#endif // LLDB_SYMBOL_SYMBOLFILELOCATOR_H diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h index aa099d4abc3b..f66b2ad4362f 100644 --- a/lldb/include/lldb/lldb-forward.h +++ b/lldb/include/lldb/lldb-forward.h @@ -217,6 +217,7 @@ class SymbolContextScope; class SymbolContextSpecifier; class SymbolFile; class SymbolFileType; +class SymbolLocator; class SymbolVendor; class Symtab; class SyntheticChildren; diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h index 2313723b1678..a22a3e9792b3 100644 --- a/lldb/include/lldb/lldb-private-interfaces.h +++ b/lldb/include/lldb/lldb-private-interfaces.h @@ -89,6 +89,9 @@ typedef SymbolVendor *(*SymbolVendorCreateInstance)( const lldb::ModuleSP &module_sp, lldb_private::Stream *feedback_strm); // Module can be NULL for default system symbol vendor +typedef SymbolLocator *(*SymbolLocatorCreateInstance)(); +typedef std::optional (*SymbolLocatorLocateExecutableObjectFile)( + const ModuleSpec &module_spec); typedef bool (*BreakpointHitCallback)(void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id, diff --git a/lldb/source/Core/DynamicLoader.cpp b/lldb/source/Core/DynamicLoader.cpp index ce6a84e4e022..7751fd70dedd 100644 --- a/lldb/source/Core/DynamicLoader.cpp +++ b/lldb/source/Core/DynamicLoader.cpp @@ -221,7 +221,7 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress( module_spec.GetSymbolFileSpec() = Symbols::LocateExecutableSymbolFile(module_spec, search_paths); ModuleSpec objfile_module_spec = - Symbols::LocateExecutableObjectFile(module_spec); + PluginManager::LocateExecutableObjectFile(module_spec); module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec(); if (FileSystem::Instance().Exists(module_spec.GetFileSpec()) && FileSystem::Instance().Exists(module_spec.GetSymbolFileSpec())) { diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index 3650df762231..519145bba495 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -9,6 +9,7 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" #include "lldb/Host/FileSystem.h" #include "lldb/Interpreter/OptionValueFileSpec.h" #include "lldb/Interpreter/OptionValueFileSpecList.h" @@ -906,7 +907,7 @@ ModuleList::GetSharedModule(const ModuleSpec &module_spec, ModuleSP &module_sp, // Fixup the incoming path in case the path points to a valid file, yet the // arch or UUID (if one was passed in) don't match. ModuleSpec located_binary_modulespec = - Symbols::LocateExecutableObjectFile(module_spec); + PluginManager::LocateExecutableObjectFile(module_spec); // Don't look for the file if it appears to be the same one we already // checked for above... diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp index ac274112e53d..85e3f1cdcf12 100644 --- a/lldb/source/Core/PluginManager.cpp +++ b/lldb/source/Core/PluginManager.cpp @@ -1081,6 +1081,59 @@ PluginManager::GetSymbolVendorCreateCallbackAtIndex(uint32_t idx) { return GetSymbolVendorInstances().GetCallbackAtIndex(idx); } +#pragma mark SymbolLocator + +struct SymbolLocatorInstance + : public PluginInstance { + SymbolLocatorInstance( + llvm::StringRef name, llvm::StringRef description, + CallbackType create_callback, + SymbolLocatorLocateExecutableObjectFile locate_executable_object_file) + : PluginInstance(name, description, + create_callback), + locate_executable_object_file(locate_executable_object_file) {} + + SymbolLocatorLocateExecutableObjectFile locate_executable_object_file; +}; +typedef PluginInstances SymbolLocatorInstances; + +static SymbolLocatorInstances &GetSymbolLocatorInstances() { + static SymbolLocatorInstances g_instances; + return g_instances; +} + +bool PluginManager::RegisterPlugin( + llvm::StringRef name, llvm::StringRef description, + SymbolLocatorCreateInstance create_callback, + SymbolLocatorLocateExecutableObjectFile locate_executable_object_file) { + return GetSymbolLocatorInstances().RegisterPlugin( + name, description, create_callback, locate_executable_object_file); +} + +bool PluginManager::UnregisterPlugin( + SymbolLocatorCreateInstance create_callback) { + return GetSymbolLocatorInstances().UnregisterPlugin(create_callback); +} + +SymbolLocatorCreateInstance +PluginManager::GetSymbolLocatorCreateCallbackAtIndex(uint32_t idx) { + return GetSymbolLocatorInstances().GetCallbackAtIndex(idx); +} + +ModuleSpec +PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec) { + auto &instances = GetSymbolLocatorInstances().GetInstances(); + for (auto &instance : instances) { + if (instance.locate_executable_object_file) { + std::optional result = + instance.locate_executable_object_file(module_spec); + if (result) + return *result; + } + } + return {}; +} + #pragma mark Trace struct TraceInstance diff --git a/lldb/source/Plugins/CMakeLists.txt b/lldb/source/Plugins/CMakeLists.txt index 63f2c5b685a8..854f589f45ae 100644 --- a/lldb/source/Plugins/CMakeLists.txt +++ b/lldb/source/Plugins/CMakeLists.txt @@ -20,6 +20,7 @@ add_subdirectory(ScriptInterpreter) add_subdirectory(StructuredData) add_subdirectory(SymbolFile) add_subdirectory(SystemRuntime) +add_subdirectory(SymbolLocator) add_subdirectory(SymbolVendor) add_subdirectory(Trace) add_subdirectory(TraceExporter) diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp index 0d1caf4d7318..93d8e9bf75f5 100644 --- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp +++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp @@ -282,7 +282,7 @@ Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) { search_paths); if (module_spec.GetSymbolFileSpec()) { ModuleSpec executable_module_spec = - Symbols::LocateExecutableObjectFile(module_spec); + PluginManager::LocateExecutableObjectFile(module_spec); if (FileSystem::Instance().Exists( executable_module_spec.GetFileSpec())) { module_spec.GetFileSpec() = diff --git a/lldb/source/Plugins/SymbolLocator/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt new file mode 100644 index 000000000000..74abecd79694 --- /dev/null +++ b/lldb/source/Plugins/SymbolLocator/CMakeLists.txt @@ -0,0 +1,4 @@ +add_subdirectory(Default) +if (CMAKE_SYSTEM_NAME MATCHES "Darwin") + add_subdirectory(DebugSymbols) +endif() diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/DebugSymbols/CMakeLists.txt new file mode 100644 index 000000000000..40f9cc1d44e2 --- /dev/null +++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/CMakeLists.txt @@ -0,0 +1,8 @@ +add_lldb_library(lldbPluginSymbolLocatorDebugSymbols PLUGIN + SymbolLocatorDebugSymbols.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + ) diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp new file mode 100644 index 000000000000..ef19507e87e5 --- /dev/null +++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp @@ -0,0 +1,327 @@ +//===-- SymbolLocatorDebugSymbols.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 "SymbolLocatorDebugSymbols.h" + +#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h" +#include "lldb/Symbol/LocateSymbolFile.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/Timer.h" +#include "lldb/Utility/UUID.h" + +#include "llvm/ADT/SmallSet.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ThreadPool.h" + +#include "Host/macosx/cfcpp/CFCBundle.h" +#include "Host/macosx/cfcpp/CFCData.h" +#include "Host/macosx/cfcpp/CFCReleaser.h" +#include "Host/macosx/cfcpp/CFCString.h" + +#include "mach/machine.h" + +#include + +#include +#include +#include +#include +#include + +using namespace lldb; +using namespace lldb_private; + +static CFURLRef (*g_dlsym_DBGCopyFullDSYMURLForUUID)( + CFUUIDRef uuid, CFURLRef exec_url) = nullptr; +static CFDictionaryRef (*g_dlsym_DBGCopyDSYMPropertyLists)(CFURLRef dsym_url) = + nullptr; + +LLDB_PLUGIN_DEFINE(SymbolLocatorDebugSymbols) + +SymbolLocatorDebugSymbols::SymbolLocatorDebugSymbols() : SymbolLocator() {} + +void SymbolLocatorDebugSymbols::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + LocateExecutableObjectFile); +} + +void SymbolLocatorDebugSymbols::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +llvm::StringRef SymbolLocatorDebugSymbols::GetPluginDescriptionStatic() { + return "DebugSymbols symbol locator."; +} + +SymbolLocator *SymbolLocatorDebugSymbols::CreateInstance() { + return new SymbolLocatorDebugSymbols(); +} + +std::optional SymbolLocatorDebugSymbols::LocateExecutableObjectFile( + const ModuleSpec &module_spec) { + Log *log = GetLog(LLDBLog::Host); + if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) { + LLDB_LOGF(log, "Spotlight lookup for .dSYM bundles is disabled."); + return {}; + } + ModuleSpec return_module_spec; + return_module_spec = module_spec; + return_module_spec.GetFileSpec().Clear(); + return_module_spec.GetSymbolFileSpec().Clear(); + + const UUID *uuid = module_spec.GetUUIDPtr(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + + int items_found = 0; + + if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr || + g_dlsym_DBGCopyDSYMPropertyLists == nullptr) { + void *handle = dlopen( + "/System/Library/PrivateFrameworks/DebugSymbols.framework/DebugSymbols", + RTLD_LAZY | RTLD_LOCAL); + if (handle) { + g_dlsym_DBGCopyFullDSYMURLForUUID = + (CFURLRef(*)(CFUUIDRef, CFURLRef))dlsym(handle, + "DBGCopyFullDSYMURLForUUID"); + g_dlsym_DBGCopyDSYMPropertyLists = (CFDictionaryRef(*)(CFURLRef))dlsym( + handle, "DBGCopyDSYMPropertyLists"); + } + } + + if (g_dlsym_DBGCopyFullDSYMURLForUUID == nullptr || + g_dlsym_DBGCopyDSYMPropertyLists == nullptr) { + return {}; + } + + if (uuid && uuid->IsValid()) { + // Try and locate the dSYM file using DebugSymbols first + llvm::ArrayRef module_uuid = uuid->GetBytes(); + if (module_uuid.size() == 16) { + CFCReleaser module_uuid_ref(::CFUUIDCreateWithBytes( + NULL, module_uuid[0], module_uuid[1], module_uuid[2], module_uuid[3], + module_uuid[4], module_uuid[5], module_uuid[6], module_uuid[7], + module_uuid[8], module_uuid[9], module_uuid[10], module_uuid[11], + module_uuid[12], module_uuid[13], module_uuid[14], module_uuid[15])); + + if (module_uuid_ref.get()) { + CFCReleaser exec_url; + const FileSpec *exec_fspec = module_spec.GetFileSpecPtr(); + if (exec_fspec) { + char exec_cf_path[PATH_MAX]; + if (exec_fspec->GetPath(exec_cf_path, sizeof(exec_cf_path))) + exec_url.reset(::CFURLCreateFromFileSystemRepresentation( + NULL, (const UInt8 *)exec_cf_path, strlen(exec_cf_path), + FALSE)); + } + + CFCReleaser dsym_url(g_dlsym_DBGCopyFullDSYMURLForUUID( + module_uuid_ref.get(), exec_url.get())); + char path[PATH_MAX]; + + if (dsym_url.get()) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + LLDB_LOGF(log, + "DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for the dSYM", + path, uuid->GetAsString().c_str()); + FileSpec dsym_filespec(path); + if (path[0] == '~') + FileSystem::Instance().Resolve(dsym_filespec); + + if (FileSystem::Instance().IsDirectory(dsym_filespec)) { + dsym_filespec = + Symbols::FindSymbolFileInBundle(dsym_filespec, uuid, arch); + ++items_found; + } else { + ++items_found; + } + return_module_spec.GetSymbolFileSpec() = dsym_filespec; + } + + bool success = false; + if (log) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + LLDB_LOGF(log, + "DebugSymbols framework returned dSYM path of %s for " + "UUID %s -- looking for an exec file", + path, uuid->GetAsString().c_str()); + } + } + + CFCReleaser dict( + g_dlsym_DBGCopyDSYMPropertyLists(dsym_url.get())); + CFDictionaryRef uuid_dict = NULL; + if (dict.get()) { + CFCString uuid_cfstr(uuid->GetAsString().c_str()); + uuid_dict = static_cast( + ::CFDictionaryGetValue(dict.get(), uuid_cfstr.get())); + } + + // Check to see if we have the file on the local filesystem. + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { + ModuleSpec exe_spec; + exe_spec.GetFileSpec() = module_spec.GetFileSpec(); + exe_spec.GetUUID() = module_spec.GetUUID(); + ModuleSP module_sp; + module_sp.reset(new Module(exe_spec)); + if (module_sp && module_sp->GetObjectFile() && + module_sp->MatchesModuleSpec(exe_spec)) { + success = true; + return_module_spec.GetFileSpec() = module_spec.GetFileSpec(); + LLDB_LOGF(log, "using original binary filepath %s for UUID %s", + module_spec.GetFileSpec().GetPath().c_str(), + uuid->GetAsString().c_str()); + ++items_found; + } + } + + // Check if the requested image is in our shared cache. + if (!success) { + SharedCacheImageInfo image_info = HostInfo::GetSharedCacheImageInfo( + module_spec.GetFileSpec().GetPath()); + + // If we found it and it has the correct UUID, let's proceed with + // creating a module from the memory contents. + if (image_info.uuid && (!module_spec.GetUUID() || + module_spec.GetUUID() == image_info.uuid)) { + success = true; + return_module_spec.GetFileSpec() = module_spec.GetFileSpec(); + LLDB_LOGF(log, + "using binary from shared cache for filepath %s for " + "UUID %s", + module_spec.GetFileSpec().GetPath().c_str(), + uuid->GetAsString().c_str()); + ++items_found; + } + } + + // Use the DBGSymbolRichExecutable filepath if present + if (!success && uuid_dict) { + CFStringRef exec_cf_path = + static_cast(::CFDictionaryGetValue( + uuid_dict, CFSTR("DBGSymbolRichExecutable"))); + if (exec_cf_path && ::CFStringGetFileSystemRepresentation( + exec_cf_path, path, sizeof(path))) { + LLDB_LOGF(log, "plist bundle has exec path of %s for UUID %s", + path, uuid->GetAsString().c_str()); + ++items_found; + FileSpec exec_filespec(path); + if (path[0] == '~') + FileSystem::Instance().Resolve(exec_filespec); + if (FileSystem::Instance().Exists(exec_filespec)) { + success = true; + return_module_spec.GetFileSpec() = exec_filespec; + } + } + } + + // Look next to the dSYM for the binary file. + if (!success) { + if (::CFURLGetFileSystemRepresentation( + dsym_url.get(), true, (UInt8 *)path, sizeof(path) - 1)) { + char *dsym_extension_pos = ::strstr(path, ".dSYM"); + if (dsym_extension_pos) { + *dsym_extension_pos = '\0'; + LLDB_LOGF(log, + "Looking for executable binary next to dSYM " + "bundle with name with name %s", + path); + FileSpec file_spec(path); + FileSystem::Instance().Resolve(file_spec); + ModuleSpecList module_specs; + ModuleSpec matched_module_spec; + using namespace llvm::sys::fs; + switch (get_file_type(file_spec.GetPath())) { + + case file_type::directory_file: // Bundle directory? + { + CFCBundle bundle(path); + CFCReleaser bundle_exe_url( + bundle.CopyExecutableURL()); + if (bundle_exe_url.get()) { + if (::CFURLGetFileSystemRepresentation(bundle_exe_url.get(), + true, (UInt8 *)path, + sizeof(path) - 1)) { + FileSpec bundle_exe_file_spec(path); + FileSystem::Instance().Resolve(bundle_exe_file_spec); + if (ObjectFile::GetModuleSpecifications( + bundle_exe_file_spec, 0, 0, module_specs) && + module_specs.FindMatchingModuleSpec( + module_spec, matched_module_spec)) + + { + ++items_found; + return_module_spec.GetFileSpec() = bundle_exe_file_spec; + LLDB_LOGF(log, + "Executable binary %s next to dSYM is " + "compatible; using", + path); + } + } + } + } break; + + case file_type::fifo_file: // Forget pipes + case file_type::socket_file: // We can't process socket files + case file_type::file_not_found: // File doesn't exist... + case file_type::status_error: + break; + + case file_type::type_unknown: + case file_type::regular_file: + case file_type::symlink_file: + case file_type::block_file: + case file_type::character_file: + if (ObjectFile::GetModuleSpecifications(file_spec, 0, 0, + module_specs) && + module_specs.FindMatchingModuleSpec(module_spec, + matched_module_spec)) + + { + ++items_found; + return_module_spec.GetFileSpec() = file_spec; + LLDB_LOGF(log, + "Executable binary %s next to dSYM is " + "compatible; using", + path); + } + break; + } + } + } + } + } + } + } + } + + if (items_found) + return return_module_spec; + + return {}; +} diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h new file mode 100644 index 000000000000..a7641b28c0dc --- /dev/null +++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.h @@ -0,0 +1,44 @@ +//===-- SymbolLocatorDebugSymbols.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 LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGSYMBOLS_SYMBOLLOCATORDEBUGSYMBOLS_H +#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGSYMBOLS_SYMBOLLOCATORDEBUGSYMBOLS_H + +#include "lldb/Symbol/SymbolLocator.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class SymbolLocatorDebugSymbols : public SymbolLocator { +public: + SymbolLocatorDebugSymbols(); + + static void Initialize(); + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "DebugSymbols"; } + static llvm::StringRef GetPluginDescriptionStatic(); + + static lldb_private::SymbolLocator *CreateInstance(); + + /// PluginInterface protocol. + /// \{ + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + /// \} + + // Locate the executable file given a module specification. + // + // Locating the file should happen only on the local computer or using the + // current computers global settings. + static std::optional + LocateExecutableObjectFile(const ModuleSpec &module_spec); +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEBUGSYMBOLS_SYMBOLLOCATORDEBUGSYMBOLS_H diff --git a/lldb/source/Plugins/SymbolLocator/Default/CMakeLists.txt b/lldb/source/Plugins/SymbolLocator/Default/CMakeLists.txt new file mode 100644 index 000000000000..6d1d300d0ca9 --- /dev/null +++ b/lldb/source/Plugins/SymbolLocator/Default/CMakeLists.txt @@ -0,0 +1,8 @@ +add_lldb_library(lldbPluginSymbolLocatorDefault PLUGIN + SymbolLocatorDefault.cpp + + LINK_LIBS + lldbCore + lldbHost + lldbSymbol + ) diff --git a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp new file mode 100644 index 000000000000..4ccca5ca0f6a --- /dev/null +++ b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.cpp @@ -0,0 +1,90 @@ +//===-- SymbolLocatorDefault.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 "SymbolLocatorDefault.h" + +#include +#include + +#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" +#include "lldb/Core/Debugger.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/ModuleList.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Progress.h" +#include "lldb/Core/Section.h" +#include "lldb/Host/FileSystem.h" +#include "lldb/Host/Host.h" +#include "lldb/Symbol/LocateSymbolFile.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/Target.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/DataBuffer.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/StreamString.h" +#include "lldb/Utility/Timer.h" +#include "lldb/Utility/UUID.h" + +#include "llvm/ADT/SmallSet.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/ThreadPool.h" + +// From MacOSX system header "mach/machine.h" +typedef int cpu_type_t; +typedef int cpu_subtype_t; + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(SymbolLocatorDefault) + +SymbolLocatorDefault::SymbolLocatorDefault() : SymbolLocator() {} + +void SymbolLocatorDefault::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + GetPluginDescriptionStatic(), CreateInstance, + LocateExecutableObjectFile); +} + +void SymbolLocatorDefault::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +llvm::StringRef SymbolLocatorDefault::GetPluginDescriptionStatic() { + return "Default symbol locator."; +} + +SymbolLocator *SymbolLocatorDefault::CreateInstance() { + return new SymbolLocatorDefault(); +} + +std::optional SymbolLocatorDefault::LocateExecutableObjectFile( + const ModuleSpec &module_spec) { + const FileSpec &exec_fspec = module_spec.GetFileSpec(); + const ArchSpec *arch = module_spec.GetArchitecturePtr(); + const UUID *uuid = module_spec.GetUUIDPtr(); + LLDB_SCOPED_TIMERF( + "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", + exec_fspec ? exec_fspec.GetFilename().AsCString("") : "", + arch ? arch->GetArchitectureName() : "", (const void *)uuid); + + ModuleSpecList module_specs; + ModuleSpec matched_module_spec; + if (exec_fspec && + ObjectFile::GetModuleSpecifications(exec_fspec, 0, 0, module_specs) && + module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) { + ModuleSpec result; + result.GetFileSpec() = exec_fspec; + return result; + } + + return {}; +} diff --git a/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h new file mode 100644 index 000000000000..b1bb58ec2980 --- /dev/null +++ b/lldb/source/Plugins/SymbolLocator/Default/SymbolLocatorDefault.h @@ -0,0 +1,44 @@ +//===-- SymbolLocatorDefault.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 LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEFAULT_SYMBOLLOCATORDEFAULT_H +#define LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEFAULT_SYMBOLLOCATORDEFAULT_H + +#include "lldb/Symbol/SymbolLocator.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class SymbolLocatorDefault : public SymbolLocator { +public: + SymbolLocatorDefault(); + + static void Initialize(); + static void Terminate(); + + static llvm::StringRef GetPluginNameStatic() { return "Default"; } + static llvm::StringRef GetPluginDescriptionStatic(); + + static lldb_private::SymbolLocator *CreateInstance(); + + /// PluginInterface protocol. + /// \{ + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + /// \} + + // Locate the executable file given a module specification. + // + // Locating the file should happen only on the local computer or using the + // current computers global settings. + static std::optional + LocateExecutableObjectFile(const ModuleSpec &module_spec); +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_SYMBOLLOCATOR_DEFAULT_SYMBOLLOCATORDEFAULT_H diff --git a/lldb/source/Symbol/LocateSymbolFile.cpp b/lldb/source/Symbol/LocateSymbolFile.cpp index 66ee7589ac60..b23b53230a4f 100644 --- a/lldb/source/Symbol/LocateSymbolFile.cpp +++ b/lldb/source/Symbol/LocateSymbolFile.cpp @@ -234,29 +234,6 @@ static FileSpec LocateExecutableSymbolFileDsym(const ModuleSpec &module_spec) { return dsym_module_spec.GetSymbolFileSpec(); } -ModuleSpec Symbols::LocateExecutableObjectFile(const ModuleSpec &module_spec) { - ModuleSpec result; - const FileSpec &exec_fspec = module_spec.GetFileSpec(); - const ArchSpec *arch = module_spec.GetArchitecturePtr(); - const UUID *uuid = module_spec.GetUUIDPtr(); - LLDB_SCOPED_TIMERF( - "LocateExecutableObjectFile (file = %s, arch = %s, uuid = %p)", - exec_fspec ? exec_fspec.GetFilename().AsCString("") : "", - arch ? arch->GetArchitectureName() : "", (const void *)uuid); - - ModuleSpecList module_specs; - ModuleSpec matched_module_spec; - if (exec_fspec && - ObjectFile::GetModuleSpecifications(exec_fspec, 0, 0, module_specs) && - module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) { - result.GetFileSpec() = exec_fspec; - } else { - LocateMacOSXFilesUsingDebugSymbols(module_spec, result); - } - - return result; -} - // Keep "symbols.enable-external-lookup" description in sync with this function. FileSpec