-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[lldb] Move LocateExecutableSymbolFile to SymbolLocator plugin #71266
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[lldb] Move LocateExecutableSymbolFile to SymbolLocator plugin #71266
Conversation
This builds on top of the work started in c3a302d to convert LocateSymbolFile to a SymbolLocator plugin. This commit moves LocateExecutableSymbolFile.
@llvm/pr-subscribers-lldb Author: Jonas Devlieghere (JDevlieghere) ChangesThis builds on top of the work started in c3a302d to convert LocateSymbolFile to a SymbolLocator plugin. This commit moves LocateExecutableSymbolFile. Patch is 54.31 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/71266.diff 18 Files Affected:
diff --git a/lldb/include/lldb/Core/PluginManager.h b/lldb/include/lldb/Core/PluginManager.h
index b69aff9e00651bb..50f0662f4bb2b95 100644
--- a/lldb/include/lldb/Core/PluginManager.h
+++ b/lldb/include/lldb/Core/PluginManager.h
@@ -351,6 +351,8 @@ class PluginManager {
SymbolLocatorCreateInstance create_callback,
SymbolLocatorLocateExecutableObjectFile locate_executable_object_file =
nullptr,
+ SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file =
+ nullptr,
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle = nullptr);
static bool UnregisterPlugin(SymbolLocatorCreateInstance create_callback);
@@ -360,6 +362,10 @@ class PluginManager {
static ModuleSpec LocateExecutableObjectFile(const ModuleSpec &module_spec);
+ static FileSpec
+ LocateExecutableSymbolFile(const ModuleSpec &module_spec,
+ const FileSpecList &default_search_paths);
+
static FileSpec FindSymbolFileInBundle(const FileSpec &dsym_bundle_fspec,
const UUID *uuid,
const ArchSpec *arch);
diff --git a/lldb/include/lldb/Symbol/LocateSymbolFile.h b/lldb/include/lldb/Symbol/LocateSymbolFile.h
index 03d3d9a2d440edf..3c0f069c27f8dd6 100644
--- a/lldb/include/lldb/Symbol/LocateSymbolFile.h
+++ b/lldb/include/lldb/Symbol/LocateSymbolFile.h
@@ -24,14 +24,6 @@ class UUID;
class Symbols {
public:
- // Locate the symbol file given a module specification.
- //
- // Locating the file should happen only on the local computer or using the
- // current computers global settings.
- static FileSpec
- LocateExecutableSymbolFile(const ModuleSpec &module_spec,
- const FileSpecList &default_search_paths);
-
// Locate the object and symbol file given a module specification.
//
// Locating the file can try to download the file from a corporate build
diff --git a/lldb/include/lldb/lldb-private-interfaces.h b/lldb/include/lldb/lldb-private-interfaces.h
index faf85833fe9f9e3..4c324a721029075 100644
--- a/lldb/include/lldb/lldb-private-interfaces.h
+++ b/lldb/include/lldb/lldb-private-interfaces.h
@@ -94,6 +94,8 @@ typedef std::optional<ModuleSpec> (*SymbolLocatorLocateExecutableObjectFile)(
const ModuleSpec &module_spec);
typedef std::optional<FileSpec> (*SymbolLocatorFindSymbolFileInBundle)(
const FileSpec &dsym_bundle_fspec, const UUID *uuid, const ArchSpec *arch);
+typedef std::optional<FileSpec> (*SymbolLocatorLocateExecutableSymbolFile)(
+ const ModuleSpec &module_spec, const FileSpecList &default_search_paths);
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 7751fd70dedd730..efed29da0835ebf 100644
--- a/lldb/source/Core/DynamicLoader.cpp
+++ b/lldb/source/Core/DynamicLoader.cpp
@@ -219,7 +219,7 @@ ModuleSP DynamicLoader::LoadBinaryWithUUIDAndAddress(
if (!module_sp) {
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
module_spec.GetSymbolFileSpec() =
- Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+ PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
ModuleSpec objfile_module_spec =
PluginManager::LocateExecutableObjectFile(module_spec);
module_spec.GetFileSpec() = objfile_module_spec.GetFileSpec();
diff --git a/lldb/source/Core/PluginManager.cpp b/lldb/source/Core/PluginManager.cpp
index 85c6b1d948a2d85..810e487f723de06 100644
--- a/lldb/source/Core/PluginManager.cpp
+++ b/lldb/source/Core/PluginManager.cpp
@@ -1089,13 +1089,16 @@ struct SymbolLocatorInstance
llvm::StringRef name, llvm::StringRef description,
CallbackType create_callback,
SymbolLocatorLocateExecutableObjectFile locate_executable_object_file,
+ SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle)
: PluginInstance<SymbolLocatorCreateInstance>(name, description,
create_callback),
locate_executable_object_file(locate_executable_object_file),
+ locate_executable_symbol_file(locate_executable_symbol_file),
find_symbol_file_in_bundle(find_symbol_file_in_bundle) {}
SymbolLocatorLocateExecutableObjectFile locate_executable_object_file;
+ SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file;
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle;
};
typedef PluginInstances<SymbolLocatorInstance> SymbolLocatorInstances;
@@ -1109,10 +1112,11 @@ bool PluginManager::RegisterPlugin(
llvm::StringRef name, llvm::StringRef description,
SymbolLocatorCreateInstance create_callback,
SymbolLocatorLocateExecutableObjectFile locate_executable_object_file,
+ SymbolLocatorLocateExecutableSymbolFile locate_executable_symbol_file,
SymbolLocatorFindSymbolFileInBundle find_symbol_file_in_bundle) {
return GetSymbolLocatorInstances().RegisterPlugin(
name, description, create_callback, locate_executable_object_file,
- find_symbol_file_in_bundle);
+ locate_executable_symbol_file, find_symbol_file_in_bundle);
}
bool PluginManager::UnregisterPlugin(
@@ -1139,6 +1143,20 @@ PluginManager::LocateExecutableObjectFile(const ModuleSpec &module_spec) {
return {};
}
+FileSpec PluginManager::LocateExecutableSymbolFile(
+ const ModuleSpec &module_spec, const FileSpecList &default_search_paths) {
+ auto &instances = GetSymbolLocatorInstances().GetInstances();
+ for (auto &instance : instances) {
+ if (instance.locate_executable_symbol_file) {
+ std::optional<FileSpec> result = instance.locate_executable_symbol_file(
+ module_spec, default_search_paths);
+ if (result)
+ return *result;
+ }
+ }
+ return {};
+}
+
FileSpec PluginManager::FindSymbolFileInBundle(const FileSpec &symfile_bundle,
const UUID *uuid,
const ArchSpec *arch) {
diff --git a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
index 93d8e9bf75f52ea..9af544b31d89649 100644
--- a/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
+++ b/lldb/source/Plugins/Process/MacOSX-Kernel/ProcessKDP.cpp
@@ -278,8 +278,8 @@ Status ProcessKDP::DoConnectRemote(llvm::StringRef remote_url) {
FileSpecList search_paths =
Target::GetDefaultDebugFileSearchPaths();
module_spec.GetSymbolFileSpec() =
- Symbols::LocateExecutableSymbolFile(module_spec,
- search_paths);
+ PluginManager::LocateExecutableSymbolFile(module_spec,
+ search_paths);
if (module_spec.GetSymbolFileSpec()) {
ModuleSpec executable_module_spec =
PluginManager::LocateExecutableObjectFile(module_spec);
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index 63b2c3a0c883097..122ab57e06ad9d7 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -4329,7 +4329,7 @@ const std::shared_ptr<SymbolFileDWARFDwo> &SymbolFileDWARF::GetDwpSymbolFile() {
FileSpecList search_paths = Target::GetDefaultDebugFileSearchPaths();
FileSpec dwp_filespec =
- Symbols::LocateExecutableSymbolFile(module_spec, search_paths);
+ PluginManager::LocateExecutableSymbolFile(module_spec, search_paths);
if (FileSystem::Instance().Exists(dwp_filespec)) {
DataBufferSP dwp_file_data_sp;
lldb::offset_t dwp_file_data_offset = 0;
diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
index 217080bfd3ef3b1..2c57ef8b6a54ea0 100644
--- a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
@@ -65,7 +65,8 @@ SymbolLocatorDebugSymbols::SymbolLocatorDebugSymbols() : SymbolLocator() {}
void SymbolLocatorDebugSymbols::Initialize() {
PluginManager::RegisterPlugin(
GetPluginNameStatic(), GetPluginDescriptionStatic(), CreateInstance,
- LocateExecutableObjectFile, FindSymbolFileInBundle);
+ LocateExecutableObjectFile, LocateExecutableSymbolFile,
+ FindSymbolFileInBundle);
}
void SymbolLocatorDebugSymbols::Terminate() {
@@ -363,3 +364,428 @@ std::optional<FileSpec> SymbolLocatorDebugSymbols::FindSymbolFileInBundle(
return {};
}
+
+static bool FileAtPathContainsArchAndUUID(const FileSpec &file_fspec,
+ const ArchSpec *arch,
+ const lldb_private::UUID *uuid) {
+ ModuleSpecList module_specs;
+ if (ObjectFile::GetModuleSpecifications(file_fspec, 0, 0, module_specs)) {
+ ModuleSpec spec;
+ for (size_t i = 0; i < module_specs.GetSize(); ++i) {
+ bool got_spec = module_specs.GetModuleSpecAtIndex(i, spec);
+ UNUSED_IF_ASSERT_DISABLED(got_spec);
+ assert(got_spec);
+ if ((uuid == nullptr || (spec.GetUUIDPtr() && spec.GetUUID() == *uuid)) &&
+ (arch == nullptr ||
+ (spec.GetArchitecturePtr() &&
+ spec.GetArchitecture().IsCompatibleMatch(*arch)))) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// Given a binary exec_fspec, and a ModuleSpec with an architecture/uuid,
+// return true if there is a matching dSYM bundle next to the exec_fspec,
+// and return that value in dsym_fspec.
+// If there is a .dSYM.yaa compressed archive next to the exec_fspec,
+// call through Symbols::DownloadObjectAndSymbolFile to download the
+// expanded/uncompressed dSYM and return that filepath in dsym_fspec.
+static bool LookForDsymNextToExecutablePath(const ModuleSpec &mod_spec,
+ const FileSpec &exec_fspec,
+ FileSpec &dsym_fspec) {
+ ConstString filename = exec_fspec.GetFilename();
+ FileSpec dsym_directory = exec_fspec;
+ dsym_directory.RemoveLastPathComponent();
+
+ std::string dsym_filename = filename.AsCString();
+ dsym_filename += ".dSYM";
+ dsym_directory.AppendPathComponent(dsym_filename);
+ dsym_directory.AppendPathComponent("Contents");
+ dsym_directory.AppendPathComponent("Resources");
+ dsym_directory.AppendPathComponent("DWARF");
+
+ if (FileSystem::Instance().Exists(dsym_directory)) {
+
+ // See if the binary name exists in the dSYM DWARF
+ // subdir.
+ dsym_fspec = dsym_directory;
+ dsym_fspec.AppendPathComponent(filename.AsCString());
+ if (FileSystem::Instance().Exists(dsym_fspec) &&
+ FileAtPathContainsArchAndUUID(dsym_fspec, mod_spec.GetArchitecturePtr(),
+ mod_spec.GetUUIDPtr())) {
+ return true;
+ }
+
+ // See if we have "../CF.framework" - so we'll look for
+ // CF.framework.dSYM/Contents/Resources/DWARF/CF
+ // We need to drop the last suffix after '.' to match
+ // 'CF' in the DWARF subdir.
+ std::string binary_name(filename.AsCString());
+ auto last_dot = binary_name.find_last_of('.');
+ if (last_dot != std::string::npos) {
+ binary_name.erase(last_dot);
+ dsym_fspec = dsym_directory;
+ dsym_fspec.AppendPathComponent(binary_name);
+ if (FileSystem::Instance().Exists(dsym_fspec) &&
+ FileAtPathContainsArchAndUUID(dsym_fspec,
+ mod_spec.GetArchitecturePtr(),
+ mod_spec.GetUUIDPtr())) {
+ return true;
+ }
+ }
+ }
+
+ // See if we have a .dSYM.yaa next to this executable path.
+ FileSpec dsym_yaa_fspec = exec_fspec;
+ dsym_yaa_fspec.RemoveLastPathComponent();
+ std::string dsym_yaa_filename = filename.AsCString();
+ dsym_yaa_filename += ".dSYM.yaa";
+ dsym_yaa_fspec.AppendPathComponent(dsym_yaa_filename);
+
+ if (FileSystem::Instance().Exists(dsym_yaa_fspec)) {
+ ModuleSpec mutable_mod_spec = mod_spec;
+ Status error;
+ if (Symbols::DownloadObjectAndSymbolFile(mutable_mod_spec, error, true) &&
+ FileSystem::Instance().Exists(mutable_mod_spec.GetSymbolFileSpec())) {
+ dsym_fspec = mutable_mod_spec.GetSymbolFileSpec();
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Given a ModuleSpec with a FileSpec and optionally uuid/architecture
+// filled in, look for a .dSYM bundle next to that binary. Returns true
+// if a .dSYM bundle is found, and that path is returned in the dsym_fspec
+// FileSpec.
+//
+// This routine looks a few directory layers above the given exec_path -
+// exec_path might be /System/Library/Frameworks/CF.framework/CF and the
+// dSYM might be /System/Library/Frameworks/CF.framework.dSYM.
+//
+// If there is a .dSYM.yaa compressed archive found next to the binary,
+// we'll call DownloadObjectAndSymbolFile to expand it into a plain .dSYM
+static bool LocateDSYMInVincinityOfExecutable(const ModuleSpec &module_spec,
+ FileSpec &dsym_fspec) {
+ Log *log = GetLog(LLDBLog::Host);
+ const FileSpec &exec_fspec = module_spec.GetFileSpec();
+ if (exec_fspec) {
+ if (::LookForDsymNextToExecutablePath(module_spec, exec_fspec,
+ dsym_fspec)) {
+ if (log) {
+ LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s",
+ dsym_fspec.GetPath().c_str());
+ }
+ return true;
+ } else {
+ FileSpec parent_dirs = exec_fspec;
+
+ // Remove the binary name from the FileSpec
+ parent_dirs.RemoveLastPathComponent();
+
+ // Add a ".dSYM" name to each directory component of the path,
+ // stripping off components. e.g. we may have a binary like
+ // /S/L/F/Foundation.framework/Versions/A/Foundation and
+ // /S/L/F/Foundation.framework.dSYM
+ //
+ // so we'll need to start with
+ // /S/L/F/Foundation.framework/Versions/A, add the .dSYM part to the
+ // "A", and if that doesn't exist, strip off the "A" and try it again
+ // with "Versions", etc., until we find a dSYM bundle or we've
+ // stripped off enough path components that there's no need to
+ // continue.
+
+ for (int i = 0; i < 4; i++) {
+ // Does this part of the path have a "." character - could it be a
+ // bundle's top level directory?
+ const char *fn = parent_dirs.GetFilename().AsCString();
+ if (fn == nullptr)
+ break;
+ if (::strchr(fn, '.') != nullptr) {
+ if (::LookForDsymNextToExecutablePath(module_spec, parent_dirs,
+ dsym_fspec)) {
+ if (log) {
+ LLDB_LOGF(log, "dSYM with matching UUID & arch found at %s",
+ dsym_fspec.GetPath().c_str());
+ }
+ return true;
+ }
+ }
+ parent_dirs.RemoveLastPathComponent();
+ }
+ }
+ }
+ dsym_fspec.Clear();
+ return false;
+}
+
+static int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
+ ModuleSpec &return_module_spec) {
+ Log *log = GetLog(LLDBLog::Host);
+ if (!ModuleList::GetGlobalModuleListProperties().GetEnableExternalLookup()) {
+ LLDB_LOGF(log, "Spotlight lookup for .dSYM bundles is disabled.");
+ return 0;
+ }
+
+ 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 items_found;
+ }
+
+ if (uuid && uuid->IsValid()) {
+ // Try and locate the dSYM file using DebugSymbols first
+ llvm::ArrayRef<uint8_t> module_uuid = uuid->GetBytes();
+ if (module_uuid.size() == 16) {
+ CFCReleaser<CFUUIDRef> 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<CFURLRef> 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<CFURLRef> 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 = PluginManager::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<CFDictionaryRef> 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<CFDictionaryRef>(
+ ::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;
+ ...
[truncated]
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🚢
This builds on top of the work started in c3a302d to convert LocateSymbolFile to a SymbolLocator plugin. This commit moves LocateExecutableSymbolFile.